Scrapy(六):Spider
总结自:Spiders — Scrapy 2.5.0 documentation
Spider
1、综述
①在回调函数Parse及其他自写的回调函数中,必须返回Item对象、Request对象、或前两种对象的迭代器形式。这些Requests同样也必须包含一个回调函数,之后它们的Response会被特定的回调函数处理;
注:除了start_request方法,其他方法的回调函数必须手动实现在Spider中,如果不写回调函数,会默认视为parse方法。
②在回调函数中,我们通常通过Selector(或BeautifulSoup、lxml、...)爬取页面内容,并用爬取到的数据构造Items
③这些从Spider中返回的Item通常会经过Pipeline处理之后放入数据库或者通过输出命令时的输出参数,直接输出到文件中。
2、属性
属性 | 说明 |
name | Spider的名字,通常直接命名为域名,即网址中不加前缀和后缀的部分 |
allowed_domains | 可选,允许访问的网址范围;只有当OffsiteMiddleware开启时才起作用 |
start_urls | 一个URL List;爬虫开始的URL |
custom_settings | 关于要被重写的Settings的Dict;具体设置项见Built-in settings reference. |
crawler | 该参数通过方法from_crawler()设置,标识了爬虫绑定的Crawler对象 |
settings | 一个Setting对象,标识爬虫运行时的配置 |
logger | 日志 |
3、方法
方法 | 说明 |
from_crawler | 被Scrapy用于创造spiders,通常不用管,因为该方法和__init__作用差不多,处理要传入的参数时,只需用处理__init__的方法就可以 |
start_requests | Scrapy开始时调用该方法处理start_urls,该方法必须返回一个Request对象。Scrapy只调用该方法一次,所以用该方法创建Generator是安全的。 |
parse | 默认回调函数(当Request并没有指定回调函数时起作用) |
log | 发送日志信息 |
closed | 当Spider关闭时被调用。该方法与spider_closed标记相关联 |
3.5、部分方法的说明
①start_requests
如果没有重写该方法,该方法默认会对start_url中的每个URL使用方法Request(url,dont_filter=True)。
重写示例:如果你想在一开始模拟一个登录的POST请求,可以这样写:
def start_requests(self): return [scrapy.FormRequest('http://www.example.com/login'), formdata={'user':'jon','pass':'secret'}, callback=self.logged_in)] def logged_in(self,response): pass
②parse
默认回调函数;该方法返回:a、爬取到的数据(以Item形式);b、更多后续URL(以Iterable of Request形式);
其他回调函数同样需要返回以上两种数据,这里所说的几种返回形式如下:
# a、item item['attr1']=values1 ... return item # b、request return scrapy.Request(...) # a与b的iterable形式 yield item yield scrapy.Request(...)
4、命令行传入Spider参数
Spider可以接收参数来修正其行为。这些参数的一般用法是:a、定义起始URLs;b、限制爬取网页的特定部分;c、也能用来设置Spider的部分功能;
Spider参数在命令行运行crawl命令时,通过-a项传递进来,传递方式为:-a attr=value
例如:
scrapy crawl myspider -a category=electronics
Spiders可以在其__init__方法中(Spider.py文件中重写__init__,而不是__init__文件中)访问这些传递进来的参数:
import scrapy class MySpider(scrapy.Spider): name='myspider' def __init__(self,category=None,*args,**kws): super(MySpider,self).__init__(*args,**kw) self.start_urls=[f'http://www.example.com/categories/{category}']
默认的__init__方法将接收任何Spider参数并将它们复制为Spiders的属性,所以这些传递进来的参数,可以在Spiders.py中的任意方法中通过self.attr的方式访问。
需要注意的是,这些传递进来的参数全都是string,且名字不要设置为start_urls
5、继承Spider
Scrapy中有许多有用的继承Spider,你可以用它们作为父类写自己的Spider。
在以下的例子中,假设我们项目中的Item文件为:
import scrapy class TestItem(scrapy.Item): id=scrapy.Field() name=scrapy.Field() description=scrapy.Field()
5.1、CrawlSpider
这个Spider是爬取有规律的URL时最常用的Spider,因为其提供了一个方便的机制去获取一系列具有一定规则的URL。
①属性
除了继承自Spider的那些属性外(见本节第2部分),还有一个属性rules
rules:一个Rule对象List,List中的每个Rule都定义了一个爬取URL的规则。如果有多种rules同时匹配了同一个URL,那么只会使用这些rule中第一个(按顺序)。
关于Rule对象,可以看5.1.③
②方法
除了继承自Spider的方法外,还有一个方法parse_start_url
该方法只为start_urls中的URL提供处理方法(原因是,首页的URL可能与那些规则并不一致,需要额外处理,这个处理函数就是该方法)。该方法同样必须返回a、Item对象;b、Request对象;c、包含上述两项的Iterable对象。
③Rule
scrapy.spiders.Rule(
link_extractor, callback,
cb_kewargs, follow, errback,
process_links, process_request
)
参数:
参数 | 说明 |
link_extractor |
Link Extractor对象;定义了需要爬取的URL规则。 如果省略该项,那么视为无规则,将提取所有URL |
callback |
回调函数;对符合规则的URL用回调函数进行处理。 回调函数构造时,接收Response作为其第一个参数且必须返回一个Item或Request对象(或它们的Iterable)。这些Response对象将包含这些Link的文本信息,如果要访问它们的话,可以在Reponse对象的meta属性(meta是Dict)中,通过link_text作为Key访问 |
cb_kwargs | 一个Dict;其中包含了传入回调函数中的参数 |
follow | Boolean;每个Response中的link是否应该遵循Rule进行跟进(即每个Response中如果有符合Rule的URL,是否也对该URL进行爬取),如果没指定callback,那么该项默认为True,否则为False |
process_links | 符合Rule的Link进行处理的函数。可以用于筛选。当调用该方法之后,才会再调用callback方法。 |
process_request | 对通过Rule提取到的Request调用该方法。该方法接收两个参数:Request与Response(产生参数Request的那个Response)。必须返回一个Request对象或None。 |
errback | 异常处理调用函数 |
注意:
当自己写CrawlSpider子类时,需要明确指定callback响应函数,否则会产生预期之外的错误。
④例子
import scrapy from scrapy.spiders import CrawlSpider,Rule from scrapy.linkextractors import LinkExtractor class MySpider(CrawlSpider): name='example' 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('Hi,this is an item page!%s',response.url) item=scrapy.Item() item['id']=response.xpath('//td[@id="item_id"]/text()').re(r'ID:(\d+)') item['name']=response.xpath('//td[@id="item_name"]/text()').extract()[0] item['description']=response.xpath('//td[@id="item_description"]/text()').extract()[0] item['link_text']=response.meta['link_text'] url=response.xpath('//td[@id="additional_data"]/@href').get() return response.follow(url,self.parse_additional_page,cb_kwargs=dict(item=item)) def parse_additional_page(self,response,item): item['additional_data']=response.xpath('//p[@id="additional_data"]/text()').get() return item
这个Spider的作用是爬取example.com的首页,并收集category、item的链接,用parse_item爬取后续页面。对每个Item Response,一些数据将会从该HTML中通XPath表达式提取出来,并且这些数据将会填充到Item项。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性