【问题标题】:Scrapy stops crawling at seemingly random pointScrapy 在看似随机的点停止爬行
【发布时间】:2017-09-05 08:00:26
【问题描述】:

设置

我正在从this site 抓取伦敦住房广告。

人们可以搜索 3 种不同区域大小的住房广告:整个伦敦、特定区域(例如伦敦市中心)或特定子区域(例如 Aldgate)。

该网站仅允许您查看每个区域每 30 个广告中的 50 个页面,无论区域大小。 IE。如果我选择 X,我可以在 X 中查看 1500 个广告,无论 X 是伦敦市中心还是 Aldgate。

在撰写此问题时,网站上有超过 37.000 个广告。

由于我想抓取尽可能多的广告,这个限制意味着我需要抓取分区级别的广告。

为此,我编写了以下蜘蛛,

# xpath to area/sub area links
area_links = ('''//*[@id="fullListings"]/div[1]/div/div/nav/aside/'''
          '''section[1]/div/ul/li/a/@href''')

class ApartmentSpider(scrapy.Spider):
    name = 'apartments2'
    start_urls = [
        "https://www.gumtree.com/property-to-rent/london"
        ]

    # obtain links to london areas
    def parse(self, response):                
            for url in response.xpath(area_links).extract():
                yield scrapy.Request(response.urljoin(url),
                         callback=self.parse_sub_area)    

    # obtain links to london sub areas
    def parse_sub_area(self, response):                
            for url in response.xpath(area_links).extract():
                yield scrapy.Request(response.urljoin(url),
                         callback=self.parse_ad_overview)    

    # obtain ads per sub area page
    def parse_ad_overview(self, response):                
            for ads in response.xpath('//*[@id="srp-results"]/div[1]/div/div[2]',
                                      ).css('ul').css('li').css('a',
                                           ).xpath('@href').extract():
                yield scrapy.Request(response.urljoin(ads),
                         callback=self.parse_ad)

                next_page = response.css(
            '#srp-results > div.grid-row > div > ul > li.pagination-next > a',
                                        ).xpath('@href').extract_first()
                if next_page is not None:
                    next_page = response.urljoin(next_page)
                    yield scrapy.Request(next_page, callback=self.parse) 

    # obtain info per ad
    def parse_ad(self, response):

    # here follows code to extract of data per ad

效果很好。

即获取到的链接,

  1. 初始页面的区域
  2. 各个区域页面中的子区域,每个区域
  3. 每个子区域页面的房屋广告,迭代每个子区域的所有页面

最终从每个单独的广告中抓取数据。


问题

代码似乎随机停止抓取,我不知道为什么。

我怀疑它已经达到了限制,因为它被告知要抓取许多链接和项目,但我不确定我是否正确。

当它停止时,它会声明,

{'downloader/request_bytes': 1295950,
 'downloader/request_count': 972,
 'downloader/request_method_count/GET': 972,
 'downloader/response_bytes': 61697740,
 'downloader/response_count': 972,
 'downloader/response_status_count/200': 972,
 'dupefilter/filtered': 1806,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2017, 9, 4, 17, 13, 35, 53156),
 'item_scraped_count': 865,
 'log_count/DEBUG': 1839,
 'log_count/ERROR': 5,
 'log_count/INFO': 11,
 'request_depth_max': 2,
 'response_received_count': 972,
 'scheduler/dequeued': 971,
 'scheduler/dequeued/memory': 971,
 'scheduler/enqueued': 971,
 'scheduler/enqueued/memory': 971,
 'spider_exceptions/TypeError': 5,
 'start_time': datetime.datetime(2017, 9, 4, 17, 9, 56, 132388)}

我不确定是否可以从中读取我是否已达到限制或其他内容,但如果有人知道,请告诉我是否这样做以及如何防止代码停止。

【问题讨论】:

  • 您只收到状态 200 响应。如果确实出现问题或您被阻止,您将收到服务不可用响应 (503) 或类似情况。您是否认为代码过早停止,因为项目计数在不同的运行中有所不同?
  • 嗨,Andras,恐怕我不明白您所说的“项目数量因不同的运行而异”是什么意思。
  • 为什么您认为您的代码会过早停止抓取?
  • 我认为它必须同时做太多事情。有60多个子区域,每个50页,每页30个广告。也许代码一次迭代太多。
  • 您必须追踪代码退出的位置。例如,您成功抓取的所有广告是否都来自同一区域?你可以从只抓取一个区域开始,看看你是否能得到所有的广告。如果可行,请尝试刮擦前两个区域,依此类推。如果它不起作用,请追踪代码中断的位置。

标签: python scrapy limit


【解决方案1】:

虽然抓取过程的完整或至少部分日志将帮助您进行故障排除,但我将冒险发布此答案,因为我看到了一件事;我假设是问题

def parse_ad_overview(self, response):                
            for ads in response.xpath('//*[@id="srp-results"]/div[1]/div/div[2]',
                                      ).css('ul').css('li').css('a',
                                           ).xpath('@href').extract():
                yield scrapy.Request(response.urljoin(ads),
                         callback=self.parse_ad)

                next_page = response.css(
            '#srp-results > div.grid-row > div > ul > li.pagination-next > a',
                                        ).xpath('@href').extract_first()
                if next_page is not None:
                    next_page = response.urljoin(next_page)
                    yield scrapy.Request(next_page, callback=self.parse) 

我很确定我知道发生了什么,过去遇到过类似的问题,并且当您从回调将其发送回解析的最后一个函数运行下一页时查看您的脚本......其中我假设下一页的链接在那个实例 http 响应上...所以只需将回调更改为 parse_ad_overview ...

【讨论】:

    猜你喜欢
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-25
    • 2018-07-03
    相关资源
    最近更新 更多