В этой главе мы узнаем, как выполнять очистку веб-страниц на динамических веб-сайтах, а также подробные концепции.
Вступление
Соскоб в Интернете — сложная задача, и сложность увеличивается, если сайт динамический. Согласно Глобальному аудиту доступности веб-сайтов Организации Объединенных Наций, более 70% веб-сайтов являются динамичными по своей природе, и для своей функциональности они используют JavaScript.
Пример динамического сайта
Давайте посмотрим на пример динамического веб-сайта и узнаем о том, почему его трудно очистить. Здесь мы собираемся взять пример поиска с веб-сайта с именем http://example.webscraping.com/places/default/search. Но как мы можем сказать, что этот сайт имеет динамичный характер? Об этом можно судить по выводу следующего скрипта Python, который попытается очистить данные с вышеупомянутой веб-страницы —
import re import urllib.request response = urllib.request.urlopen('http://example.webscraping.com/places/default/search') html = response.read() text = html.decode() re.findall('(.*?)',text)
Выход
[ ]
Приведенный выше вывод показывает, что пример скребка не смог извлечь информацию, потому что элемент <div>, который мы пытаемся найти, пуст.
Подходы для очистки данных с динамических сайтов
Мы видели, что скребок не может очистить информацию с динамического веб-сайта, потому что данные загружаются динамически с помощью JavaScript. В таких случаях мы можем использовать следующие два метода для очистки данных с динамических JavaScript-зависимых веб-сайтов:
- Обратный инжиниринг JavaScript
- Рендеринг JavaScript
Обратный инжиниринг JavaScript
Процесс, называемый обратным инжинирингом, будет полезен и позволит нам понять, как данные загружаются динамически веб-страницами.
Для этого нам нужно щелкнуть вкладку inspect element для указанного URL. Далее мы перейдем на вкладку NETWORK, чтобы найти все запросы, сделанные для этой веб-страницы, включая search.json с путем / ajax . Вместо доступа к данным AJAX из браузера или через вкладку NETWORK, мы можем сделать это также с помощью следующего скрипта Python —
import requests url=requests.get('http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=a') url.json()
пример
Приведенный выше скрипт позволяет нам получить доступ к ответу JSON с помощью метода Python json. Точно так же мы можем загрузить необработанный строковый ответ и, используя метод json.loads в python, также можем загрузить его. Мы делаем это с помощью следующего скрипта Python. Он будет в основном очищать все страны, выполняя поиск буквы алфавита «а», а затем перебирая получившиеся страницы ответов JSON.
import requests import string PAGE_SIZE = 15 url = 'http://example.webscraping.com/ajax/' + 'search.json?page={}&page_size={}&search_term=a' countries = set() for letter in string.ascii_lowercase: print('Searching with %s' % letter) page = 0 while True: response = requests.get(url.format(page, PAGE_SIZE, letter)) data = response.json() print('adding %d records from the page %d' %(len(data.get('records')),page)) for record in data.get('records'):countries.add(record['country']) page += 1 if page >= data['num_pages']: break with open('countries.txt', 'w') as countries_file: countries_file.write('n'.join(sorted(countries)))
После запуска вышеприведенного скрипта мы получим следующий вывод, и записи будут сохранены в файле с именем country.txt.
Выход
Searching with a adding 15 records from the page 0 adding 15 records from the page 1 ...
Рендеринг JavaScript
В предыдущем разделе мы провели реверс-инжиниринг на веб-странице о том, как работает API и как мы можем использовать его для получения результатов в одном запросе. Тем не менее, мы можем столкнуться со следующими трудностями при выполнении обратного проектирования —
-
Иногда сайты могут быть очень сложными. Например, если веб-сайт создан с помощью расширенного инструмента браузера, такого как Google Web Toolkit (GWT), то полученный в результате код JS будет сгенерирован машинным способом и сложен для понимания и обратного инжиниринга.
-
Некоторые высокоуровневые фреймворки, такие как React.js, могут затруднить обратный инжиниринг, абстрагируя и без того сложную логику JavaScript.
Иногда сайты могут быть очень сложными. Например, если веб-сайт создан с помощью расширенного инструмента браузера, такого как Google Web Toolkit (GWT), то полученный в результате код JS будет сгенерирован машинным способом и сложен для понимания и обратного инжиниринга.
Некоторые высокоуровневые фреймворки, такие как React.js, могут затруднить обратный инжиниринг, абстрагируя и без того сложную логику JavaScript.
Решение вышеуказанных трудностей состоит в том, чтобы использовать механизм рендеринга браузера, который анализирует HTML, применяет форматирование CSS и выполняет JavaScript для отображения веб-страницы.
пример
В этом примере для рендеринга Java Script мы будем использовать знакомый модуль Python Selenium. Следующий код Python будет визуализировать веб-страницу с помощью Selenium —
Во-первых, нам нужно импортировать веб-драйвер из селена следующим образом:
from selenium import webdriver
Теперь укажите путь к веб-драйверу, который мы скачали в соответствии с нашим требованием —
path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver' driver = webdriver.Chrome(executable_path = path)
Теперь укажите URL, который мы хотим открыть в этом веб-браузере, который теперь контролируется нашим скриптом Python.
driver.get( 'http://example.webscraping.com/search' )
Теперь мы можем использовать идентификатор панели инструментов поиска для настройки элемента для выбора.
driver.find_element_by_id('search_term').send_keys('.')
Далее, мы можем использовать java-скрипт для установки содержимого поля выбора следующим образом:
js = "document.getElementById('page_size').options[1].text = '100';" driver.execute_script(js)
Следующая строка кода показывает, что поиск готов для нажатия на веб-странице —
driver.find_element_by_id('search').click()
Следующая строка кода показывает, что он будет ждать 45 секунд для завершения запроса AJAX.
driver.implicitly_wait(45)
Теперь для выбора ссылок на страны мы можем использовать селектор CSS следующим образом:
links = driver.find_elements_by_css_selector('#results a')
Теперь текст каждой ссылки может быть извлечен для создания списка стран —