Найти в Дзене
Евгений Шуравин

Граббим Дзен

В одной из предыдущий статей , на примере сайта столото, я описал как можно в автоматическим режиме получить данные с сайта и обработать их. Но вот беда, подобный прямолинейный подход не сработает с любым сайтом. Многие современные сайты используют технологию JavaScript - сайт интерактивен и взаимодействует с пользователем. Возьмем тот же Дзен - он не показывает все карточки канала сразу. Но когда мы прокручиваем страницу вниз, новые карточки подгружаются автоматически. И так может быть очень долго, практически бесконечно, если канал большой. Это работает JavaScript. Этот скрипт по прокрутке до конца страницы запрашивает сервер и подгружает еще карточки. Технология, если не ошибаюсь называется Ajax, но я, если честно не особо в этом разбираюсь. Не суть важно, важно то что страница формируется динамически. К сожалению, Python не может выполнить JavaScript и получить динамически сформированную страницу, поэтому с помощью requests мы получим только карточки с первого экрана. Но выход ест

В одной из предыдущий статей , на примере сайта столото, я описал как можно в автоматическим режиме получить данные с сайта и обработать их. Но вот беда, подобный прямолинейный подход не сработает с любым сайтом. Многие современные сайты используют технологию JavaScript - сайт интерактивен и взаимодействует с пользователем. Возьмем тот же Дзен - он не показывает все карточки канала сразу. Но когда мы прокручиваем страницу вниз, новые карточки подгружаются автоматически. И так может быть очень долго, практически бесконечно, если канал большой. Это работает JavaScript. Этот скрипт по прокрутке до конца страницы запрашивает сервер и подгружает еще карточки. Технология, если не ошибаюсь называется Ajax, но я, если честно не особо в этом разбираюсь. Не суть важно, важно то что страница формируется динамически. К сожалению, Python не может выполнить JavaScript и получить динамически сформированную страницу, поэтому с помощью requests мы получим только карточки с первого экрана.

Но выход есть! Библиотека Selenium позволяет использовать обычный браузер, который умеет выполнять JavaScript. В пакет Анаконда Selenium не включен, поэтому сначала надо его установить командой

!pip install Selenium

Также понадобится драйвер браузера, например для FireFox это geckodriver.exe - я просто положил его в папку со скриптом.

Итак, после того как необходимые установки сделаны, напишем скрипт:

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
SCROLL_PAUSE_TIME = 5
max_count_scroll = 200
count = 0
url = "https://zen.yandex.ru/chanel"

Здесь загружаются нужные библиотеки и инициализируются переменные. url содержит адрес, который и будем исследовать - подставьте вместо channel конкретный канал Дзена.

driver = webdriver.Firefox()
driver.get(url)

активируем драйвер и получаем страничку. Пока только те карточки, что видны на начальном экране.

last_height = driver.execute_script("return document.body.scrollHeight")

получаем высоту окна браузера в пикселах. (по сути дела мы даем команду браузеру выполнить JavaScript, который возвращает текущую высоту содержимого браузера).

И вот дальше - самое интересное:

while True:
count +=1
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(SCROLL_PAUSE_TIME)
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height or count>max_count_scroll :
break
last_height = new_height

Мы в цикле даем команду браузеру прокрутить содержимое вниз, подождать 5 секунд.... в это время скрипт Дзена догрузит еще карточки... и мы запрашиваем новое значение высоты окна браузера. Если оно не равно старому, то карточки подгрузились и мы повторяем цикл вновь и вновь. А если равно, значит карточек больше нет, и можно выйти из цикла. Переменная count содержит количество скроллов, статей в дзене немеряно, некоторые каналы возможно листать бесконечно, поэтому еще одно условие выхода - количество листаний достигло максимума.

outs = driver.page_source
driver.close()

ну и под конец получаем код страницы и закрываем драйвер (браузер). Код страницы со всеми карточками у нас в переменной outs.

Что можно сделать с этой страничкой? Точно так же "скормить" её BeautifulSoup и например извлечь ссылки на статьи:

from bs4 import BeautifulSoup
import re
soup = BeautifulSoup(t, 'html.parser')
texts = []
for link in soup.find_all('a'):
l = link.get('href')
if 'comments_data=p_root' not in l:
s = re.search(r'https://zen.yandex.ru/media[^?]*', l)
if s != None:
texts.append(s[0])
print(len(texts))

в списке texts мы получим список всех ссылок на статьи канала. На самом деле в карточке есть две ссылки, одна на саму статью, вторая на комментарии. Ссылки на комментарии содержат строку " comments_data=p_root ", мы записываем только те ссылки, что не содержат эту строку. Кроме того ссылка слишком длинная, после знака ? в url передаются разные параметры, которые нам в принципе не нужны, поэтому просто отрезаем их с помощью регулярного выражения. К сожалению больше ничего полезного получить с этой странице не удалось, разве что название статьи и количество комментариев. Для того чтобы получить подробную статистику канала потребуется в цикле загружать все страницы. Там можно будет получить количество дочитываний, количество показов, комментарии, темы публикации, да и сам текст.

Есть конечно опасения, что дзену это не очень понравится, но с другой стороны, мы будем загружать страницы быстро, например будем делать паузу в пять секунд, чтобы страница успела отработать JavaScript: PAUSE_TIME = 5 , каких-то обвинений в накрутке посещаемости не должно быть, поскольку дзен учитывает дочитки только длиннее 45 секунд.