scrapy回调在功能上不起作用

时间:2017-06-24 08:53:42

标签: python-3.x scrapy

当执行第一个产量时,它不会进入函数 parse_url ,并且在执行第二个 yield 时,它将不会返回该函数解析,它就结束了。在整个过程中,没有例外。我不知道如何处理这个问题,我需要帮助。

import scrapy
import re
from crawlurl.items import CrawlurlItem

class HouseurlSpider(scrapy.Spider):
    name = 'houseurl'
    allowed_domains = ['qhd.58.com/ershoufang/']
    start_urls = ['http://qhd.58.com/ershoufang//']
    header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'
    }

    def parse(self, response):
        urls = response.xpath('//div[@class="list-info"]/h2[@class="title"]/a/@href').extract()
        next_url = response.xpath('//a[@class="next"]/@href').extract()

        for url in urls:
            yield scrapy.Request(url,headers=self.header,callback=self.parse_url)

        if next_url:
            next_url = next_url[0]
            yield scrapy.Request(next_url,headers=self.header,callback=self.parse)

    def parse_url(self,response):
        item = CrawlurlItem()
        url_obj = re.search('(http://qhd.58.com/ershoufang/\d+x.shtml).*',response.url)
        url = url_obj.group(1)
        item['url'] = url
        yield item

2 个答案:

答案 0 :(得分:2)

如果您仔细查看了日志,那么您可能已经注意到scrapy过滤了异地域请求。这意味着当scrapy尝试ping short.58.comjxjump.58.com时,它没有完成。您可以将这些域添加到Spider类中的allowed_domains过滤器,您将看到正在发送的请求。

替换:

allowed_domains = ['qhd.58.com/ershoufang/']

使用:

allowed_domains = ['qhd.58.com', 'short.58.com', 'jxjump.58.com']

它应该有效!

答案 1 :(得分:0)

问题出在你的allowed_domains条款中。它应该只包含域,没有路径。因此,您的qhd.58.com/ershoufang/项目无法识别。因此,您产生的所有网址(start_urls除外)实际上已被过滤掉,这反映在日志中:

2017-06-24 14:05:09 [scrapy.spidermiddlewares.offsite] DEBUG: Filtered offsite request to 'qhd.58.com': <GET http://qhd.58.com/ershoufang/30456249766826x.shtml>

这绝对不是你想要的。您可以通过在allowed_domains中放置一个域并在其他位置过滤不需要的URL来解决此问题,例如:在yield之前:

allowed_domains = ['qhd.58.com']
...
for url in urls:
    if 'qhd.58.com/ershoufang/' in url:
        yield response.follow(url, self.parse_url, headers=self.header)
...

通常最好使用response.follow()代替scrapy.Request(),因为前者支持相对网址。