这是一个效果很好的scraper:
from scrapy.contrib.spiders import CrawlSpider,Rulefrom scrapy.selector import HtmlXPathSelectorfrom scrapy.http import Requestfrom scrapySpider.items import SPagefrom scrapy.contrib.linkextractors.sgml import SgmllinkExtractorclass 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变化:
已实现
parse_start_url
-不幸的是,当你为第一个请求指定回调时,规则不会执行。这是Scrapy
内置的,我们只能通过变通办法来管理它。因此,我们list(self.parse_links(response))
在此函数内部做一个 。为什么list()
呢?因为parse_链接是一个生成器,生成器是lazy的,我们需要完全明确地调用它。cleaned_url = "%s/?1" % url if not '/' in url.partition('//')[2] else "%s?1" % url-这里发生了几件事情:
一个。我们在网址末尾添加
“ /?1”-由于
parse_links返回重复的网址,因此
Scrapy会将其过滤掉。避免这种情况的更简单方法是传递
dont_filter=True给Request()。但是,你所有的页面都是相互链接的(从pageAA返回索引,等等),dont_filter这里导致重复的请求和项目过多。
b。if not '/' in url.partition('//')[2]-同样,这是由于你网站中的链接。内部链接之一是“ www.cumulodata.com”,另一个是“ www.cumulodata.com/”。由于我们明确添加了一种允许重复的机制,因此这又增加了一项。由于我们需要完美,因此我实施了此技巧。
title = ''.join(link.select('./@title').extract())-你不想返回节点,但是要返回数据。另外:如果列表为空,''。join(list)
优于list [0]
。



