1、爬虫(Spiders)
Spider类定义了如何爬取某个(或某些)网站。包括爬取的动作(例:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。
===>则Spider就是定义的爬取动作及分析某个网页。
对于Spider,爬取循环做以下的事:
- 首先生成抓取第一个URL的初始request,request下载完成后生成response,然后指定对response要使用的回调函数。通过调用start_requests()方法(默认情况下)为start_urls中指定的URL生成初始的Request以及将parse方法作为回调函数。 【注:可以自己重写start_requests()方法】
- 在回调函数中,解析Response(网页)并返回带有提取的数据的dict,Item对象,Request对象或这些对象的可迭代容器。这些请求还将包含回调(可能是相同的),然后由Scrapy下载,然后由指定的回调函数处理它们的响应。
- 在回调函数中,通常使用选择器来解析页面内容(但也可以使用Beautiful Soup或者lxml),并使用解析的数据生成Item。
- 最后,从爬虫返回的Item通常将持久存储到数据库(在某些Item Pipeline中)或使用Feed导出文件。
这个循环适用于任何种类的Spider,Scrapy实现了不同种类的默认spider用于不同需求。
2、Class scrapy.spiders.Spider
- 最简单的爬虫,每个其他爬虫必须继承该类(包括 Scrapy 自带的一些爬虫,以及你自己写的爬虫)。
- 它不提供任何特殊功能。
- 它只是提供了一个默认的start_requests()实现,它读取并请求爬虫start_urls属性,并为每个结果响应调用爬虫的parse方法。
其中一些常用的参数为:
(1)name:爬虫名称,重要,因为最后需要运行程序。scrapy crawl name
(2)allowed_domains:可选。包含了此爬虫允许抓取的域的列表。
(3)start_urls:URL列表。当没有指定特定 URL 时,爬虫将从从该列表中开始抓取。
因此,爬取的第一个页面将是这里列出的某个 URL。后续的 URL 将根据包含在起始 URL 中的数据连续生成。
(4)start_requests:此方法必须返回一个可迭代对象(iterable),该对象包含了 spider 用于爬取的第一个Request。
- 当 spider 启动时且未指定特定的 URL 时,Scrapy 会调用该方法(start_requests)。
- 如果指定了特定的 URL,则使用 make_requests_from_url() 来创建 Request 对象。此方法仅被调用一次,因此将其作为生成器实现是安全的。该方法的默认实现是使用 start_urls 的 url 生成 Request。
- 若想要修改最初爬取某个网站的Request对象,可重写该方法start_requests。
- 如下面的例子,在启动时通过使用post请求登录:
class MySpider(scrapy.Spider):
name = 'myspider'
def start_requests(self):
return [scrapy.FormRequest("http://www.example.com/login",formdata={'user': 'john', 'pass': 'secret'}, callback=self.logged_in)]
def logged_in(self, response):
#该处可以提取链接来跟踪和返回每个链接的请求并带有一个回调函数
pass
(5)make_requests_from_url(url):该方法接受一个URL并返回用于爬取的 Request 对象。 该方法在初始化request时被 start_requests() 调用,也被用于转化url为request。默认未被复写(overridden)的情况下,该方法返回的Request对象中, parse() 作为回调函数,dont_filter参数也被设置为开启。
(6)parse(response):当response没有指定回调函数时,这是Scrapy用来处理下载的response的默认方法。parse 方法负责处理response并返回所抓取的数据以及跟进的URL。Spider 对其他的Request的回调函数也有相同的要求。
参数:response(Response) - 用于分析的response
(7)log(message[, level, component]):通过 Spider 的 logger 发送日志消息,保留向后兼容性。
(8)closed(reason):当spider关闭时,该函数被调用。 该方法提供了一个替代调用signals.connect()来监听 [spider_closed] 信号的快捷方式。
补充:class scrapy.spiders.Spider的三个例子
例1:最基础
import scrapy class MySpider(scrapy.Spider): name='example.com' allowed_domains=['example.com'] start_urls=[ 'http://www.example.com/1.html', 'http://www.example.com/2.html', 'http://www.example.com/3.html', ] def parse(self,response): self.logger.info('爬取网址:{}'.format(response.url))
例2:在单个回调函数中返回多个Request以及Item
import scrapy class MySpider(scrapy.Spider): name='example.com' allowed_domains=['example.com'] start_urls=[ 'http://www.example.com/1.html', 'http://www.example.com/2.html', 'http://www.example.com/3.html', ] def parse(self,response): for h3 in response.xpath('//h3').extract(): yield {'title':h3} for url in response.xpath('//a/@href').extract(): yield scrapy.Request(url,callback=self.parse)
例3:除了start_urls,可直接使用start_requests(),也可以使用items来给予数据更多的结构性
import scrapy from myproject.items import MyItem class MySpider(scrapy.Spider): name='example.com' allowed_domains=['example.com'] def start_requests(self): yield scrapy.Request(url='http://www.example.com/1.html',callback=self.parse) yield scrapy.Request(url='http://www.example.com/2.html', callback=self.parse) yield scrapy.Request(url='http://www.example.com/3.html', callback=self.parse) def parse(self,response): for h3 in response.xpath('//h3').extract(): item=MyItem() item['title']=h3 yield item for url in response.xpath('//a/@href').extract(): yield scrapy.Request(url,callback=self.parse)
3、class scrapy.spiders.CrawlSpider
最常用的爬行常规网站的spider,因为它通过定义一组规则为跟进链接提供了一个方便的机制。
(1)除了从Spider继承的属性(您必须指定),这个类支持一个新的属性:rule
(2)该spider也提供了一个可复写(overrideable)的方法:parse_start_url(response)
对于 start_urls 中url所对应的 response 调用此方法。它允许解析初始响应,并且必须返回 Item 对象,Request 对象或包含其中任何对象的iterable。
(3-1)link_extractor 是一个 链接提取器(Link Extractor)对象,它定义如何从要爬取的页面提取链接。
(3-2)callback 是一个 callable 或 string(在这种情况下,该spider中同名的函数将会被调用),使用 link_extractor 从 Response 对象中提取的每个链接将会调用该函数。该回调接函数收一个 response 作为它的第一个参数,并且必须返回一个包含 Item 及(或)[Request] 对象(或它们的任何子类)的列表。
警告:当编写爬虫规则时,避免使用 parse 作为回调,因为 CrawlSpider
使用parse方法本身来实现其逻辑。如果覆盖 parse 方法,crawl spider 将会运行失败。
补充:class scrapy.spiders.CrawlSpider的例子
import re import scrapy from scrapy.spider import CrawlSpider,Rule from scrapy.linkextractors import LinkExtractor class MySpider(CrawlSpider): name='example.com' allowed_domains=['example.com'] start_urls=['http://www.example.com'] rules = ( Rule(LinkExtractor(allow=('category\.php'),deny=('subsection\.php'))), Rule(LinkExtractor(allow=('item\.php')),callback='parse_item'), ) def parse_item(self,response): self.logger.info('当前爬取网址为:{}'.format(response.url)) item=scrapy.Item() id=response.xpath('//td[@id="team_id"]/text()').extract()[0] item['id']=re.findall('(\d+)',id)[0] item['name']=response.xpath('//td[@id="team_name"]/text()').extract()[0] item['description']=response.xpath('//td[@id="item_description"]/text()').extract()[0] return item
说明:该spider将从example.com的首页开始爬取,获取category以及item的链接并对后者使用parse_item方法。
当item获得返回(response)时,将使用xpath处理HTML并生成一些数据填入Item中。