CoderCastrov logo
CoderCastrov
Парсер

Искусство не попадать в блокировку: Как я использовал Selenium и Python для парсинга Facebook и Tiktok

Искусство не попадать в блокировку: Как я использовал Selenium и Python для парсинга Facebook и Tiktok
просмотров
5 мин чтение
#Парсер

Не так давно было невероятно легко получить данные пользователей Facebook. Graph API был решением, которое позволяло программистам получать доступ к общедоступным данным пользователей/страниц с определенной степенью свободы. Однако, с падением Cambridge Analytica и увеличением важности конфиденциальности данных, эта реальность изменилась. Facebook сделал невозможным массовое сбор данных пользователей.

Tiktok (ранее известный как Musically) также решил не предоставлять никаких законных средств для сбора своих данных. Он серьезно заботится о конфиденциальности своих (в основном) подростковых пользователей и стремится обеспечить, чтобы платформа не создавала возможности для хищнического сбора данных.

В этом руководстве я буду использовать Python для настройки драйвера Selenium. Более важно, я поделюсь с вами ценными правилами, которые помогут вам избежать блокировки со стороны администраторов систем Facebook/Tiktok.

Во-первых, давайте обсудим, почему нам нужен Selenium.

Selenium: Симулятор браузера

Если мы попытаемся сделать обычный GET-запрос (с помощью cUrl/urlib/requests) на Facebook или Tiktok, мы получим только частичный HTML-домен. Некоторые элементы будут отсутствовать, в основном из тега <body>.

Facebook и Tiktok основаны на JavaScript, и urllib не знает, как парсить их.

Selenium откроет Chrome (или Firefox, если вы хотите), перейдет по нужному URL-адресу, подождет, пока загрузится JavaScript, и только после этого получит и вернет HTML.

Теперь давайте перейдем к коду.

Выше приведены импорты, которые мы будем использовать. Вам потребуется установить следующие зависимости Python:

Также вам потребуется установить Chrome на своем компьютере.

Я начинаю новый класс с именем Request, который будет полезен, если у вас есть разные типы запросов в вашем алгоритме.

logger - это просто версия функции print() в Python, которая записывает логи в stderr. Вы можете игнорировать это!

Переменная selenium retries поможет нам отслеживать количество неудачных попыток выполнения запроса с помощью Selenium. Поверьте мне, это будет важно, учитывая, что мы имеем дело с Facebook/Tiktok.

Погружение в функцию get_selenium_res():

the get_selenium_res() function 1/2

Вначале мы настраиваем переменные для User-Agent, используя внешнюю зависимость random_user_agent, которую я импортировал, чтобы автоматически получать случайный User-Agent для каждого вызова selenium.

User-Agent выглядит примерно так: Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36

Представьте его как средство, с помощью которого вы, как пользователь, получаете доступ к сайту; идентификатор. Помните, что мы здесь не для того, чтобы быть пойманными при парсинге данных, поэтому мы будем притворяться разными User-Agent при каждом новом запросе.

Наконец, я настраиваю chrome_options. Они будут использоваться позже, когда мы объявим экземпляр браузера selenium.

Chrome-Options: аргумент за аргументом

Как использовать прокси

функция get_selenium_res() 2/2

Выше приведен фрагмент кода, который относится к использованию прокси. Позже я расскажу, действительно ли использование прокси будет полезным в нашем случае:

Однако настройка прокси в селениуме не очень хорошо освещена в Интернете. Давайте разберемся вместе:

Сначала настройте переменную PROXY. Вы можете получить бесплатную прокси отсюда ссылка. Случайная прокси выглядит примерно так: "http://123.45.678.21:8080" ("http://IP:PORT"). Убедитесь, что вы получаете активную прокси с поддержкой https.

Местоположение бинарного файла было настроено для указания Chrome правильного расположения драйвера на моем локальном диске. Вы можете столкнуться с "ошибкой", если эта переменная не объявлена. Это не связано с использованием прокси, я включаю это, так как это может вызвать проблемы.

Затем я создаю экземпляр объекта Proxy(). Я настраиваю его на ручной режим и также устанавливаю флаг autodetect в False, чтобы убедиться, что мы не объявляем миру, что мы используем ручной прокси. Затем я устанавливаю настройки прокси http и ssl равными переменной PROXY, которую мы ранее объявили. В качестве последнего шага я должен добавить эти возможности к экземпляру Proxy() и настройка завершена.

Последнее слово по поводу прокси: если вы собираетесь использовать провайдера прокси, используйте того, который позволит вам добавить в белый список ваш локальный IP и запросить случайную прокси без ввода имени пользователя и пароля через селениум. Smartproxy рекомендуется по этой причине. Установите переменную PROXY равной адресу хоста:порта прокси-вращающегося API.

Запуск веб-браузера

Вы можете легко переключить использование прокси, изменив способ инициализации нового экземпляра браузера:

# **browser** = webdriver.Chrome(**chrome_options**=chrome_options,
#                            **desired_capabilities**=capabilities)
  **browser** = webdriver.Chrome(**chrome_options**=chrome_options)

Обратите внимание, что я инициирую браузер без прокси по причинам, о которых я расскажу позже в этом руководстве.

Использование браузера Selenium

Если вы используете прокси, вам может понадобиться протестировать его работу.

Используйте:

# при тестировании прокси
browser.**get**('[http://lumtest.com/myip.json](http://lumtest.com/myip.json)')

Вышеуказанный адрес вернет json с местоположением, которое вы имитируете. Если настройка прокси была неудачной, вы увидите текущий (реальный) IP-адрес вашего компьютера.

Мы отправим GET-запрос по URL, для которого мы создали объект Request...

browser.**get**(self.url)

Если вы не работаете в режиме без головы, то вышеуказанная строка фактически откроет окно браузера на вашем компьютере и перейдет по желаемому URL-адресу.

Пока все хорошо? Теперь становится немного интереснее:

В этом руководстве мы будем использовать явное ожидание, которое я считаю "лучшей практикой", когда это возможно. Это означает, что Chrome не закроется и не вернет нам DOM, пока не будет отрисован определенный элемент. presence_if_element_located((By.CLASS_NAME, class_name)) - это наш способ указать браузеру ждать, пока элемент с указанным классом не будет отрисован.

ОЧЕНЬ ВАЖНО: class_name - это переменная, которую нужно передать в метод запроса. В этом примере вы можете передать строку с именем класса, на котором вы хотите подождать, например: Request('www.facebook.com').get_selenium_res('name_of_class')

Как только этот элемент будет отрисован, я приказываю браузеру максимизировать окно (мы уже настроили это в настройках Chrome - но здесь я показываю еще один способ сделать это), чтобы получить полностью DOM.

browser.page_source - это команда, используемая для получения и сохранения в памяти HTML.

Не забудьте закрыть браузер с помощью browser.close().

Обработка исключений

Исключение Timeout Exception возникает, когда запрос Selenium не может получить ответ в установленный временной интервал (time_to_wait). Это классическая блокировка. Если с URL, который вы указали, все в порядке, это может быть сигналом того, что были активированы автоматические брандмауэры, чтобы предотвратить сбор данных.

Исключение WebDriverException в основном возникает на Unix-машине, которую я настроил для продакшена. Это исключение НЕ является результатом блокировки Facebook/Tiktok.

Если возникает исключение, я просто возвращаю ту же функцию get_selenium_res (создавая потенциальную бесконечную петлю сбоев Selenium)... Я настроил это так, потому что я знаю, что Facebook/Tiktok заблокируют меня, и я хотел бы автоматически повторить попытку. Повторная попытка GET-запроса иногда может сработать.

Теперь, когда у вас есть техническая возможность делать GET-запросы с помощью Selenium, позвольте мне поделиться некоторыми чрезвычайно ценными знаниями из моего опыта парсинга Tiktok и Facebook в пост-камбрийскую эпоху Аналитики.

Facebook и Tiktok: (избегая) блокировки

Facebook и Tiktok активно ищут парсеров данных. Они не просто проверяют user-agent и IP-адрес, чтобы найти нас "парсеров". Вот несколько выводов:

Не стесняйтесь поделиться своими опытами парсинга с использованием Selenium.