Скрапинг сайтов с JavaScript на Python

Языки клиентской стороны — это языки, которые выполняются в браузере, а не на веб-сервере. Успех языка клиентской стороны зависит от способности вашего браузера правильно интерпретировать и выполнять этот язык. (Вот почему так легко отключить JavaScript в вашем браузере.)

Частично из-за сложности добиться согласия всех производителей браузеров по стандартам, языков клиентской стороны намного меньше, чем языков серверной стороны. Это хорошо, когда дело доходит до веб-скрапинга: чем меньше языков, с которыми нужно работать, тем лучше.

В основном вы часто сталкиваетесь онлайн только с двумя языками: ActionScript (который используется в приложениях Flash) и JavaScript. ActionScript сегодня используется гораздо реже, чем 10 лет назад, и часто используется для потоковой передачи мультимедийных файлов, как платформа для онлайн-игр или для отображения приветственных страниц для веб-сайтов, которые не поняли, что никто не хочет смотреть приветственные страницы. В любом случае, поскольку нет большого спроса на скрапинг Flash-страниц, эта глава вместо этого фокусируется на языке клиентской стороны, который повсеместно присутствует на современных веб-страницах: JavaScript.

JavaScript — это, безусловно, самый распространенный и хорошо поддерживаемый язык сценариев на стороне клиента в современном интернете. Его можно использовать для сбора информации для отслеживания пользователей, отправки форм без перезагрузки страницы, встраивания мультимедиа и даже для создания целых онлайн-игр. Даже на вид простые страницы часто содержат несколько фрагментов JavaScript. Вы можете найти его встроенным между тегами script в исходном коде страницы:

<script>
alert("Код создает всплывающее окно с помощью JavaScript");
</script>

Введение в JavaScript

Знание хотя бы некоторых основ JavaScript может быть чрезвычайно полезным при работе с кодом, который вы скрапите. С этой целью хорошо бы ознакомиться с JavaScript.

JavaScript — это язык с слабой типизацией, с синтаксисом, который часто сравнивают с C++ и Java. Хотя некоторые элементы синтаксиса, такие как операторы, циклы и массивы, могут быть схожими, слабая типизация и скриптоподобная природа языка могут сделать его непростым для понимания для некоторых программистов.

Например, следующий код рекурсивно вычисляет значения в последовательности Фибоначчи и выводит их в консоль разработчика браузера:

<script>
function fibonacci(a, b){
var nextNum = a + b;
console.log(nextNum+" is in the Fibonacci sequence");
if(nextNum < 100){
fibonacci(b, nextNum);
}
}
fibonacci(1, 1);
</script>

Обратите внимание, что все переменные определяются с использованием ключевого слова var. Это похоже на знак $ в PHP или на объявление типа (int, String, List и т. д.) в Java или C++. Python в этом отношении необычен, поскольку у него нет такого явного объявления переменных.

JavaScript также отлично подходит для передачи функций так же, как и переменных:

<script>
var fibonacci = function() {
var a = 1;
var b = 1;
return function () {
var temp = b;
b = a + b;
a = temp;
return b;
}
}
var fibInstance = fibonacci();
console.log(fibInstance()+" is in the Fibonacci sequence");
console.log(fibInstance()+" is in the Fibonacci sequence");
console.log(fibInstance()+" is in the Fibonacci sequence");
</script>

Код может показаться сложным на первый взгляд, но становится проще, если думать в терминах лямбда-выражений. Переменная fibonacci определяется как функция. Значение этой функции возвращает функцию, которая выводит все большие значения в последовательности Фибоначчи. Каждый раз, когда она вызывается, она возвращает функцию, вычисляющую Фибоначчи, которая снова выполняется и увеличивает значения в функции.

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

Известные библиотеки JavaScript

Хотя знание основного языка JavaScript важно, на современном вебе нельзя пройти далеко без использования хотя бы одной из множества сторонних библиотек языка. Вы, возможно, увидите одну или несколько из этих часто используемых библиотек, когда будете изучать исходный код страницы.

Выполнение JavaScript с использованием Python может быть крайне затратным по времени и процессорному ресурсу, особенно если вы делаете это в больших масштабах. Знание JavaScript и умение его разбирать напрямую (без необходимости выполнения для получения информации) может быть чрезвычайно полезным и сэкономить вам много головной боли.

jQuery

jQuery — крайне распространенная библиотека, используемая 70% самых популярных сайтов интернета и примерно 30% остальных. Сайт, использующий jQuery, легко идентифицируется, потому что он содержит импорт jQuery где-то в своем коде:

<a href="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js</a>

Если jQuery найден на сайте, нужно быть осторожным при его скрапинге. jQuery умеет динамически создавать HTML-контент, который появляется только после выполнения JavaScript. Если вы скрапите содержимое страницы с использованием традиционных методов, вы получите только предварительно загруженную страницу, которая появляется до того, как JavaScript создаст контент (эта проблема скрапинга рассматривается подробнее в разделе «Ajax и динамический HTML» ).

Кроме того, на таких страницах чаще всего присутствуют анимации, интерактивный контент и встроенные медиа-файлы, что может сделать скрапинг сложным.

Google Analytics

Google Analytics используется примерно на 50% всех веб-сайтов, что, возможно, делает его самой распространенной библиотекой JavaScript и наиболее популярным инструментом отслеживания пользователей в Интернете. Как http://pythonscraping.com, так и http://www.oreilly.com используют Google Analytics.

Определить, использует ли страница Google Analytics, легко. На ней будет JavaScript внизу, аналогичный следующему (взятый с сайта O’Reilly Media):

<!-- Google Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-4591498-1']);
_gaq.push(['_setDomainName', 'oreilly.com']);
_gaq.push(['_addIgnoredRef', 'oreilly.com']);
_gaq.push(['_setSiteSpeedSampleRate', 50]);
_gaq.push(['_trackPageview']);
(function() { var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true; ga.src = ('https:' ==
document.location.protocol ? 'https://ssl' : 'http://www') +
'.google-analytics.com/ga.js'; var s =
document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s); })();
</script>

Этот скрипт обрабатывает специфические для Google Analytics файлы cookie, используемые для отслеживания вашего посещения со страницы на страницу. Это иногда может стать проблемой для веб-скраперов, предназначенных для выполнения JavaScript и обработки файлов cookie (таких как те, которые используют Selenium, о котором будет рассказано позже в этой главе).

Если сайт использует Google Analytics или подобную систему веб-аналитики, и вы не хотите, чтобы сайт знал, что его сканируют или скрейпят, убедитесь, что вы удаляете все файлы cookie, используемые для аналитики, или вообще отказываетесь от файлов cookie.

Google Maps

Если вы провели хотя бы немного времени в Интернете, вы почти наверняка видели встроенные в веб-сайт карты Google Maps. Его API делает крайне простым встраивание карт с настраиваемой информацией на любом сайте.

Если вы скрапите какие-либо данные о местоположении, понимание того, как работает Google Maps, делает легким получение хорошо отформатированных координат широты/долготы и даже адресов. Одним из наиболее распространенных способов обозначения местоположения в Google Maps является маркер (также известный как штырь).

Маркеры могут быть вставлены в любую карту Google с помощью кода, подобного следующему:

var marker = new google.maps.Marker({
    position: new google.maps.LatLng(-25.363882, 131.044922),
    map: map,
    title: 'Some marker text'
});

Python делает легким извлечение всех экземпляров координат, которые встречаются между google.maps.LatLng( и ) для получения списка координат широты/долготы.

Используя API обратного геокодирования Google, вы можете преобразовать эти пары координат в адреса, которые хорошо форматированы для хранения и анализа.

AJAX и Dynamic HTML

До сих пор единственным способом общения с веб-сервером, который у нас был, было отправка ему какого-то HTTP-запроса путем извлечения новой страницы. Если вы когда-либо отправляли форму или получали информацию с сервера без перезагрузки страницы, вероятно, вы использовали веб-сайт, который использует Ajax.

Вопреки некоторым мнениям, Ajax не является языком, а группой технологий, используемых для выполнения определенной задачи (очень похоже на веб-скрапинг, если подумать). Ajax означает «Асинхронный JavaScript и XML» и используется для отправки информации на веб-сервер и получения ее оттуда без выполнения отдельного запроса на страницу.

Вы никогда не должны говорить: «Этот веб-сайт будет написан на Ajax.» Правильно будет сказать: «Эта форма будет использовать Ajax для общения с веб-сервером».

Подобно Ajax, динамический HTML (DHTML) — это набор технологий, используемых для общей цели. DHTML представляет собой HTML-код, язык CSS или оба того, которые изменяются по мере изменения HTML-элементов на странице сценариями на стороне клиента. Кнопка может появиться только после перемещения пользователем курсора, цвет фона может измениться при щелчке мыши, или запрос Ajax может вызвать загрузку нового блока контента.

Следует отметить, что хотя слово «динамический» обычно ассоциируется с такими словами, как «движущийся» или «изменяющийся», наличие интерактивных компонентов HTML, движущихся изображений или встроенных мультимедийных элементов не обязательно делает страницу DHTML, хотя она может выглядеть динамично. Кроме того, некоторые из самых скучных, статически выглядящих страниц в интернете могут иметь процессы DHTML, работающие в фоновом режиме, которые зависят от использования JavaScript для манипуляции HTML и CSS.

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

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

Оба этих случая вызваны невозможностью вашего скрейпера выполнить JavaScript, который осуществляет волшебство на странице. Без JavaScript HTML просто стоит на месте, и сайт может выглядеть совершенно иначе, чем в вашем веб-браузере, который исполняет JavaScript без проблем.

Есть несколько признаков того, что страница может использовать Ajax или DHTML для изменения/загрузки контента, но в таких ситуациях есть только два решения: скрапить контент напрямую из JavaScript; или использовать пакеты Python, способные выполнять JavaScript самостоятельно, и скрапить веб-сайт, просматривая его в вашем браузере.

Запуск JavaScript в Python с помощью Selenium

Селениум — мощный инструмент для веб-скрапинга, изначально разработанный для тестирования веб-сайтов. В наши дни его также используют, когда требуется точное воспроизведение веб-сайтов так, как они отображаются в браузере. Селениум работает путем автоматизации браузеров для загрузки веб-сайта, получения необходимых данных, а также создания снимков экрана или проверки, что на веб-сайте происходят определенные действия.

Селениум не содержит собственного веб-браузера; он требует интеграции с браузерами сторонних производителей для работы. Если вы запустите селениум с Firefox, например, то увидите, что на вашем экране открывается экземпляр Firefox, переходит на веб-сайт и выполняет действия, указанные в коде. Хотя это может быть здорово смотреться, я предпочитаю, чтобы мои сценарии выполнялись тихо на заднем плане, поэтому я использую инструмент под названием PhantomJS вместо реального браузера.

PhantomJS — это так называемый браузер без интерфейса. Он загружает веб-сайты в память и выполняет JavaScript на странице, но не отображает веб-сайт графически пользователю. Сочетая селениум с PhantomJS, вы можете запускать очень мощный веб-скрейпер, который легко обрабатывает куки, JavaScript, заголовки и все остальное, что вам нужно.

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

PhantomJS можно загрузить с его веб-сайта. Поскольку PhantomJS является полноценным (хотя и бесшумным) браузером, а не библиотекой Python, для его использования требуется загрузка и установка, и он не может быть установлен с помощью pip.

Хотя многие страницы используют Ajax для загрузки данных (в частности Google), есть тестовая страница по адресу http://pythonscraping.com/pages/javascript/ajaxDemo.html для запуска ваших скрейперов. Эта страница содержит некоторый образец текста, зафиксированный в HTML-коде страницы, который заменяется Ajax-сгенерированным контентом после двухсекундной задержки. Если бы вы скрейпили данные этой страницы с помощью традиционных методов, вы получили бы только страницу загрузки без данных, которые вам нужны.

Библиотека Selenium — это API, вызываемое на объекте WebDriver. WebDriver немного похож на браузер в том смысле, что он может загружать веб-сайты, но его также можно использовать как объект BeautifulSoup для поиска элементов страницы, взаимодействия с элементами на странице (отправка текста, клик и т. д.) и выполнения других действий для управления веб-скрейперами.

Следующий код получает текст за Ajax «стеной» на тестовой странице:

from selenium import webdriver
import time
driver = webdriver.PhantomJS(executable_path='<Путь к PhantomJS>')
driver.get('http://pythonscraping.com/pages/javascript/ajaxDemo.html')
time.sleep(3)
print(driver.find_element_by_id('content').text)
driver.close()

Селекторы Selenium

В предыдущих разделах, вы выбирали элементы страницы, используя селекторы BeautifulSoup, такие как find и find_all. Selenium использует совершенно новый набор селекторов для поиска элемента в DOM WebDriver, хотя они имеют довольно простые имена.

В примере вы использовали селектор find_element_by_id, хотя также могли бы сработать следующие селекторы:

driver.find_element_by_css_selector('#content')
driver.find_element_by_tag_name('div')

Конечно, если вы хотите выбрать несколько элементов на странице, большинство этих селекторов элементов могут вернуть список элементов Python, добавив elements (то есть сделав его во множественном числе):

driver.find_elements_by_css_selector('#content')
driver.find_elements_by_css_selector('div')

Если вы все еще хотите использовать BeautifulSoup для анализа этого контента, вы можете это сделать, используя функцию page_source WebDriver, которая возвращает исходный код страницы, просмотренный DOM на данный момент времени, как строку:

pageSource = driver.page_source
bs = BeautifulSoup(pageSource, 'html.parser')
print(bs.find(id='content').get_text())

Этот код создает новый Selenium WebDriver, используя библиотеку PhantomJS, которая указывает WebDriver загрузить страницу, а затем приостановить выполнение на три секунды перед анализом страницы для извлечения (надеюсь, загруженного) содержимого. В зависимости от места установки PhantomJS вам также может потребоваться явно указать Selenium правильное направление при создании нового WebDriver для PhantomJS:

driver = webdriver.PhantomJS(executable_path='path/to/driver/'\
'phantomjs-1.9.8-macosx/bin/phantomjs')

Если все настроено правильно, скрипт должен занять несколько секунд на выполнение, а затем привести к следующему тексту:

«Вот некоторый важный текст, который вы хотите получить! Кнопка для нажатия!»

Обратите внимание, что хотя на самой странице присутствует HTML-кнопка, функция .text Selenium извлекает текстовое значение кнопки так же, как и все остальное содержимое на странице. Если паузу time.sleep изменить на одну секунду вместо трех, возвращаемый текст изменится на оригинальный:

«Это некоторый контент, который появится на странице во время ее загрузки. Вам не нужно скрейпить это.»

Хотя это решение работает, оно несколько неэффективно, и его реализация может вызвать проблемы при масштабном использовании. Время загрузки страницы неустойчиво и зависит от загрузки сервера в любую конкретную миллисекунду, а также происходят естественные колебания скорости подключения. Хотя эта загрузка страницы должна занять немного больше двух секунд, вы предоставляете ей целых три секунды, чтобы убедиться, что она загружается полностью. Более эффективным решением было бы повторное проверка наличия конкретного элемента на полностью загруженной странице и возврат только тогда, когда этот элемент существует.

Этот код использует наличие кнопки с ID loadedButton для объявления о том, что страница полностью загружена:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.PhantomJS(executable_path='')
driver.get('http://pythonscraping.com/pages/javascript/ajaxDemo.html')

try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, 'loadedButton')))
finally:
    print(driver.find_element_by_id('content').text)
    driver.close()

Этот скрипт имеет несколько новых импортов, в основном WebDriverWait и expected_conditions, которые вместе формируют то, что Selenium называет неявным ожиданием.

Неявное ожидание отличается от явного ожидания тем, что оно ожидает наступления определенного состояния в DOM перед продолжением выполнения, в то время как явное ожидание определяет жесткое время, как в предыдущем примере, где ожидание составляет три секунды. В неявном ожидании состояние DOM, которое вызывает его, определяется ожидаемым условием (обратите внимание, что импорт здесь приводится к EC, общепринятой сокращенной форме). Ожидаемые условия могут быть разными в библиотеке Selenium, включая следующее:

  • Всплывает окно предупреждения.
  • Элемент (например, текстовое поле) находится в выбранном состоянии.
  • Изменяется заголовок страницы или текст теперь отображается на странице или в определенном элементе.
  • Элемент теперь виден DOM, или элемент исчезает из DOM. Большинство из этих ожидаемых условий требуют, чтобы вы сначала указали элемент, за которым следует наблюдать. Элементы указываются с помощью локаторов. Обратите внимание, что локаторы не то же самое, что селекторы (см. «Селекторы Selenium» на странице 167 для более подробной информации о селекторах). Локатор — это абстрактный язык запросов, использующий объект By, который может использоваться различными способами, в том числе для создания селекторов. В следующем коде локатор используется для поиска элементов с ID loadedButton :
    EC.presence_of_element_located((By.ID, 'loadedButton'))
    

Локаторы также могут использоваться для создания селекторов, используя функцию WebDriver find_element:

print(driver.find_element(By.ID, 'content').text)

Это, конечно, функционально эквивалентно строке в коде примера:

print(driver.find_element_by_id('content').text)

Если вам не нужно использовать локатор, не используйте его; это сэкономит вам импорт. Однако это удобный инструмент, который используется для различных приложений и обладает большой гибкостью. Следующие стратегии выбора локаторов могут использоваться с объектом By:

  • ID Используется в примере; находит элементы по их атрибуту HTML id.
  • CLASS_NAME Используется для поиска элементов по их атрибуту HTML class. Почему эта функция называется CLASS_NAME, а не просто CLASS ? Использование формы object.CLASS вызвало бы проблемы для библиотеки Selenium на Java, где .class является зарезервированным методом. Чтобы сохранить синтаксис Selenium согласованным между языками, вместо этого было использовано CLASS_NAME.
  • CSS_SELECTOR Находит элементы по их class , id или имени тега, используя соглашение #idName , .className , tagName.
  • LINK_TEXT Находит теги HTML <a> по тексту, который они содержат. Например, ссылка с надписью «Next» может быть выбрана с помощью (By.LINK_TEXT, «Next»).
  • PARTIAL_LINK_TEXT Аналогично LINK_TEXT , но соответствует частичной строке.
  • NAME Находит теги HTML по их атрибуту name. Это удобно для HTML-форм.
  • TAG_NAME Находит теги HTML по их имени тега.
  • XPATH Использует выражение XPath (синтаксис которого описан в следующем разделе) для выбора совпадающих элементов.

XPath

XPath (сокращение от XML Path) — это язык запросов, используемый для навигации и выбора частей XML-документа. Созданный W3C в 1999 году, он иногда используется в языках программирования, таких как Python, Java и C#, при работе с XML-документами.

Хотя BeautifulSoup не поддерживает XPath, многие другие библиотеки, такие как Scrapy и Selenium, поддерживают его. Он часто может использоваться так же, как селекторы CSS (например, mytag#idname ), хотя он предназначен для работы с более обобщенными XML-документами, а не только с HTML-документами.

Синтаксис XPath имеет четыре основных концепции:

  • Корневые узлы против не корневых узлов
    • /div выберет узел div только в том случае, если он находится в корне документа.
    • //div выбирает все div’ы в любом месте документа.
  • Выбор атрибутов
    • //@href выбирает любые узлы с атрибутом href .
    • //a[@href=’http://google.com‘] выбирает все ссылки в документе, указывающие на Google.
  • Выбор узлов по позиции
    • //a[3] выбирает третью ссылку в документе.
    • //table[last()] выбирает последнюю таблицу в документе.
    • //a[position() < 3] выбирает первые три ссылки в документе.
  • Звездочки () соответствуют любому набору символов или узлов и могут использоваться в различных ситуациях
    • //table/tr/ выбирает все дочерние элементы тегов tr во всех таблицах (это хорошо для выбора ячеек, используя как теги th , так и td ).
    • //div[@*] выбирает все теги div , у которых есть какие-либо атрибуты.

Синтаксис XPath также имеет множество продвинутых функций. С течением времени он развился в относительно сложный язык запросов, с логикой булевых операций, функциями (такими как position() ) и различными операторами, не обсуждаемыми здесь.

Если у вас есть проблема с выбором HTML- или XML-элементов, которую нельзя решить с помощью функций, показанных здесь, обратитесь к странице синтаксиса XPath от Microsoft.

Дополнительные вебдрайверы для Selenium

В предыдущем разделе был использован драйвер PhantomJS с Selenium. В большинстве случаев нет особой необходимости в том, чтобы браузер появлялся на экране и начинал сканировать веб, поэтому безголовые веб-драйверы, такие как PhantomJS, могут быть удобны. Однако использование другого типа веб-браузера может быть полезным при выполнении ваших сканеров по нескольким причинам:

  • Отладка. Если ваш код запускается с PhantomJS и завершается с ошибкой, то сложно диагностировать эту ошибку, не видя страницу перед собой. Вы также можете приостановить выполнение кода и взаимодействовать со страницей как обычно в любой момент.
  • Тесты могут зависеть от определенного браузера для выполнения.
  • Необычный веб-сайт или скрипт может вести себя немного иначе в разных браузерах. Ваш код просто может не работать в PhantomJS.

Сегодня множество групп, как официальные, так и неофициальные, занимаются созданием и поддержкой веб-драйверов Selenium для каждого основного браузера. Группа Selenium собирает коллекцию этих веб-драйверов для удобства использования.

firefox_driver = webdriver.Firefox('<путь к драйверу Firefox>')
chrome_driver = webdriver.Chrome('<путь к драйверу Chrome>')
safari_driver = webdriver.Safari('<путь к драйверу Safari>')
ie_driver = webdriver.Ie('<путь к драйверу Internet Explorer>')

Обработка перенаправлений

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

Однако при сканировании веба разница очевидна. Перенаправление на стороне сервера, в зависимости от того, как оно обрабатывается, может быть легко обойдено библиотекой urllib Python без помощи Selenium. Перенаправления на стороне клиента не будут обрабатываться вообще, если скрапер не выполняет JavaScript.

Selenium способен обрабатывать эти JavaScript-перенаправления так же, как и другие выполнения JavaScript; однако основная проблема с этими перенаправлениями заключается в том, когда остановить выполнение страницы — то есть, как сообщить, когда страница завершает перенаправление. Демонстрационная страница по адресу http://pythonscraping.com/pages/javascript/redirectDemo1.html дает пример этого типа перенаправления с двухсекундной задержкой.

Вы можете обнаружить это перенаправление в умном режиме, «наблюдая» за элементом в DOM при начальной загрузке страницы, а затем повторно вызывая этот элемент, пока Selenium не выбросит исключение StaleElementReferenceException; элемент больше не присоединен к DOM страницы, и сайт был перенаправлен:

from selenium import webdriver
import time
from selenium.webdriver.remote.webelement import WebElement
from selenium.common.exceptions import StaleElementReferenceException

def waitForLoad(driver):
    elem = driver.find_element_by_tag_name("html")
    count = 0
    while True:
        count += 1
        if count > 20:
            print('Timing out after 10 seconds and returning')
            return
        time.sleep(.5)
        try:
            elem == driver.find_element_by_tag_name('html')
        except StaleElementReferenceException:
            return

driver = webdriver.PhantomJS(executable_path='<Путь к Phantom JS>')
driver.get('http://pythonscraping.com/pages/javascript/redirectDemo1.html')
waitForLoad(driver)
print(driver.page_source)

Этот скрипт проверяет страницу каждые полсекунды, с таймаутом 10 секунд, хотя время, используемое для проверки и таймаут, может быть легко увеличено или уменьшено по мере необходимости.

В качестве альтернативы можно написать аналогичный цикл, проверяющий текущий URL страницы до тех пор, пока URL не изменится или не совпадет с конкретным URL, который вы ищете.

Ожидание появления и исчезновения элементов — это обычная задача в Selenium, и вы также можете использовать ту же функцию WebDriverWait, используемую в предыдущем примере загрузки кнопки. Здесь вы устанавливаете для нее тайм-аут 15 секунд и селектор XPath, который ищет содержимое тела страницы, чтобы выполнить ту же задачу:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

driver = webdriver.PhantomJS(executable_path='<Путь к Phantom JS>')
driver.get('http://pythonscraping.com/pages/javascript/redirectDemo1.html')
try:
    bodyElement = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, '//body[contains(text(), "This is the page you are looking for!)]')))
    print(bodyElement.text)
except TimeoutException:
    print('Did not find the element')

Финальное замечание о JavaScript

Большинство сайтов в современном интернете используют JavaScript. К счастью для нас, это использование JavaScript в большинстве случаев не влияет на процесс скрапинга страницы. JavaScript может быть ограничен использованием для запуска инструментов отслеживания, управления небольшим разделом сайта или манипуляции выпадающим меню, например. В тех случаях, когда JavaScript влияет на способ скрапинга сайта, его легко выполнить с помощью инструментов, таких как Selenium, чтобы получить простую HTML-страницу, которую вы учились скрапить в первой части этой книги.

Помните: только потому, что сайт использует JavaScript, это не означает, что все традиционные инструменты скрапинга перестают работать. Цель JavaScript в конечном итоге состоит в том, чтобы создавать HTML- и CSS-код, который может быть отображен браузером, или в общении с сервером динамически, через HTTP-запросы и ответы. После использования Selenium HTML и CSS на странице можно читать и разбирать, как и на любом другом сайте, а HTTP-запросы и ответы могут быть отправлены и обработаны вашим кодом с помощью техник, описанных в предыдущих главах, даже без использования Selenium.

Кроме того, JavaScript может даже быть полезным для веб-скраперов, потому что его использование в качестве «системы управления контентом на стороне браузера» может выявить полезные API для внешнего мира, позволяя вам получать данные более прямым образом. Дополнительную информацию об этом можно найти далее в разделе про API.

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

Индивидуальное и групповое обучение «Аналитик данных»
Если вы хотите стать экспертом в аналитике, могу помочь. Запишитесь на мой курс «Аналитик данных» и начните свой путь в мир ИТ уже сегодня!

Контакты
Для получения дополнительной информации и записи на курсы свяжитесь со мной:

Телеграм: https://t.me/Vvkomlev
Email: victor.komlev@mail.ru

Объясняю сложное простыми словами. Даже если вы никогда не работали с ИТ и далеки от программирования, теперь у вас точно все получится! Проверено десятками примеров моих учеников.

Гибкий график обучения. Я предлагаю занятия в мини-группах и индивидуально, что позволяет каждому заниматься в удобном темпе. Вы можете совмещать обучение с работой или учебой.

Практическая направленность. 80%: практики, 20% теории. У меня множество авторских заданий, которые фокусируются на практике. Вы не просто изучаете теорию, а сразу применяете знания в реальных проектах и задачах.

Разнообразие учебных материалов: Теория представлена в виде текстовых уроков с примерами и видео, что делает обучение максимально эффективным и удобным.

Понимаю, что обучение информационным технологиям может быть сложным, особенно для новичков. Моя цель – сделать этот процесс максимально простым и увлекательным. У меня персонализированный подход к каждому ученику. Максимальный фокус внимания на ваши потребности и уровень подготовки.

Понравилась статья? Поделиться с друзьями:
Школа Виктора Комлева
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.