Python 过了一段时间,scrapy停止爬行并交出物品,但继续运行

Python 过了一段时间,scrapy停止爬行并交出物品,但继续运行,python,web-scraping,scrapy,web-crawler,Python,Web Scraping,Scrapy,Web Crawler,我已经编写了一些零碎的代码,应该能够在一系列城市中循环,转到这些城市的特定页面,获取该页面上表中的所有数据,并遍历该城市表中的所有页面。 我的代码运行了,但过了一段时间似乎超时了,我开始在日志中记录这一点: 2020-12-16 18:47:47 [yjs] INFO: Parsing table and getting job data for page url http://www.yingjiesheng.com/other-morejob-1372.html 2020-12-16 18:

我已经编写了一些零碎的代码,应该能够在一系列城市中循环,转到这些城市的特定页面,获取该页面上表中的所有数据,并遍历该城市表中的所有页面。 我的代码运行了,但过了一段时间似乎超时了,我开始在日志中记录这一点:

2020-12-16 18:47:47 [yjs] INFO: Parsing table and getting job data for page url http://www.yingjiesheng.com/other-morejob-1372.html
2020-12-16 18:48:27 [scrapy.extensions.logstats] INFO: Crawled 113 pages (at 2 pages/min), scraped 111 items (at 2 items/min)
2020-12-16 18:49:27 [scrapy.extensions.logstats] INFO: Crawled 113 pages (at 0 pages/min), scraped 111 items (at 0 items/min)
2020-12-16 18:50:27 [scrapy.extensions.logstats] INFO: Crawled 113 pages (at 0 pages/min), scraped 111 items (at 0 items/min)
2020-12-16 18:51:27 [scrapy.extensions.logstats] INFO: Crawled 113 pages (at 0 pages/min), scraped 111 items (at 0 items/min)
2020-12-16 18:52:27 [scrapy.extensions.logstats] INFO: Crawled 113 pages (at 0 pages/min), scraped 111 items (at 0 items/min)
这似乎发生在随机的时间点。我第一次运行它时,我在66页之后开始得到这个。下面是我的蜘蛛代码:

URLROOT = "https://www.yingjiesheng.com/"
CITIES = {"beijing": "北京"}

class YjsSpider(scrapy.Spider):
    name = "yjs"

    def start_requests(self):
        # loop through cities and pass info
        for key, value in CITIES.items():
            self.logger.info('Starting requests for %s', key)
            url = URLROOT + str(key)
            yield scrapy.Request(
                url=url, callback=self.retrieve_tabsuffix, 
                meta={'city': key, 'city_ch': value},
                encoding='gb18030'
            )

    def retrieve_tabsuffix(self, response):
        city = response.meta['city']
        city_ch = response.meta['city_ch']

        morepages = response.xpath(
            '//*[contains(concat( " ", @class, " " ), concat( " ", "mbth", " " ))]')
        morepage_html = morepages.css("a::attr(href)").get()
        if "-morejob-" in morepage_html:
            jobpage_one = f"{URLROOT}{city}-morejob-1.html"
        elif "list_" in morepage_html:
            jobpage_one = f"{URLROOT}{city}/list_1.html"
        yield response.follow(
            url=jobpage_one, 
            callback=self.retrieve_tabhtmls,
            meta={'city': city, 'city_ch': city_ch},
            encoding='gb18030')


    def retrieve_tabhtmls(self, response):
        city = response.meta['city']
        city_ch = response.meta['city_ch']
        self.logger.info('Encodings are %s, %s', encoding1, encoding2)

        # htmls
        listhtmls = response.xpath(
                '//*[contains(concat( " ", @class, " " ), concat( " ", "clear", " " ))]').get()
 
        totalrecords = response.xpath(
            '//*[contains(concat( " ", @class, " " ), concat( " ", "act", " " ))]').get()
        self.logger.info("totalrecords: %s", totalrecords)

        # identify the last page number
        listhtmls = listhtmls.split("a href=\"")
        for listhtml in listhtmls:
            if "last page" in listhtml:
                lastpagenum = re.findall(r"\d+", listhtml)[0]
        morejobpages = list(range(1, int(lastpagenum) + 1))
        self.logger.info("total number tables %s", lastpagenum)

        self.logger.info('Getting all table page URLs for %s', city)
        morejobpages_urls = [
                "http://www.yingjiesheng.com/{}/list_{}.html".format(city, i) for i in morejobpages]

        self.logger.info(morejobpages)
        yield from response.follow_all(
            urls=morejobpages_urls,
            callback=self.parse_tab,
            meta={'city': city, 'city_ch': city_ch,
                  'totalrecords': totalrecords},
            encoding='gb18030')
    

    def parse_tab(self, response):
        city = response.meta['city']
        city_ch = response.meta['city_ch']
        totalrecords = response.meta['totalrecords']
        self.logger.info('Parsing table and getting job data for page url %s', response.url)

        # table content
        tabcontent = response.xpath(
            '//*[(@id = "tb_job_list")]')
        # list of rows
        tabrows = tabcontent.css("tr.jobli").getall()

        item = YjsTable()
        item['table'] = tabrows
        item['time_scraped'] = datetime.datetime.now().strftime(
                "%m/%d/%Y %H:%M:%S")
        item['city'] = city
        item['city_ch'] = city_ch
        item['totalrecords'] = totalrecords
        item['pageurl'] = response.url
        yield item
这是我发现的唯一一篇似乎遇到相同问题的文章,但他们是从SQL数据库中提取的,而我不是

有人知道为什么scrapy会工作一段时间,然后突然停止请求页面和获取数据,但继续运行吗

编辑:我使用调试日志设置重新运行,得到以下信息:

2020-12-17 10:35:47 [scrapy.extensions.logstats] INFO: Crawled 41 pages (at 0 pages/min), scraped 39 items (at 0 items/min)
2020-12-17 10:35:49 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET http://www.yingjiesheng.com/app/job.php?Action=FullTimeMore&Location=guangzhou&Source=Other&Page=86> from <GET http://www.yingjiesheng.com/guangzhou-morejob-86.html>
2020-12-17 10:36:06 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET http://www.yingjiesheng.com/guangzhou-morejob-86.html> from <GET http://www.yingjiesheng.com/app/job.php?Action=FullTimeMore&Location=guangzhou&Source=Other&Page=86>
2020-12-17 10:36:24 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET http://www.yingjiesheng.com/app/job.php?Action=FullTimeMore&Location=guangzhou&Source=Other&Page=85> from <GET http://www.yingjiesheng.com/guangzhou-morejob-85.html>
2020-12-17 10:35:47[scrapy.extensions.logstats]信息:抓取41页(0页/分钟),抓取39项(0项/分钟)
2020-12-17 10:35:49[scrapy.downloadermiddleware.redirect]调试:重定向(301)到
2020-12-17 10:36:06[scrapy.downloadermiddleware.redirect]调试:重定向(302)到
2020-12-17 10:36:24[scrapy.downloadermiddleware.redirect]调试:重定向(301)到

看起来我被重定向了,但是它没有成功地从重定向中抓取信息,然后转到下一页。有人知道你会如何让scrapy一直尝试一个页面直到成功吗?或者,如果有更好的方法来处理这个问题?

首先,您需要检查,以便能够更好地记录您的情况,只需设置
LOG\u LEVEL='DEBUG'
就可以更简单了,这样您就可以看到正在发生的一切,看起来它现在已经设置为“INFO”

可能会发生的事情是,爬行器一直在查找请求,但所有请求都被拒绝,因此它们不被计算为“页面”,它们可能是404、503等等

你也可以有一些页面有很长的超时时间,scrapy不会停止工作,因为它的本质是异步的,所以日志可能会一直出现,即使scrapy正在等待一个正确的响应

您还可以将您的scrapy项目配置为这样工作(永不结束,只需继续生活),但从您共享的内容来看,情况并非如此。尽管如此,还是值得检查您的扩展、管道和中间件在做什么,这样您就可以确保它们不会干扰您的spider


你可以随时杀死蜘蛛,但要确保它自行停止,这样它也会返回一些统计信息,这些信息非常能揭示执行过程中发生的情况。

首先,你需要检查,以便更好地记录你的情况,只需设置
LOG_LEVEL='DEBUG'
就可以更简单了,这样您就可以看到正在发生的一切,看起来它现在被设置为“INFO”

可能会发生的事情是,爬行器一直在查找请求,但所有请求都被拒绝,因此它们不被计算为“页面”,它们可能是404、503等等

你也可以有一些页面有很长的超时时间,scrapy不会停止工作,因为它的本质是异步的,所以日志可能会一直出现,即使scrapy正在等待一个正确的响应

您还可以将您的scrapy项目配置为这样工作(永不结束,只需继续生活),但从您共享的内容来看,情况并非如此。尽管如此,还是值得检查您的扩展、管道和中间件在做什么,这样您就可以确保它们不会干扰您的spider


你可以随时杀死蜘蛛,但要确保它自行停止,这样它也会返回一些统计信息,这些信息非常能揭示执行过程中发生的情况。

我解决了我的问题。如下面的日志所示,这些链接向不同的链接抛出301重定向,然后抛出302并重定向回原始链接。然后scrapy没有删除页面,因为这是一个重复的请求

2020-12-17 10:35:49 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET http://www.yingjiesheng.com/app/job.php?Action=FullTimeMore&Location=guangzhou&Source=Other&Page=86> from <GET http://www.yingjiesheng.com/guangzhou-morejob-86.html>
2020-12-17 10:36:06 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET http://www.yingjiesheng.com/guangzhou-morejob-86.html> from <GET http://www.yingjiesheng.com/app/job.php?Action=FullTimeMore&Location=guangzhou&Source=Other&Page=86>
2020-12-17 10:35:49[scrapy.downloadermiddleware.redirect]调试:将(301)重定向到
2020-12-17 10:36:06[scrapy.downloadermiddleware.redirect]调试:重定向(302)到
为了解决这个问题,我在
响应中添加了参数
dont\u filter=True
。follow\u all()
调用,这样使用该函数调用发出的请求就不会过滤出重复的内容。我还将以下内容添加到我的
settings.py
文件中以获取调试帮助:
DUPEFILTER\u DEBUG=True


在scrapy中处理重复请求的更多答案可以找到。

我解决了我的问题。如下面的日志所示,这些链接向不同的链接抛出301重定向,然后抛出302并重定向回原始链接。然后scrapy没有删除页面,因为这是一个重复的请求

2020-12-17 10:35:49 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET http://www.yingjiesheng.com/app/job.php?Action=FullTimeMore&Location=guangzhou&Source=Other&Page=86> from <GET http://www.yingjiesheng.com/guangzhou-morejob-86.html>
2020-12-17 10:36:06 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET http://www.yingjiesheng.com/guangzhou-morejob-86.html> from <GET http://www.yingjiesheng.com/app/job.php?Action=FullTimeMore&Location=guangzhou&Source=Other&Page=86>
2020-12-17 10:35:49[scrapy.downloadermiddleware.redirect]调试:将(301)重定向到
2020-12-17 10:36:06[scrapy.downloadermiddleware.redirect]调试:重定向(302)到
为了解决这个问题,我在
响应中添加了参数
dont\u filter=True
。follow\u all()
调用,这样使用该函数调用发出的请求就不会过滤出重复的内容。我还将以下内容添加到我的
settings.py
文件中以获取调试帮助:
DUPEFILTER\u DEBUG=True


有关在scrapy中处理重复请求的更多答案,请参见。

谢谢!我用调试日志设置重新运行,似乎301和302重定向出现了问题。@seagullnutkin我检查了你的更新,现在你有了一个完全不同的问题(与原来的问题无关),所以我建议你再问一个问题。检查问题时,需要对站点进行大量调试并理解