gpt4 book ai didi

python - 为什么我的 Scrapy CrawlSpider 规则不起作用?

转载 作者:太空狗 更新时间:2023-10-29 18:20:35 28 4
gpt4 key购买 nike

我已经成功地使用 Scrapy 编写了一个非常简单的爬虫,具有这些给定的约束:

  • 存储所有链接信息(例如: anchor 文本、页面标题),因此有 2 个回调
  • 使用 CrawlSpider 来利用规则,因此没有 BaseSpider

它运行良好,除了如果我向第一个请求添加回调它不会执行规则!

这是我的代码:(有效但不正确,有一个实例)

from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request
from scrapySpider.items import SPage
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor

class TestSpider4(CrawlSpider):
name = "spiderSO"
allowed_domains = ["cumulodata.com"]
start_urls = ["http://www.cumulodata.com"]
extractor = SgmlLinkExtractor()

def parse_start_url(self, response):
#3
print('----------manual call of',response)
self.parse_links(response)
print('----------manual call done')
# 1 return Request(self.start_urls[0]) # does not call parse_links(example.com)
# 2 return Request(self.start_urls[0],callback = self.parse_links) # does not call parse_links(example.com)

rules = (
Rule(extractor,callback='parse_links',follow=True),
)

def parse_links(self, response):
hxs = HtmlXPathSelector(response)
print('----------- manual parsing links of',response.url)
links = hxs.select('//a')
for link in links:
title = link.select('@title')
url = link.select('@href').extract()[0]
meta={'title':title,}
yield Request(url, callback = self.parse_page,meta=meta)

def parse_page(self, response):
print('----------- parsing page: ',response.url)
hxs = HtmlXPathSelector(response)
item=SPage()
item['url'] = str(response.request.url)
item['title']=response.meta['title']
item['h1']=hxs.select('//h1/text()').extract()
yield item

我已经尝试通过 3 种方式解决这个问题:

  • 1:返回带有起始 url 的请求 - 不执行规则
  • 2:与上面相同,但带有对 parse_links 的回调 - 同样的问题
  • 3:调用parse_links抓取开始url后,通过实现parse_start_url,函数不会被调用

这是日志:

----------manual call of <200 http://www.cumulodata.com>)

----------manual call done

#No '----------- manual parsing links', so `parse_links` is never called!

版本

  • python 2.7.2
  • 抓取 0.14.4

最佳答案

这是一个完美工作的抓取刀:

from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request
from scrapySpider.items import SPage
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor

class TestSpider4(CrawlSpider):
name = "spiderSO"
allowed_domains = ["cumulodata.com"]
start_urls = ["http://www.cumulodata.com/"]

extractor = SgmlLinkExtractor()

rules = (
Rule(extractor,callback='parse_links',follow=True),
)

def parse_start_url(self, response):
list(self.parse_links(response))

def parse_links(self, response):
hxs = HtmlXPathSelector(response)
links = hxs.select('//a')
for link in links:
title = ''.join(link.select('./@title').extract())
url = ''.join(link.select('./@href').extract())
meta={'title':title,}
cleaned_url = "%s/?1" % url if not '/' in url.partition('//')[2] else "%s?1" % url
yield Request(cleaned_url, callback = self.parse_page, meta=meta,)

def parse_page(self, response):
hxs = HtmlXPathSelector(response)
item=SPage()
item['url'] = response.url
item['title']=response.meta['title']
item['h1']=hxs.select('//h1/text()').extract()
return item

变化:

  1. 已实现 parse_start_url - 不幸的是,当您为第一个请求指定回调时,规则不会被执行。这是 Scrapy 内置的,我们只能通过变通方法来解决这个问题。所以我们在这个函数中做了一个 list(self.parse_links(response)) 。为什么 list()?因为 parse_links 是一个生成器,而生成器是惰性的。所以我们需要明确地完全调用它。

  2. cleaned_url = "%s/?1"% url if not '/' in url.partition('//')[2] else "%s?1"% url - 这里发生了几件事:

    一个。我们在 URL 的末尾添加 '/?1' - 由于 parse_links 返回重复的 URL,Scrapy 将它们过滤掉。避免这种情况的更简单方法是将 dont_filter=True 传递给 Request()。但是,您的所有页面都是相互链接的(从 pageAA 返回索引,等等)并且此处的 dont_filter 会导致太多重复的请求和项目。

    if not '/' in url.partition('//')[2] - 同样,这是因为您网站中的链接。其中一个内部链接指向“www.cumulodata.com”,另一个指向“www.cumulodata.com/”。由于我们明确添加了一种允许重复的机制,因此这导致了一个额外的项目。由于我们需要完美,所以我实现了这个 hack。

  3. title = ''.join(link.select('./@title').extract()) - 您不想返回节点,而是返回数据.另外:''.join(list) 在空列表的情况下优于 list[0]。

恭喜您创建了一个测试网站,它提出了一个奇怪的问题 - 重复既是必要的也是不需要的!

关于python - 为什么我的 Scrapy CrawlSpider 规则不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12736257/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com