Парсинг веб-сайтов с поддержкой Javascript с помощью Scrapy-Selenium
Scrapy-selenium - это промежуточное программное обеспечение, которое используется для веб-парсинга. Scrapy не поддерживает пасинг современных сайтов, использующих javascript-фреймворки, и именно поэтому данное промежуточное программное обеспечение используется вместе со scrapy для парсинга этих современных сайтов. Scrapy-selenium предоставляет функциональные возможности selenium, которые помогают работать с javascript-сайтами. Другим преимуществом является драйвер, с помощью которого мы можем видеть, что происходит за кулисами. Поскольку selenium является автоматизированным инструментом, он также предоставляет нам возможность работать с тегами ввода и выполнять парсинг в соответствии с тем, что вы передаете в поле ввода. Впервые scrapy-selenium был представлен в 2018 году и является открытым исходным кодом. Альтернативой ему может быть scrapy-splash
Установка и настройка Scrapy -
- Установить scrapy
- Запустите
scrapy startproject projectname (projectname - имя проекта)
Теперь запустим,
scrapy genspider spidername example.com
(замените spidername на предпочитаемое имя паука, а example.com - на сайт, который вы хотите запарсить). Примечание: В дальнейшем url также может быть изменен внутри вашего scrapy

Установите scrapy-selenium и добавьте следующее в файл settings.py
# для firefox
from shutil import which
SELENIUM_DRIVER_NAME = 'firefox'
SELENIUM_DRIVER_EXECUTABLE_PATH = which('geckodriver')
SELENIUM_DRIVER_ARGUMENTS=['-headless']
# для драйвера chrome
from shutil import which
SELENIUM_DRIVER_NAME = 'chrome'
SELENIUM_DRIVER_EXECUTABLE_PATH = which('chromedriver')
SELENIUM_DRIVER_ARGUMENTS=['--headless']
DOWNLOADER_MIDDLEWARES = {
'scrapy_selenium.SeleniumMiddleware': 800
}
В данном проекте используется драйвер chrome. Драйвер chrome должен быть загружен в соответствии с версией браузера chrome. Перейдите в раздел справки браузера chrome, затем нажмите кнопку О Google chrome и проверьте свою версию.
Запустить проект:
command- scrapy crawl spidername (в данном проекте scrapy crawl integratedspider)
код паука перед scrapy-selenium:
import scrapy
class IntegratedspiderSpider(scrapy.Spider):
name = 'integratedspider' # имя паука
allowed_domains = ['example.com']
start_urls = ['http://example.com/']
def parse(self, response):
pass
Важные поля в scrapy-selenium:
- name - это переменная, в которую записывается имя паука, и каждый паук распознается по этому имени. Команда для запуска паука - scrapy crawl spidername (здесь spidername обозначает имя, которое определено в пауке).
- function start_requests - Первые запросы выполняются вызовом метода start_requests(), который генерирует Request для URL, указанного в поле url в yield SeleniumRequest, и метод parse в качестве функции обратного вызова для Requests
- url- Здесь указывается url сайта.
- screenshot- С помощью метода get_screenshot_as_file() можно сделать скриншот веб-страницы, указав в качестве параметра имя файла, который будет сохранен в проекте.
- callback - функция, которая будет вызвана с ответом на данный запрос в качестве первого параметра.
- dont_filter - указывает на то, что данный запрос не должен фильтроваться планировщиком. Если тот же самый url будет отправлен на разбор, то он не выдаст исключения о том, что к нему уже обращались. Это означает, что к одному и тому же url можно обращаться более одного раза. По умолчанию значение false.
- wait_time - Scrapy не ожидает фиксированного времени между запросами. Но с помощью этого поля мы можем назначить его во время обратного вызова.

Общая структура scrapy-selenium spider:
import scrapy
from scrapy_selenium import SeleniumRequest
class IntegratedspiderSpider(scrapy.Spider):
name = 'integratedspider'
def start_requests(self):
yield SeleniumRequest(
url = "https://www.geeksforgeeks.org/",
wait_time = 3,
screenshot = True,
callback = self.parse,
dont_filter = True
)
def parse(self, response):
pass
Код для сопоставления данных о курсах от Geeksforgeeks -
import scrapy
from scrapy_selenium import SeleniumRequest
class IntegratedspiderSpider(scrapy.Spider):
name = 'integratedspider'
def start_requests(self):
yield SeleniumRequest(
url = "https://practice.geeksforgeeks.org/courses/online",
wait_time = 3,
screenshot = True,
callback = self.parse,
dont_filter = True
)
def parse(self, response):
# courses make list of all items that came in this xpath
# this xpath is of cards containing courses details
courses = response.xpath('/*[@id ="active-courses-content"]/div/div/div')
# course is each course in the courses list
for course in courses:
# xpath of course name is added in the course path
# text() will scrape text from h4 tag that contains course name
course_name = course.xpath('./a/div[2]/div/div[2]/h4/text()').get()
# course_name is a string containing \n and extra spaces
# these \n and extra spaces are removed
course_name = course_name.split('\n')[1]
course_name = course_name.strip()
yield {
'course Name':course_name
}


