第8章-Scrapy
一、Scrapy介绍
Scrapy是⼀个为了爬取⽹站数据、提取结构性数据⽽编写的应⽤框架,我们只需要实现少量的代码,就能够实现快速的抓取
Scrapy使⽤了Twisted异步⽹络框架,可以使爬虫更快、更强
- 模块是框架的一部分
二、Scrapy工作流程
- 首先Spider(爬虫)将需要发送请求的url经过Scrapy Engine(引擎)交给Scheduler(调度器)
- Scheduler(调度器) 将url排序,放入队列处理后,再经过Scrapy Engine(引擎)到Downloader Middlewares(下载中间件,在此可以添加user-agent 、cookie、 proxy)交给downloader
- Downloader向互联网发起请求,并接收响应(response),将响应再经过Scrapy Engine(引擎)由Spider Middlewares(爬虫中间件)交给Spider
- Spider处理response,提取数据并将数据经过Scrapy Engine交给itemPipeline(管道)保存数据
三、Scrapy入门
- spider/douban.py:填写爬虫的逻辑
- items.py:填写要爬取的字段,起数据封装的效果
- pipeline.py:填写数据保存的逻辑
- settings.py:开启或关闭相关的组件
(1)settings中:
关闭ROBOTSTXT_OBEY = True协议
打开DEFAULT_REQUEST_HEADERS,添加UA等Headers
打开ITEM_PIPELINES组件
添加LOG_LEVEL = ‘WARNING’,只有高于或等于WARNING级别的信息才输出到日志中
注:共享的信息字段也可以放到settings中,通过模块导入方式在别的模块中引用,setting中的字段都要大写,以区别 其他模块中的代码;引用方式有两种A.直接用settings中的字段B.在spider模块中用self.settings.get(字段)方式 C.在pipeline中用spider.settings.get(字段)方式
(2)spider/douban.py中:
response返回<class ‘scrapy.http.response.html.HtmlResponse’>,其中有如下方法:
response.body或.text:用于获取html,其中text是解码后的,body是十六进制的
可以通过response.xpath 进行数据的提取
在scrapy中对selector进行元素值提取的方法:get()或extract(),如下图:
注意:get()返回第一个,extract()返回全部
注:如果需要yield返回为空,必须跟{}:yield {}
(3)在pipeLIne中:
item是spider/douban.py中yield传递过来的数据,仍遵循生成器规则,通过process_item(self, item, spider)逐个提取进行存储处理
- 当在pipelines.py中创建多个class MyspiderPipeline时,可以在settings.py中设定各自的优先级
- 当创建多个spider,如:douban.py,jingdong.py,可以在pipelines.py中的通过判断spider.name来确定item的数据来源于哪个spider
class MyspiderPipeline:
def process_item(self, item, spider):
if spider.name == 'douban':
print('item is from ' + spider.name)
else:
print('item is from other')
- 多个pipeline的应用:
A. 可能会有多个spider,不同的pipeline处理不同的item的内容
B. ⼀个spider的内容可能要做不同的操作,⽐如存⼊不同的数据库中
C. pipeline的权重越⼩优先级越⾼
D. pipeline中process_item⽅法名不能修改为其他的名称
四、logging设置
(1)在相关的模块中,将log明确模块来源
(2)在settings中通过设置LOG_FILE,将不同模块的log统一输出到一个log文件中
如上图,告警log输出到logs.log文件中后,将不再显示于控制台
详细说明请参考:https://docs.scrapy.org/en/latest/topics/logging.html
五、scrapy.Request知识点
scrapy.Request(url, callback=None, method='GET', headers=None, body=None,cookies=None, meta=None, encoding='utf-8', priority=0,dont_filter=False, errback=None, flags=None)
常⽤参数为:
callback:指定传⼊的URL交给哪个解析函数去处理
meta:实现在不同的解析函数间传递数据;meta默认会携带部分信息,⽐如下载延迟,请求深度
dont_filter:让scrapy的去重不会过滤当前URL,scrapy默认有URL去重功能,对需要重复请求的URL有重要作用
案例介绍:
import scrapy
import json
from tencent.items import TencentItem # 引用item中预定义的字段,通过类实例化方式
from scrapy.http.response.text import TextResponse # 通过此方法查看TextResponse中的可用方法
class HrSpider(scrapy.Spider):
name = 'hr'
allowed_domains = ['careers.tencent.com']
list_page = 'https://careers.tencent.com/tencentcareer/api/post/Query?timestamp=1606024015414&countryId=&cityId=&bgIds=&productId=&categoryId=&parentCategoryId=&attrId=&keyword=&pageIndex={}&pageSize=10&language=zh-cn&area=cn'
detail_page = 'https://careers.tencent.com/tencentcareer/api/post/ByPostId?timestamp=1606024441199&postId={}&language=zh-cn'
start_urls = [list_page.format(1)]
def parse(self, response): # response只返回start_urls的200ok
for i in range(1, 3): # 从1开始,那么parse_list会对start_url