Spiders
Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
对spider来说,爬取的循环类似下文:
1. 以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。
spider中初始的request是通过调用 start_requests() 来获取的。 start_requests() 读取 start_urls 中的URL, 并以 parse 为回调函数生成 Request 。
2. 在回调函数内分析返回的(网页)内容,返回 Item 对象或者 Request 或者一个包括二者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。
3. 在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。
4. 最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)或使用 Feed exports 存入到文件中。
虽然该循环对任何类型的spider都(多少)适用,但Scrapy仍然为了不同的需求提供了多种默认spider。 之后将讨论这些spider。
scrapy.Spider
Spider是最简单的spider。每个其他的spider必须继承自该类(包括Scrapy自带的其他spider以及我们自己编写的spider)。 Spider并没有提供什么特殊的功能。 其仅仅请求给定的 start_urls/start_requests ,并根据返回的结果(resulting responses)调用spider的 parse 方法。
name:
定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。 不过您可以生成多个相同的spider实例(instance),这没有任何限制。 name是spider最重要的属性,而且是必须的。
如果该spider爬取单个网站(single domain),一个常见的做法是以该网站(domain)(加或不加 后缀 )来命名spider。 例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite 。allowed_domains:
可选,包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进。start_urls:
URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。custom_settings:
一个在运行时会覆盖项目设置的字典。它必须设置为类属性,因为设置在实例化之前更新。可以使用的设置字段可以参考这里Built-in settings reference。crawler:
这个属性会在类初始化以后通过from_crawler()方法获得,并链接到此Spider实例绑定到的Crawler对象。
Crawlers在项目中封装了大量的组件用于他们的单个条目访问(例如扩展,中间件,信号管理器等)。 有关详情,请参阅抓取工具API。settings:
运行此Spider的配置。 这是一个设置实例,有关此主题的详细介绍,请参阅设置主题。logger:
使用Spider的name创建的Python记录器。我们可以通过它来发送在Spider运行时产生的日志消息。from_crawler(crawler, *args, **kwargs)
这是Scrapy用来创建Spider的方法。
你可能不需要直接覆盖它,因为默认实现充当init ()方法的代理,使用给定的参数args和命名参数kwargs调用它。
经管如此,该方法在创建新实例的时候会设置crawler和settings,以便稍后再Spider程序中访问。参数含义
crawler(Crawler实例):将于Spider绑定的crawler
args(list):将要传递到_init_()中的参数
kwargs(dict):传递给_init_()关键字参数start_requests():
该方法返回一个可迭代的对象,包含了Spider用于爬取的第一个Request。
当spider启动爬取并且未制定URL时,该方法被调用。 当指定了URL时,make_requests_from_url() 将被调用来创建Request对象。 该方法仅仅会被Scrapy调用一次,因此我们可以将其实现为生成器。
该方法默认通过make_requests_from_url()来为start_urls中的每一个url创建Requests(请求)。
如果想要修改最初爬取某个网站的Request对象,我们可以重写(override)该方法。 例如,如果我们需要在启动时以POST登录某个网站:
import scrapy
class LogginSpider(scrapy.Spider):
name = 'loggin_test'
def start_requests(self):
return [scrapy.FormRequest('http://quotes.toscrape.com/login',
formdata={'password': '1234', 'username': '1234'},
callback= self.loggin)]
def loggin(self, response):
print response.body
make_requests_from_url(url):
该方法接受一个URL并且返回一个Request对象(或者Request列表)用于爬取。此方法用于在start_requests()方法中构造初始请求,并且通常用于将URL转换为请求。
除非重写,否则该方法返回一个以parse()作为回调方法的Request,并启用dont_filter参数。parse(response)
当response没有指定回调函数时,该方法是Scrapy处理下载的response的默认方法。
parse 负责处理response并返回处理的数据以及(/或)跟进的URL。 Spider 对其他的Request的回调函数也有相同的要求。
这个方法及其他Request的回调方法都必须返回一个可迭代的Request对象,或字典,或Item对象。log(message[,level, component])
使用 scrapy.log.msg() 方法记录(log)message。 log中自动带上该spider的 name 属性closed(reason)
该方法在Spider关闭时调用,该方法提供了一个替代调用signals.connect()来监听 spider_closed 信号的快捷方式。
通用Spider
Scrapy附带一些有用的通用蜘蛛,你可以使用它来子类化你的蜘蛛。 他们的目的是为一些常见的抓取案例提供方便的功能,例如根据某些规则跟踪网站上的所有链接,从站点地图抓取或解析XML / CSV Feed
在接下来的例子中,我们首先要在项目根目录下的items.py文件中新建TestItem类:
import scrapy
class TestItem(scrapy.Item):
id = scrapy.Field()
name = scrapy.Field()
description = scrapy.Field()
CrawlSpider
这是最常用的爬行常规网站的Spider,因为它通过定义一组规则为跟随链接提供了一种方便的机制。 它可能不是最适合特定网站或项目,但它是通用的几种情况下,所以我们可以从它开始,覆盖它根据需要更多的自定义功能,或只是实现自己的Spider。
除了继承自Spider的属性,该类还有一个新的属性:
- rules
一个包含一个(或多个) Rule 对象的集合(list)。 每个 Rule 对爬取网站的动作定义了特定表现。 Rule对象在下边会介绍。 如果多个rule匹配了相同的链接,则根据他们在本属性中被定义的顺序,第一个会被使用。
CrawlSpider也提供了一个可以复写的方法:
-parse_start_url(response):
start_urls响应时调用此方法。 它允许解析初始响应,并且必须返回Item对象,Request对象或包含两者的iterable。
Crawling rules
Rule 构造函数的参数:
- link_extractor:是一个Link Extractor 对象,它定义了如何从爬取的页面中提取链接。
- callback : 是一个回调接口或者String(Spider中同名函数将被调用),从link_extractor中每获取到链接时将会调用该函数。该回调函数接受一个response作为其第一个参数, 并返回一个包含 Item 以及(或) Request 对象(或者这两者的子类)的列表(list)。
注意
当编写爬虫规则的时候,应避免使用parse()做为回调函数,因为CrawlSpider 使用parse()实现其逻辑。
- cb_kwargs : 包含传递给回调函数的参数(keyword argument)的字典。
- follow : 是一个布尔(boolean)值,指定了根据该规则从response提取的链接是否需要跟进。 如果 callback 为None, follow 默认设置为 True ,否则默认为 False 。
- process_links : 是一个callable或string(该spider中同名的函数将会被调用)。 从link_extractor中获取到链接列表时将会调用该函数。该方法主要用来过滤。
- process_request : 是一个callable或string(该spider中同名的函数将会被调用)。 该规则提取到每个request时都会调用该函数。该函数必须返回一个request或者None。 (用来过滤request)。
XMLFeedSpider
XMLFeedSpider被设计用于通过迭代各个节点来分析XML源(XML feed)。 迭代器可以从 iternodes , xml , html 选择。 鉴于 xml 以及 html 迭代器需要先读取所有DOM再分析而引起的性能问题, 一般还是推荐使用 iternodes 。 不过使用 html 作为迭代器能有效应对错误的XML。
在使用的时候我们必须通过定义类属性来设置 iterator 和 tag 的 名称:
- iterator
用于确定使用哪个迭代器的string。可选项有:
- iternodes: 一个高性能的基于正则表达式的迭代器
- html : 使用 Selector 的迭代器。 需要注意的是该迭代器使用DOM进行分析,其需要将所有的DOM载入内存, 当数据量大的时候会产生问题。
- xml : 使用 Selector 的迭代器。 需要注意的是该迭代器使用DOM进行分析,其需要将所有的DOM载入内存, 当数据量大的时候会产生问题
itertag
包含开始迭代的节点的名称itertag = ‘product’namespaces:
一个由 (prefix, url) 元组(tuple)所组成的list。 其定义了在该文档中会被spider处理的可用的namespace。 prefix 及 uri 会被自动调用 register_namespace() 生成namespace。
除了这些新添加的属性外,我们也可以复写一些方法:
adapt_response(responsed):
该方法在Spider解析response之前被调用。我们可以在response在被分析之前修改其内容。该方法接收一个responsez并且也返回一个response(可以是相同的)。parse_node(response, selector):
对于与提供的标记名称(itertag)匹配的节点,将调用此方法。 接收每个节点的响应和选择器。 覆盖此方法是必需的。 否则,你的Spider不会工作。 此方法必须返回Item对象,Request对象或包含其中任何对象的iterable。process_results(response, results):
对于由Spider返回的每个结果(项目或请求),将调用此方法,并且它将在将结果返回到框架核心之前执行所需的任何最后处理,例如设置项目ID。 它接收结果列表和产生那些结果的响应。 它必须返回结果列表(项目或请求)。
CSVFeedSpider
这个Spider非常类似于XMLFeedSpider,除了它迭代行,而不是节点。 在每次迭代中调用的方法是parse_row()。
- delimiter:
CSV文件中字段组成的字符串,默认以”,”隔开。
quotechar:
同上,默认’ ” ‘。headers:
文件CSV Feed中包含的行的列表,用于从中提取字段。parse_row(response, row):
使用CSV文件的每个提供(或检测到)标头的键接收响应和dict(表示每行)。 此Spider还提供了覆盖adapt_response和process_results方法用于预处理和后处理目的的机会。
SitemapSpider
SitemapSpider允许您通过使用Sitemaps发现网址来抓取网站。
它支持嵌套Sitemap和从robots.txt发现Sitemap网址。
sitemao_urls:
抓取的网站的网址列表。
还可以指向robots.txt,自动解析从中提取Sitemap网址。sitemap_follow:
应遵循的网站地图的正则表达式列表。 这只适用于使用指向其他Sitemap文件的Sitemap索引文件的网站。
默认情况下,将跟踪所有网站地图sitemap_alternate_links:
指定是否应遵循一个网址的替代链接。 这些是同一网站在同一网址中传递的另一种语言的链接。