前言
这是 Scrapy 系列学习文章之一,本章主要介绍 Spiders 相关的内容;
本文为作者的原创作品,转载需注明出处;
Spiders
Spiders 是一系列用来定义如何爬取特定网站的 classes,包括如何爬取,如何从它们的页面中提取结构化的数据;换句话说,Spiders 就是开发者用来对特定的
网址自定义爬取动作以及如何解析的地方;
从总体而言,爬取的步骤如下,
- 通过生成 initial Requests 去爬取最初的 URLS 开始,然后通过指定 callback 方法处理 requests 的 response 的返回;
最开始通过start_requests()
方法获取最开始的 requests,start_requests()
内部通过start_urls
返回,start_urls
包含了请求的 URLS;parse()
方法作为 Request 请求的回调方法; - 在该回调方法(一般指的就是
parse()
)中,通过解析 response (既网页的内容)然后返回 dicts,Item 对象,Request 对象或者是一个 iterable 的对象;返回的 Requests 同样可以包含 callback 回调函数,这些 Requests 同样将会通过 Scrapy 去下载网页内容,并通过该 callback 回调函数进行解析;(这里其实讲的就是爬取的深度了) - 在回调函数中,通过解析页面的内容,典型的解析方式是通过使用 Selectors (还可以使用 BeautifulSoup 或者是 lxml ) 生成解析后的 items (数据);
- 最后,从爬虫中返回的数据(items)将会被持续化到数据库中(通常是在 Item Pipeline 中执行)或者是通过 Feed exports 写入文件中;
虽然上述的步骤或多或少的应用到了所有类型的 spiders 中,但是仍然有为了不同目的不同类型的默认爬虫;
scrapy.Spider
1 | class scrapy.spiders.Spider |
这是最简单的爬虫,而且是其它所有的爬虫必须要继承的;它没有提供任何特殊的方法,它只提供了一个默认的start_requests()
实现,用来从start_urls
解析得到请求 requests 并发送请求 requests,然后通过调用 spider 的parse
方法来解析每一次请求所响应的 response;下面,我们就依次来看一看对应的属性,
name
用来定义 Spider 的名字,用来定位一个 spider,所以它必须是全局唯一的;但是,没有任何限制机制放置你这么做,你可以定义两个同名的 spiders,所以在编程的时候一定要小心了;
allowed_domains
一个可选的 domains 队列限制了 spiders 的爬取行为,约定只能爬取该 domains 队列中的域名;
start_urls
指定了一组 URLs 告诉 spider 从什么地方开始去进行爬取;
custom_settings
当在执行某个 spider 的时候通过它可以覆盖该 spider 所涉及的 project 范围内的 settings;它必须被定义为类属性,因为它们必须在初始化之前定义;更多的 built-in 配置参考 Built-in settings reference
crawler
该属性是通过from_crawler()
类方法在 class 初始化以后进行设置的,然后为当前的 Spider 实例链接到该Crawler
对象;
Crawlers 在项目中封装了大量的模块(包括,extensions, middlewares, signals managers 等等),查看 Crawler API 去更了解它的功能;
settings
当前 spider 执行相关的配置;这是一个 Settings 实例,查看 settings 相关内容以获取更多的信息;
logger
通过 Spider 的名字来创建 Python logger;通过 Logging from Spiders 以查看更多的相关内容;
from_crawler(crawler, *args, **kwargs)
该类方法是一个类方法,是 Scrapy 用来创建 spiders 所用的;
你通常不需要覆盖此方法,因为它是通过构造函数 __init__() 进行初始化的;尽管如此,该方法为新的实例设置了 crawler 和 settings 属性,所以它们可以在随后的 spider 代码中进行访问;
参数解释
- crawler (Crawler instance) – crawler to which the spider will be bound
- args (list) – arguments passed to the __init__() method
- kwargs (dict) – keyword arguments passed to the __init__() method
start_requests()
该方法为 spider 返回首批需要进行爬取的 Requests;它在 Spider 初始化以后并且在开始爬取数据的时候才会被调用;Scrapy 只调用它一次,所以将start_requests
实现为一个 generator 是非常安全的;
该方法默认将会为 start_urls 中所包含的每一个 url 生成Request(url, dont_filter=True)
对象;
那么该方法能够起到什么作用呢?下面通过一个例子来进行描述,如果你需要在爬取之前通过 POST 请求进行登录操作,你可以执行如下的代码,
1 | class MySpider(scrapy.Spider): |
parse(response)
当没有为它们的 requests 指定任何特殊的回调方法的时候,这是一个默认的回调方法用来处理所有的 downloaded responses;
同其他 Request callback 一样,该方法也必须返回一个 Request、dicts 或者 Item 对象的 iterable;
log(message[, level, component])
输出日志信息,更多有关 Scrapy 日志方面的内容,请查看 Logging from Spiders;
closed(reason)
当 spider 关闭的时候调用,该方法为 signals.connect() 发送 spider_closed 消息;
一些用例
1 | import scrapy |
注意,该用例没有为单独的,特定的 Request 设置 callback 方法,所以,任何 Request 的响应都会回调该默认的parse()
方法;
1 | import scrapy |
对上面的例子稍微做了一些改动,在parse()
方法中通过解析得到不同的元素,生成新的 Request 对象;
除了直接使用 start_urls,你可以通过使用 start_request() 来初始化相关的 Requests,同时,为了生成结构化的数据,你可以使用 Items
1 | import scrapy |
start_requests()
的一个非常重要的方法,就是可以扩展出自定义的回调方法 parse;
Spider 参数
Spider 可以通过接收参数的方式来修改他们的行为;可以限制 spider 爬取的范围也可以配置 spider 的功能;
如何传参和获取参数
Spider 的参数是通过crawl
命令通过-a
选项传入的,比如,
1 | scrapy crawl myspider -a category=electronics |
Spiders 可以通过 __init__ 方法来访问它们的参数,比如下面的 MySpider 实例通过 __init__ 方法可以获取从命令行输入的参数 category;
1 | import scrapy |
还可以将参数写在schedule.json
文件中,参考 Scrapyd document;
其它用例
可以为使用了 HttpAuthMiddleware 和 UserAgentMiddleware 这些中间件的 Spiders 传递参数;
1 | scrapy crawl myspider -a http_user=myuser -a http_pass=mypassword -a user_agent=mybot |
通用的 Spiders
Scrapy 提供了一些有用的且通用的 spiders 可以作为父类来定义你自己的 Spiders;它的目的是为一些通用的爬取用例提供一些便利的方法,就像一个网站有自己通用的爬取规则,从 Sitemaps 中爬取,或者是从 XML/CSV feed 中进行爬取;
为了进行如下的用例的演示,我们首先假定你已经由有一个在myproject.items
中申明的TestItem
模块;如下,
1 | import scrapy |
CrawlSpider
1 | class scrapy.spiders.CrawlSpider |
这是被用得最普遍的用来爬取常用的
websites 的 Spider;除了从 [Spider class] 中所继承的属性意外,该类提供了一些新的属性:
新的属性
rules
Rule 对象的一个列表,每一个 Rule 定义了一些特定的爬取行为;如果多个 Rule 匹配了同一个 link,第一个将会被使用,这个第一个指的就是 rules 中排在一个的元素 Rule;
parse_start_url(response)
这时 CrawlSpider 暴露出来可以被重载的方法;通过它来解析初始化的 responses,而且必须返回 Item 对象或者一个 Request 对象,或者是一个 iterable 对象其中的元素包含 Item 或者是 Request;
Crawling rules
1 | class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None) |
- link_extractor
是一个 Link Extractor 对象专门用来定义这些链接
将会如何从被爬取页面中提取; - callback
回调函数;回调每一个通过特定 link_extractor 所提取的 link;该回调方法接收一个 response 作为其第一个参数,然后必须返回一个包含 Item 或者是 Request 的 list;注意
,当使用 Crawl spider rules 的时候,避免使用parse
作为回调方法,因为CrawlSpider
通过封装了parse
方法来实现它的内部逻辑;所以,一旦你自己重载了parse
方法,crawl spider 将不会再工作了; - cb_kwargs
这是一个 dict 包含了传递给回调方法的关键字参数; - follow
is a boolean which specifies if links should be followed from each response extracted with this rule. If callback is None follow defaults to True, otherwise it defaults to False.
- process_links
一个回调方法,将在 links 从 response 中提出出来以后被调用;主要是起到过滤的作用;
XMLFeedSpider
TODO
CSVFeedSpider
TODO
SitemapSpider
TODO