Scrapy框架
1 框架的模块和流程
模块
- spider:爬虫模块,指定起始页的url地址,以及去构造请求对象和提取数据
- Engine: 引擎模块,负责每个模块之间的数据的传递(Request,Response,Item)
- Scheduler: 调度器,存储Request对象的,里面维护一个列表,数据取出来之后,列表中这个数据就不存在了.
[1,2,3] 取出来,这个时候列表中就剩下[2,3]
-Downloader:下载器,负责发送请求获取响应,Scrapy中的响应对象,是Scrapy中自己构造出来的. - Item Pipeline :数据管道.存储数据,在管道中要去编写存储数据的逻辑.
流程:
- 在spider中去指定 start_url,框架会自动的将起始页的url地址,构造成Request对象.将Request返回给 引擎(Engine).
- 引擎拿到 起始页url地址对应的Request对象后,会将Request对象交给调度器.
- 调度器会先去做一个去重操作,如果不重复,将Request放入调度器队列中.
- 此时,调度器队列中就有了一个起始页的Request对象,会将Request对象取出来,交给引擎.
- 引擎拿到从调度器中取出来的Request对象,会将Request对象交给下载器.
- 下载器拿到引擎传递来的Request对象,会对这个Request对象中的url地址,去发送请求,获取到响应Response. 将这个Response对象返回给引擎.
- 引擎拿到的是从下载器传递过来的Response对象,将Response 传递给爬虫(parse 方法) 可以去解析数据.
①解析出来的数据Item,爬虫会将数据传递给引擎,引擎再将数据传递给管道.
②解析出来的是新的URL地址,那么会在爬虫中将新的url地址 构造一个Request 对象,交给引擎,引擎再给调度器(循环)
2 scrapy的三个内置对象
Request:
Response:
Item:
本质就是一个字典
3 scrapy框架 基础命令
创建项目:
scrapy startproject 项目名称
创建爬虫:
cd 项目路径下
scrapy genspider 爬虫名 爬虫运行抓取的域名范围
运行爬虫:
在项目路径下去运行爬虫
scrapy crawl 爬虫名字
4 爬虫框架项目
spiders包:用于存放爬虫文件的包,可以有多个爬虫文件,一个项目可以有多个不同的爬虫.
items.py: 在此文件中定义item类
middlewares.py:中间件文件,在此文件中编写中间件类
pipelines.py:管道文件,定义管道类,去实现数据的存储.
settings.py:项目中的配置文件,配置一些项目所有的信息,例如:UA,管道,中间件
scra.py 项目在部署到服务器的时候用到的配置文件
框架中需要手写的有: spider(爬虫)和Item Pipeline管道,其他(Scrapy
engine引擎,Scheduler调度器,Downloader下载器) scrapy都已经实现
5 scrapy数据建模
为什么要进行数据建模?:
- 定义Item即提前规划好哪些字段需要抓取,防止手误,因为定义好之后,在运行的过程中,系统会自动检查
- 配个注释一起可以清晰的知道要抓取哪些字段,没有定义的字段不能抓取,在目标字段少的时候可以使用字典代替
- 使用Scrapy的一些特定组件需要Item 做支持,如:scrapy的ImagesPipeline管道类.
粗俗理解:自定义爬虫中只能爬取item中的字段
定义:
格式:字段名 = scrapy.Field()
使用:
在爬虫文件中去使用,就是在构造数据的字典的时候去时候.
- 1 先导入我们自己定义好的item类
- 2 创建item对象 赋值: item[字段名] = 值
6 Request对象的构造(实现翻页)
Request的参数:
scrapy.Request(url[,callback,method=“GET”,headers,body,cookies,meta,dont_filter=False])
- url: 构造新的request对象的url地址,必传
- callback: request对象的响应对象交给哪一个解析函数去解析,不传默认是
parse()
方法。 - meta: 实现数据在不同的解析函数中传递,meta默认带有部分数据,比如下载延迟,请求深度等
- method: 请求方式,默认是 GET
- headers: 请求头的字典,其中不包含Cookie
- cookies: 接收cookie字典,专门用于携带Cookie数据。
- body: 接收json字符串,为POST数据,发送POST请求的时候会使用该参数。
- dont_filter: 默认为False,会过滤请求的url地址,即 去重.start_urls中的地址会被反复请求,否则程序不会启动。
request请求对象源码:
代码实现:
yield scrapy.Request(
url=next_url,
# callback=self.parse_detail 假如 这个url地址是详情页的url地址,在获取数据的时候和列表页的结果是不一样的,要指定新的解析方法
# 如果不去指定 callback,默认值 就是parse
callback=self.parse
)
完整爬虫代码:
import scrapy
class JobSpider(scrapy.Spider):
name = 'job'
allowed_domains = ['hr.163.com']
start_urls = ['https://hr.163.com/position/list.do']
base_url = "https://hr.163.com/position/list.do"
def parse(self, response):
# 1. 先分组 在遍历提取
tr_list = response.xpath("//table[@class='position-tb']/tbody/tr")
# 将包含数据的 tr 给提取出来
tr_list = tr_list[::2]
for tr in tr_list:
item = {
}
# 招聘的标题
item["title"] = tr.xpath("./td[1]/a/text()").extract_first()
# 部门
item["department"] = tr.xpath("./td[2]/text()").extract_first()
# 城市
item["city"] = tr.xpath("./td[5]/text()").extract_first()
yield item
# 获取下一页的url地址
next_url = response.xpath("//a[text()='>']/@href").extract_first