Начало работы с Scrapy: веб-парсер на основе скриптов на Python
Table Of Content
Привет всем, давайте создадим простой веб-парсер, используя фреймворк для парсинга веб-страниц на Python - "Scrapy".
Обзор Scrapy
Scrapy - это фреймворк на Python для масштабированного парсинга веб-страниц. Scrapy построен на асинхронном сетевом движке Twisted, что означает, что он не использует стандартную инфраструктуру асинхронности/ожидания в Python. Twisted - это событийно-ориентированный сетевой движок, написанный на Python. Он позволяет Scrapy обрабатывать запросы и ответы асинхронно, назначая каждый входящий запрос "реактору", который ожидает ответа. Это позволяет Scrapy обрабатывать несколько запросов одновременно, улучшая его производительность и эффективность.
Прежде чем перейти к техническим деталям и начать писать код, давайте сначала попробуем понять или получить обзор нескольких вещей, которые необходимы для парсинга веб-страниц, а именно XPATH и CSS-селекторы.
XPATH
XPath - это язык запросов, который используется для выбора элементов из XML-документа, такого как HTML-страница. Он предоставляет способ навигации по иерархии документа и поиска элементов, которые соответствуют определенному набору критериев, таких как атрибуты элемента или его положение в документе.
Вот несколько простых примеров выражений XPath:
Примечание, что это всего лишь несколько примеров для иллюстрации синтаксиса XPath. Существует еще много более мощных и сложных выражений, которые можно использовать для выбора конкретных элементов из HTML-документа.
CSS Selectors
Как и XPATH, CSS-селекторы также используются для выбора элементов на HTML-странице. CSS-селекторы используют синтаксис языка Cascading Style Sheets (CSS) для указания элементов, которые вы хотите выбрать. Например, вы можете использовать CSS-селектор для выбора всех элементов <h1>
на странице, всех элементов с классом title
или всех элементов с идентификатором main-content
.
Вот несколько примеров CSS-селекторов, которые вы можете использовать в проекте по парсингу:
h1
: Этот селектор выбирает все элементы<h1>
на странице..title
: Этот селектор выбирает все элементы с классомtitle
.#main-content
: Этот селектор выбирает элемент с идентификаторомmain-content
.a[href]
: Этот селектор выбирает все элементы<a>
, у которых есть атрибутhref
.table tr:nth-child(2) td:nth-child(3)
: Этот селектор выбирает третий элемент<td>
второго элемента<tr>
внутри<table>
.
Это всего лишь несколько примеров из множества различных CSS-селекторов, которые вы можете использовать при парсинге. Чтобы узнать больше о CSS-селекторах и о том, как их использовать, вы можете обратиться к документации библиотеки или фреймворка для парсинга, которые вы используете.
**СОВЕТ: **CSS-селекторы работают быстрее, чем выражения XPath для выбора элементов на веб-странице. Это связано с тем, что большинство современных веб-браузеров, включая Google Chrome и Mozilla Firefox, используют оптимизированные алгоритмы для быстрого вычисления CSS-селекторов и поиска соответствующих элементов на странице.
Scrapy Shell
Scrapy поставляется с интерактивной оболочкой, которая является инструментом командной строки, позволяющим тестировать наш код парсинга в живой среде перед запуском полноценного парсера.
Чтобы запустить оболочку Scrapy, мы должны ввести эту команду в командной строке или терминале:
scrapy shell
после ввода вышеуказанной команды терминал будет выглядеть так:
Теперь нам нужно указать URL веб-сайта, который мы хотим спарсить и протестировать в оболочке Scrapy. Для этого команда будет следующей:
fetch("URL")
В нашем случае мы будем парсить этот веб-сайт: https://beutlich.com/products/. поэтому команда будет выглядеть так:
fetch("https://beutlich.com/products/")
Обратите внимание, что код ответа 200. Это означает, что мы успешно обработали введенный URL.
После обработки URL теперь нам нужно спарсить доступные URL-адреса продуктов. Если мы проверим URL-адреса продуктов, они доступны в теге якоря, который находится внутри тега статьи. См. скриншот ниже
поэтому мы можем составить XPATH следующим образом: //article[contains(@class, 'portfolio-item count')]/a/@href
В нашей оболочке Scrapy мы напишем команду для извлечения URL:
response.xpath("//article[contains(@class, 'portfolio-item count')]/a/@href").extract()
Это вернет нам список URL-адресов различных доступных продуктов.
Теперь мы можем получить URL-адреса продуктов, поэтому мы можем, наконец, спарсить информацию о продукте.
Теперь мы отправим другой запрос на спарсенные URL-адреса и получим ответ. В нашем коде Python мы напишем отдельную функцию для этого и передадим ответ каждого URL-адреса по одному этой функции.
Но пока мы протестируем наш код на одном URL в оболочке Scrapy.
Теперь мы хотим спарсить название продукта, которое доступно внутри тега h1, и у тега h1 нет класса, но мы можем получить доступ к этому тегу с помощью идентификатора тега заголовка. Так что XPATH будет выглядеть так:
//header[@id='page-heading']/h1/text()
и команда Scrapy
response.xpath("//header[@id='page-heading']/h1/text()").extract_first()
Обратите внимание: важно отметить, что extract() вернет список всех соответствующих результатов, тогда как extract_first() вернет только первый результат в виде строки.
Для парсинга артикула продукта код Scrapy будет выглядеть так.
response.css(".entry ul li:nth-child(8)::text").get().split(": ")[1]
Для парсинга описания продукта код Scrapy будет выглядеть так
response.css(".entry ::text").getall()
Обратите внимание, что между именем класса и двоеточием есть пробел, что означает, что мы хотим получить весь доступный текст внутри этого тега.
Для парсинга изображения код Scrapy будет выглядеть так.
response.css(".slide>a::attr(href)").get()
Теперь перейдем к коду Python.
Сначала мы импортируем scrapy и его необходимые функции
import scrapy
from scrapy.crawler import CrawlerProcess
Теперь мы определим наш класс парсера и внутри этого класса определим некоторые переменные класса.
class beutlich_scraper(scrapy.Spider):
custom_settings = {
'DOWNLOAD_DELAY' : 0.25,
'RETRY_TIMES': 10,
# экспорт в формате CSV
'FEED_FORMAT' : 'csv',
'FEED_URI' : 'Beutlich-data.csv'
'OBEY_ROBOTS' : False,
}
start_urls =['https://beutlich.com/products/']
Custom_settings: для определения некоторых пользовательских настроек при отправке запросов на URL.
start_urls: это наш начальный URL.
Теперь мы определим нашу первую функцию внутри нашего класса парсера, имя которой должно быть parse() (по умолчанию это требуется).
def parse(self, response):
links =response.xpath("//article[contains(@class, 'portfolio-item count')]/a/@href").extract()
for link in links:
yield scrapy.Request(link, callback=self.parse_product)
Эта функция парсит URL-адреса продуктов, и через цикл мы передаем их в другую функцию для парсинга информации о продукте.
Внутри нашей функции parse_product() мы парсим необходимую информацию и сохраняем ее в словаре
def parse_product(self, response):
data_dict = {}
data_dict['Название продукта']=response.css("#page-heading>h1").get()
data_dict['Артикул продавца']= response.css(".entry ul li:nth-child(8)::text").get().split(": ")[1]
data_dict['Описание']=response.css(".entry ::text").getall()
data_dict['URL изображения']=response.css(".slide>a::attr(href)").get()
yield data_dict
Затем нам нужно инициализировать класс CrawlProcess и передать наш класс парсера в качестве аргумента.
process = CrawlerProcess()
process.crawl(beutlich_scraper)
process.start()
При запуске этого кода этот парсер будет парсить информацию и сохранять данные в формате csv.
Это конец блога.
Пожалуйста, поделитесь этим блогом со своими друзьями.
Пожалуйста, подпишитесь на меня в Twitter. https://twitter.com/faheem2920