Парсинг веб-сайтов с поддержкой 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:

  1. name - это переменная, в которую записывается имя паука, и каждый паук распознается по этому имени. Команда для запуска паука - scrapy crawl spidername (здесь spidername обозначает имя, которое определено в пауке).
  2. function start_requests - Первые запросы выполняются вызовом метода start_requests(), который генерирует Request для URL, указанного в поле url в yield SeleniumRequest, и метод parse в качестве функции обратного вызова для Requests
  3. url- Здесь указывается url сайта.
  4. screenshot- С помощью метода get_screenshot_as_file() можно сделать скриншот веб-страницы, указав в качестве параметра имя файла, который будет сохранен в проекте.
  5. callback - функция, которая будет вызвана с ответом на данный запрос в качестве первого параметра.
  6. dont_filter - указывает на то, что данный запрос не должен фильтроваться планировщиком. Если тот же самый url будет отправлен на разбор, то он не выдаст исключения о том, что к нему уже обращались. Это означает, что к одному и тому же url можно обращаться более одного раза. По умолчанию значение false.
  7. 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
            }