【问题标题】:scrapy.Request does not callback my functionscrapy.Request 不回调我的函数
【发布时间】:2023-04-10 04:35:01
【问题描述】:

如果我的问题太琐碎,我很抱歉,但从今天早上起我就陷入困境......我是scrapy的新手,我已经阅读了文档,但我还没有找到答案......

我写了这个蜘蛛,当我在rules = (Rule(LinkExtractor(), callback='parse_body'),) 中调用parse_body 时,它确实:

tchatch = response.xpath('//div[@class="ProductPriceBox-item detail"]/div/a/@href').extract()
            print('\n TROUVE \n')
            print(tchatch)
            print('\n DONE \n')

但是当我在代码中的任何地方重命名函数 parse_body 时,只需 parse,它就可以了:

    print('\n EN FAIT, ICI : ', response.url, '\n')

似乎我的scrapy.Request 请求从未被调用.... 我什至打印了很多无用的东西来了解我的代码是否正在运行这些函数,但它除了上面写的print 之外什么都没有打印。

有什么想法吗?

# -*- coding: utf-8 -*-
import scrapy
import re
import numbers
from fnac.items import FnacItem
from urllib.request import urlopen
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from bs4 import BeautifulSoup

class Fnac(CrawlSpider):
    name = 'FnacCom'
    allowed_domains = ['fnac.com']
    start_urls = ['http://musique.fnac.com/a10484807/The-Cranberries-Something-else-CD-album']

    rules = (
        Rule(LinkExtractor(), callback='parse_body'),
    )

    def parse_body(self, response):
        item = FnacItem()

        nb_sales = response.xpath('//body//table[@summary="données détaillée du vendeur"]/tbody/tr/td/span/text()').re(r'([\d]*) ventes')
        country = response.xpath('//body//table[@summary="données détaillée du vendeur"]/tbody/tr/td/text()').re(r'([A-Z].*)')

        item['nb_sales'] = ''.join(nb_sales).strip()
        item['country'] = ''.join(country).strip()

        print(response.url)
        test_list = response.xpath('//a/@href')
        for test_list in response.xpath('.//div[@class="ProductPriceBox-item detail"]'):
            tchatch = response.xpath('//div[@class="ProductPriceBox-item detail"]/div/a/@href').extract()
            print('\n TROUVE \n')
            print(tchatch)
            print('\n DONE \n')

        yield scrapy.Request(response.url, callback=self.parse_iframe, meta={'item': item})

    def parse_iframe(self, response):
        f_item1 = response.meta['item']

        print('\n EN FAIT, ICI : ', response.url, '\n')
        soup = BeautifulSoup(urlopen(response.url), "lxml")
        iframexx = soup.find_all('iframe')
        if (len(iframexx) != 0):
            for iframe in iframexx:
                yield scrapy.Request(iframe.attrs['src'], callback=self.extract_or_loop, meta={'item': f_item1})
        else:
            yield scrapy.Request(response.url, callback=self.extract_or_loop, meta={'item': f_item1})

    def extract_or_loop(self, response):
        f_item2 = response.meta['item']

        print('\n PEUT ETRE ICI ? \n')
        address = response.xpath('//body//div/p/text()').re(r'.*Adresse \: (.*)\n?.*')
        email = response.xpath('//body//div/ul/li[contains(text(),"@")]/text()').extract()
        name = response.xpath('//body//div/p[@class="customer-policy-label"]/text()').re(r'Infos sur la boutique \: ([a-zA-Z0-9]*\s*)')
        phone = response.xpath('//body//div/p/text()').re(r'.*Tél \: ([\d]*)\n?.*')
        siret = response.xpath('//body//div/p/text()').re(r'.*Siret \: ([\d]*)\n?.*')
        vat = response.xpath('//body//div/text()').re(r'.*TVA \: (.*)')

        if (len(name) != 0):
            print('\n', name, '\n')
            f_item2['name'] = ''.join(name).strip()
            f_item2['address'] = ''.join(address).strip()
            f_item2['phone'] = ''.join(phone).strip()
            f_item2['email'] = ''.join(email).strip()
            f_item2['vat'] = ''.join(vat).strip()
            f_item2['siret'] = ''.join(siret).strip()
            yield f_item2
        else:
            for sel in response.xpath('//html/body'):
                list_urls = sel.xpath('//a/@href').extract()
                list_iframe = response.xpath('//div[@class="ProductPriceBox-item detail"]/div/a/@href').extract()
                if (len(list_iframe) != 0):
                    for list_iframe in list_urls:
                        print('\n', list_iframe, '\n')
                        print('\n GROS TCHATCH \n')
                        yield scrapy.Request(list_iframe, callback=self.parse_body)
                for url in list_urls:
                    yield scrapy.Request(response.urljoin(url), callback=self.parse_body)

【问题讨论】:

  • 如果您甚至不使用真正的规则,为什么不使用Spider 而不是CrawlSpider
  • 因为如果我把Spider而不是CrawlSpider,我有这个错误raise NotImplementedError
  • 这可能是因为你没有按原样实现 parse 方法。
  • 我该怎么做?我对scrapy和python的很多东西都不了解...我必须将parse_body更改为parse吗?或者写另一个函数叫parse

标签: python parsing web-scraping scrapy


【解决方案1】:

在CrawlSpider的scrapy文档中,有一个警告:

警告

在编写爬虫规则时,避免使用parse 作为回调,因为CrawlSpider 使用parse 方法本身来实现其逻辑。所以如果你重写parse 方法,爬虫将不再工作。

你可以看看这个,这里是link

【讨论】:

  • 谢谢,我会检查链接...请问您对其他问题有什么想法吗?如果我写了 parse_body,我的请求也不起作用......
  • @P.Postrique 我尝试调试您的代码我所做的第一件事是将parse_body 更改为parse_start_url,这允许调用第二个函数parse_iframe,但在此函数中您正在访问的链接是这样被重定向的:2017-07-13 12:31:51 [scrapy.downloadermiddlewares.redirect] 调试:从 secure.fnac.com/account/alerting 重定向 (302) 到 secure.fnac.com/Account/Logon/…> > 这是登录页面
  • 只是改名字,我的函数就被调用了,是不是很奇怪?我不明白... parse_iframe 只被调用一次是否正常?
  • 不,正如我之前所说,它不是始终致力于使用您想要继承的 Scrapy 类中的方法。但这里的重点是重定向到登录页面,似乎某个 url 受到保护
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多