Scrapy игнорирует содержимое второй страницы

Я написал крошечный скребок на python scrapy для анализа разных имен с веб-страницы. Страница прошла еще 4 страницы с помощью нумерации страниц. Всего имен на страницах 46, но он вычищает 36 имен.

Предполагается, что парсер пропускает содержимое первых целевых страниц, но, используя аргумент parse_start_url в моем парсере, я обработал его.

Однако проблема, с которой я столкнулся в данный момент с этим парсером, заключается в том, что он на удивление пропускает содержимое второй страницы и анализирует все остальное, я имел в виду первую страницу, третью страницу, четвертую страницу и так далее. Почему это происходит и как с этим бороться? Заранее спасибо.

Вот сценарий, который я пытаюсь использовать:

import scrapy

class DataokSpider(scrapy.Spider):

    name = "dataoksp"
    start_urls = ["https://data.ok.gov/browse?page=1&f[0]=bundle_name%3ADataset&f[1]=im_field_categories%3A4191"]

    def parse(self, response):
        for link in response.css('.pagination .pager-item a'):
            new_link = link.css("::attr(href)").extract_first()
            yield scrapy.Request(url=response.urljoin(new_link), callback=self.target_page)

    def target_page(self, response):
        parse_start_url = self.target_page  # I used this argument to capture the content of first page
        for titles in response.css('.title a'):
            name = titles.css("::text").extract_first()
            yield {'Name':name}

person SIM    schedule 18.09.2017    source источник


Ответы (2)


Решение оказывается очень простым. Я уже починил.

import scrapy

class DataokSpider(scrapy.Spider):

    name = "dataoksp"
    start_urls = ["https://data.ok.gov/browse?f[0]=bundle_name%3ADataset&f[1]=im_field_categories%3A4191"]

    def parse(self, response):
        for f_link in self.start_urls:
            yield response.follow(url=f_link, callback=self.target_page) #this is line which fixes the issue

        for link in response.css('.pagination .pager-item a'):
            new_link = link.css("::attr(href)").extract_first()
            yield response.follow(url=new_link, callback=self.target_page)

    def target_page(self, response):
        for titles in response.css('.title a'):
            name = titles.css("::text").extract_first()
            yield {'Name':name}

Теперь это дает мне все результаты.

person SIM    schedule 27.09.2017

Потому что ссылка, которую вы указываете в start_urls, на самом деле является ссылкой второй страницы. Если вы откроете его, вы увидите, что на текущей странице нет тега <a>. Вот почему страница 2 не достигает target_page, поэтому вы должны указать start_urls на:

https://data.ok.gov/browse?f[0pting=bundle_name%3ADataset&f[1]]=im_field_categories%3A4191

Этот код должен помочь вам:

import scrapy
from scrapy.http import Request


class DataokspiderSpider(scrapy.Spider):
    name = 'dataoksp'
    allowed_domains = ['data.ok.gov']
    start_urls = ["https://data.ok.gov/browse?f[0]=bundle_name%3ADataset&f[1]=im_field_categories%3A4191",]

    def parse(self, response):
        for titles in response.css('.title a'):
            name = titles.css("::text").extract_first()
            yield {'Name':name}

        next_page = response.xpath('//li[@class="pager-next"]/a/@href').extract_first()
        if next_page:
            yield Request("https://data.ok.gov{}".format(next_page), callback=self.parse)

Статистика (см. item_scraped_count):

{
    'downloader/request_bytes': 2094,
    'downloader/request_count': 6,
    'downloader/request_method_count/GET': 6,
    'downloader/response_bytes': 45666,
    'downloader/response_count': 6,
    'downloader/response_status_count/200': 6,
    'finish_reason': 'finished',
    'finish_time': datetime.datetime(2017, 9, 19, 7, 23, 47, 801934),
    'item_scraped_count': 46,
    'log_count/DEBUG': 53,
    'log_count/INFO': 7,
    'memusage/max': 47509504,
    'memusage/startup': 47509504,
    'request_depth_max': 4,
    'response_received_count': 6,
    'scheduler/dequeued': 5,
    'scheduler/dequeued/memory': 5,
    'scheduler/enqueued': 5,
    'scheduler/enqueued/memory': 5,
    'start_time': datetime.datetime(2017, 9, 19, 7, 23, 46, 59360)
}
person Andrés Pérez-Albela H.    schedule 19.09.2017
comment
Спасибо Андресу Перес-Альбеле Х. за ваш ответ. Это решение определенно работает, и перед публикацией здесь я тоже пробовал его. Однако в scrapy есть встроенный стиль для анализа данных с первой страницы, которая равна parse_start_url, я действительно ожидал, что мой сценарий будет построен на этом руководстве. Спасибо еще раз. - person SIM; 19.09.2017
comment
@Topto Я рад, что мой ответ помог. Если он отвечает на ваш вопрос, укажите его как выбранный ответ и проголосуйте, если вы цените мою поддержку. - person Andrés Pérez-Albela H.; 19.09.2017
comment
@Topto parse_start_url предназначен для CrawlSpider, а не для Spider. Тем не менее, если вам нужно переопределить его, вам сначала нужно наследовать от CrawlSpider. Тем не менее, CrawlSpider не нужен для вашего варианта использования, поскольку вам не нужны правила, а также то же поведение можно воспроизвести с помощью кода, который я добавил в свой ответ (только с помощью Spider). - person Andrés Pérez-Albela H.; 20.09.2017