Реализация веб-парсинга в Python с помощью Scrapy

С помощью Scrapy можно :

1. Эффективно получать миллионы данных
2. Запустить его на сервере
3. Получить данные 
4. Запустить spider в нескольких процессах

Scrapy предлагает совершенно новые возможности по созданию spider'а, его запуску и последующему сохранению данных путем их соскабливания, что делает его отличным инструментом для парсинга сайтов и маркетплейсов. Поначалу это выглядит довольно запутанно, но это и к лучшему.

Давайте поговорим об установке, создании spider'а и его тестировании.

Шаг 1: Создание виртуальной среды

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

sudo apt-get install python3-venv

Создайте одну папку и активизируйте ее:

mkdir scrapy-project && cd scrapy-project
python3 -m venv myvenv 

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

python3.5 -m venv myvenv

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

source myvenv/bin/activate

Шаг 2 : Установка модуля Scrapy

Установите модуль Scrapy с помощью программы:

pip install scrapy

Для установки scrapy для какой-либо конкретной версии python:

python3.5 -m pip install scrapy

Замените версию 3.5 на какую-либо другую, например 3.6.

Шаг 3: Создание проекта Scrapy

При работе с Scrapy необходимо создать проект scrapy.

scrapy startproject gfg

В Scrapy всегда стараются создать одного паука, который помогает получать данные, поэтому для его создания перейдите в папку spider и создайте там один python-файл. Создайте одного паука с именем gfgfetch.py python-файла.

Шаг 4: Создание Spider

Перейдите в папку spider и создайте файл gfgfetch.py. При создании паука всегда создавайте один класс с уникальным именем и определяйте требования. Прежде всего, необходимо дать имя spider'у, присвоив ему переменную name, а затем указать начальный URL, по которому паук начнет ползать. Определите некоторые методы, которые помогут проползти гораздо глубже на этот сайт. На данный момент давайте отбракуем все имеющиеся URL и сохраним их.

import scrapy
 
class ExtractUrls(scrapy.Spider):
 
# This name must be unique always
name = "extract"
 
# Function which will be invoked
def start_requests(self):
 
# enter the URL here
urls = ['https://www.geeksforgeeks.org/', ]
 
for url in urls:
yield scrapy.Request(url = url, callback = self.parse)

Основная цель - получить каждый url и затем запросить его. Извлечь из него все url или теги anchor. Для этого необходимо создать еще один метод parse , который будет получать данные из заданного url.

Шаг 5. Получение данных с заданной страницы

Перед написанием функции parse необходимо проверить несколько моментов, например, как получить данные с заданной страницы. Для этого можно воспользоваться оболочкой scrapy. Этот инструмент помогает в проектировании решения для веб-парсинга. Это такой же интерпретатор python, но с возможностью извлечения данных из заданного url. Короче говоря, это интерпретатор python с функциональностью Scrapy.

scrapy shell URL

Примечание: Убедитесь, что в той же директории, где находится scrapy.cfg, находится файл scrapy.cfg, иначе он не будет работать.

scrapy shell https://www.geeksforgeeks.org/

Теперь для получения данных с заданной страницы используются селекторы. Эти селекторы могут быть как из CSS, так и из Xpath. Сейчас попробуем получить все url с помощью CSS-селектора.

  • Для получения тега anchor:

response.css('a')

  • Для извлечения данных :

links = response.css('a').extract()

  • Например, для links[0] будет показано что-то вроде этого :

'<a href="https://www.geeksforgeeks.org/" title="GeeksforGeeks" rel="home">GeeksforGeeks</a>'

  • Чтобы получить атрибут href, используйте тег attributes.

links = response.css('a::attr(href)').extract()

Это позволит получить все данные href, что очень полезно. Воспользуйтесь этой ссылкой и начните запрашивать ее.

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

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

# Parse function
def parse(self, response):
 
# Extra feature to get title
title = response.css('title::text').extract_first()
 
# Get anchor tags
links = response.css('a::attr(href)').extract()
 
for link in links:
yield
{
'title': title,
'links': link
}
 
if 'geeksforgeeks' in link:
yield scrapy.Request(url = link, callback = self.parse)

Ниже приведена реализация парсинга:
# importing the scrapy module
import scrapy
 
class ExtractUrls(scrapy.Spider):
name = "extract"
 
# request function
def start_requests(self):
urls = [ 'https://www.geeksforgeeks.org', ]
 
for url in urls:
yield scrapy.Request(url = url, callback = self.parse)
 
# Parse function
def parse(self, response):
 
# Extra feature to get title
title = response.css('title::text').extract_first()
 
# Get anchor tags
links = response.css('a::attr(href)').extract()
 
for link in links:
yield
{
'title': title,
'links': link
}
 
if 'geeksforgeeks' in link:
yield scrapy.Request(url = link, callback = self.parse)

Шаг 6: На последнем шаге запустите spider и получите результат в виде простого json-файла

scrapy crawl NAME_OF_SPIDER -o links.json

В данном примере имя spider'а - "extract". За несколько секунд он соберет большое количество данных.