Загружаем модули и библиотеки, необходимые для работы:
import requests
import time
import pandas as pd
Для начала давайте посмотрим на документацию API и посмотрим, как к нему формировать запросы: https://dev.vk.com/api/api-requests.
В прошлый раз по инструкции мы получили доступ к API, вспомним шаги.
# вводим id своего приложения
# и проходим по ссылке с этим id
app_id = input("Enter your client id: ")
url = f"https://oauth.vk.com/authorize?client_id={app_id}&display=page&redirect_uri=http://oauth.vk.com/blank.html&scope=all&response_type=token"
print(url)
# копируем токен доступа
token = input("Enter your token here: ")
На этом практическом занятии мы будем выгружать посты из сообщества Цитатник ВШЭ. Сохраним в переменные версию API, ссылку для метода работы со стеной сообщества и название сообщества:
v = "5.131"
main_wall = "https://api.vk.com/method/wall.get"
domain = "hseteachers"
Функция get()
из библиотеки requests
умеет подставлять в запрос необходимые параметры и объединять их с помощью ?
и &
. Сохраним необходимые параметры в виде словаря:
params_wall = {"access_token" : token,
"domain" : domain,
"count" : 100,
"v" : v}
А теперь сформируем запрос и выгрузим результаты в формате JSON – в Python данные в таком формате будут представлены в виде словаря:
req_wall = requests.get(main_wall, params = params_wall)
json_wall = req_wall.json()
# json_wall
Извлечём из этого большого словаря элемент, который хранит непосредственно результаты – список из маленьких словарей с информацией о постах (1 словарь = 1 пост):
items_wall = json_wall['response']['items']
Посмотрим на один элемент такого списка:
i = items_wall[0]
i
Поработаем с ним!
Извлечь из элемента i
следующие компоненты:
# YOUR CODE HERE
Напишите функцию get_posts()
, которая принимает на вход словарь, аналогичный сохранённому в i
, и возвращает список из следующих характеристик:
# YOUR CODE HERE
Примените функцию get_posts()
ко всем элементам списка items_wall
и сохраните полученные результаты в список posts
.
# YOUR CODE HERE
Прочитайте в документации к API ВКонтакте про аргумент offset
в методе wall.get
. Используя полученную информацию и блоки кода ниже, выгрузите и сохраните в список items_more
данные по всем постам на стене сообщества.
Подсказка: чтобы расширять список правильным образом, используйте метод .extend()
, а не .append()
, он добавляет не один элемент, а сразу несколько (см. примеры ниже).
# с append()
A = []
for i in range(5):
B = [1, 2, 3]
A.append(B)
print(A)
# с extend()
A = []
for i in range(5):
B = [1, 2, 3]
A.extend(B)
print(A)
params_wall_long = {"access_token" : token,
"domain" : domain,
"count" : 100,
"offset" : 100,
"v" : v}
# CHANGE CODE HERE
items_more = []
req_wall_long = requests.get(main_wall, params = params_wall_long)
json_wall_long = req_wall_long.json()
items_wall_long = json_wall_long['response']['items']
Теперь извлечём из каждого элемента items_more
нужную информацию и расширим список posts
, который у нас уже был до этого:
for i in items_more:
p = get_posts(i)
posts.append(p)
len(posts) # все идёт по плану
Преобразуем результат в датафрейм, добавим названия столбцов:
dat = pd.DataFrame(posts)
dat.columns = ["id", "timestamp", "post", "likes",
"reposts", "views", "comments"]
Несколько строк датафрейма для примера:
dat.head()
Разобьём текст поста по #
, чтобы извлечь тэги:
with_tags = dat["post"].str.split("#", expand = True)
with_tags
Основная информация – это первые два тэга, имя преподавателя и курс (по крайней мере, в большинстве случаев это так). Заберём для дальнейшей работы только их:
small = with_tags.loc[:, 0:2]
small.columns = ["text", "teacher", "course"]
Склеим датафрейм dat
с датафреймом small
по столбцам:
final = pd.concat([dat, small], axis = 1)
Заполним пропуски – добавим «пустой» текст в ячейки, где нет никаких значений:
final = final.fillna("")
Избавимся от лишних пробелов и отступов в текстовых данных:
final["text"] = final["text"].apply(lambda x: x.strip())
final["teacher"] = final["teacher"].apply(lambda x: x.strip())
final["course"] = final["course"].apply(lambda x: x.strip())
Осталось поработать с форматом времени в столбце timestamp
.
final["timestamp"]
t = final["timestamp"][0]
t
Импортируем из модуля datetime
функцию datetime
, она поможет нам получить дату и время в привычном формате:
from datetime import datetime
datetime.utcfromtimestamp(t)
datetime.utcfromtimestamp(t).strftime('%Y-%m-%d %H:%M:%S')
Напишем функцию для преобразования временной метки:
def time_transform(t):
r = datetime.fromtimestamp(t).strftime('%Y-%m-%d %H:%M:%S')
return r
Применим её ко всем элементам столбца:
final["datetime"] = final["timestamp"].apply(time_transform)
Теперь можем разбить дату-время по пробелу, чтобы получить отдельные столбцы с датой и временем (механизм нам уже известен, мы разбивали пост по #
выше):
dt = final["datetime"].str.split(" ", expand = True)
dt.columns = ["date", "time"]
final = pd.concat([final, dt], axis = 1)