【问题标题】:Scrapy Spider pagination ending earlyScrapy Spider 分页提前结束
【发布时间】:2021-01-12 00:30:06
【问题描述】:

我正在为一个项目开发一个爬虫蜘蛛。我正在抓取的大多数网站都具有带有列表页面的搜索页面的一般格式。我编写了一个蜘蛛来从搜索页面和列表页面中抓取每个列表的数据。我遇到的问题是,在抓取我的蜘蛛时,我的蜘蛛会抓取所有搜索页面并将列表页面排队等待抓取,但是一旦到达最终搜索页面,蜘蛛就会关闭。有时它也会在到达最后一页之前结束。如果我让它只运行一个搜索页面(没有分页),那么所有列表都会返回。我还在学习,所以我确定我错过了一些东西。

我在这里写了一个示例蜘蛛,使用的结构与我写的相同。

import scrapy

class exampleSpider(scrapy.Spider):
    name = 'exampleSpider'
    
    start_urls = ['eample.com/pages=1']

    custom_settings={ 'FEED_URI': "example_%(time)s.csv", 'FEED_FORMAT': 'csv'}

    def parse(self, response):
        for post in response.css('.job-listings'):
            url = post.css('.job-url::text').get()
            title = post.css('.job-title::text').get()
            yield scrapy.Request(url=url, callback=self.parse_listing,meta={'url':url,'title':title})

        #pagination
        next_page = response.css('.pagination li:last-child a::attr(href)').get()
        if next_page is not None:
            next_page = 'example.com' + next_page
            yield scrapy.Request(url=next_page, callback=self.parse)

    def parse_listing(self, response):
        yield{
              'url': response.meta['url'],
              'title': response.meta['title'],
              'company': response.css('.row:nth-child(1) a::text').get(),
              'specialty': response.css('.row:nth-child(2) a::text').get(),
              'city': response.css('.value span:nth-child(1)::text').get(),
              'state': response.css('.value span+ span::text').get(),
              'job type': response.css('.row:nth-child(4) .value::text').get(),
         }

这是我运行蜘蛛后通常得到的输出。例如,这个网站有大约 6000 个页面,但它只有 153 个。

2021-01-11 17:43:00 [scrapy.core.engine] INFO: Closing spider (finished)
2021-01-11 17:43:00 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 115052,
 'downloader/request_count': 203,
 'downloader/request_method_count/GET': 203,
 'downloader/response_bytes': 2272046,
 'downloader/response_count': 203,
 'downloader/response_status_count/200': 173,
 'downloader/response_status_count/404': 2,
 'downloader/response_status_count/429': 27,
 'downloader/response_status_count/500': 1,
 'elapsed_time_seconds': 223.01121,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2021, 1, 11, 23, 43, 0, 37435),
 'httperror/response_ignored_count': 1,
 'httperror/response_ignored_status_count/404': 1,
 'item_scraped_count': 153,
 'log_count/DEBUG': 356,
 'log_count/ERROR': 6,
 'log_count/INFO': 14,
 'request_depth_max': 13,
 'response_received_count': 175,
 'retry/count': 28,
 'retry/reason_count/429 Unknown Status': 27,
 'retry/reason_count/500 Internal Server Error': 1,
 'robotstxt/request_count': 1,
 'robotstxt/response_count': 1,
 'robotstxt/response_status_count/404': 1,
 'scheduler/dequeued': 202,
 'scheduler/dequeued/memory': 202,
 'start_time': datetime.datetime(2021, 1, 11, 23, 39, 17, 26225)}
2021-01-11 17:43:00 [scrapy.core.engine] INFO: Spider closed (finished)

【问题讨论】:

    标签: python scrapy


    【解决方案1】:

    我为遇到类似情况的其他人找到了解决我的问题的方法。我发现了 2 个问题。首先,我正在抓取的网站的职位列表布局略有不同。广告和常规帖子的类名不同,所以一旦我到达第 35 页左右,我的 for 循环就会检查 None 并结束抓取。第二个问题是一些列表页面不再存在,但仍然被张贴。所以当刮板试图刮它时 None 再次返回。所以这里的教训是使用 try 和 except 语句,因为我的问题与我想的分页没有任何关系。这是现在适用于我的更新代码。

    import scrapy
    
    class exampleSpider(scrapy.Spider):
        name = 'exampleSpider'
        
        start_urls = ['eample.com/pages=1']
    
        custom_settings={ 'FEED_URI': "example_%(time)s.csv", 'FEED_FORMAT': 'csv'}
    
        def parse(self, response):
           if(response.css('.job-listings') == []):
              try:
                 for post in response.css('.job-listings-old'):
                    url = post.css('.job-url::text').get()
                    title = post.css('.job-title::text').get()
                    yield scrapy.Request(url=url, callback=self.parse_listing,meta {'url':url,'title':title})
              except Exception e:
                 print(e)
           else:
              try:
                 for post in response.css('.job-listings'):
                    url = post.css('.job-url::text').get()
                    title = post.css('.job-title::text').get()
                    yield scrapy.Request(url=url, callback=self.parse_listing,meta {'url':url,'title':title})
              except Exception e:
                 print(e)
    
            #pagination
            next_page = response.css('.pagination li:last-child a::attr(href)').get()
            if next_page is not None:
                next_page = 'example.com' + next_page
                yield scrapy.Request(url=next_page, callback=self.parse)
    
        def parse_listing(self, response):
            yield{
                  'url': response.meta['url'],
                  'title': response.meta['title'],
                  'company': response.css('.row:nth-child(1) a::text').get(),
                  'specialty': response.css('.row:nth-child(2) a::text').get(),
                  'city': response.css('.value span:nth-child(1)::text').get(),
                  'state': response.css('.value span+ span::text').get(),
                  'job type': response.css('.row:nth-child(4) .value::text').get(),
             }
    

    【讨论】:

      猜你喜欢
      • 2015-02-14
      • 1970-01-01
      • 2017-03-19
      • 1970-01-01
      • 2016-12-14
      • 1970-01-01
      • 2016-05-09
      • 1970-01-01
      • 2015-10-14
      相关资源
      最近更新 更多