爬虫笔记...
scrapy运行流程
先弄清除他的运行流程之外,得先知道他的5大核心组件
1 spider,爬虫
2 引擎
3 调度器
4 下载器
5 管道
流程:
- 在爬虫类中定义要爬取得url,将url封装成一个对象,传入引擎
- 引擎接收到对象,将对象传到调度器
- 调度器由2个部分组成,一个是过滤器,一个是队列,每一个url对象都会经过过滤器去重,然后存在队列中,将队列传给引擎
- 引擎接收到队列,将队列给到下载器
- 下载器接到队列,在互联网中下载资源,下好得资源得到一个response,将response传递给引擎
- 引擎将response传递给爬虫得parse方法,解析response,然后封装item,将item传递给管道进行持久化存储
问题:
为什么都要经过引擎?
- 因为引擎可以触发事务
- Scrapy引擎是整个框架的核心。它用来控制调试器、下载器、爬虫。实际上,引擎相当于计算机的CPU,它控制着整个流程。
在爬虫和引擎之间 下载器和引擎之间都有个中间件
- 下载器和引擎之间得中间件可以做ip池和UA池
创建项目
- scrapy startproject namepro
- cd namepro
- scrapy genspider name www.xxx.com
启动项目
- scrapy crawl name
settings需要配置
- 开启管道
- 可以开启多个管道,连着一起用,需要的是优先执行问题
- 传递给管道得值 yield item item 必须是Request, BaseItem, dict, None 其他报错
- 爬虫中间件,下载中间件,都需要开启
pipeline使用
- 为什么需要多个pipeline,可能有多个spider,不同的pipeline处理不同的item的内容
- pipeline的权重越小,优先级越大
- process_item不能改名
- spider参数 spider.name 返回项目名字
logging模块
- LOG_LEVEL = 'ERROR'
- LOG_FILE = './log.log'
构造请求 翻页
传参数
yield scrapy.Request(url='xx',rollback=self.parse,meta={'item':item})
item = response.meta.get('item')
item['x'] = x
yield item
DEBUG:
pass
scrapy shell
使用方法: scrapy shell url地址 进入类似python终端界面
可以调试 response.xxx 之类
管道 -> 数据保存
- open_spider(self,spider) 爬虫开启执行 -> 数据库建立连接 仅执行一次
- process_item(self,item,spider) 处理Item -> 存入数据库
- close_spider(self,spider) 爬虫结束 -> 数据库关闭连接 执行一次
- from_crawler(self,crawler)
全站爬取 crawlspider
- scrapy startproject xxpro
- scrapy genspider -t crawl xx www.xx.com
# 定义提取规则地方
rules = (
# LinkExtractor 连接提取器,提取url地址
# callback 提取出来的response给callback处理, 可以不写
# follow 当前url地址的响应是否重新经过rules来提取url地址
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
)
- crawlspider里面不能定义parse方法
- 如果多个rule都满足一个url,会选择第一个进行操作
scrapy携带cookie模拟登录
- 先去找起始url的首页,不需要cookie登录的那种,
- 获取他的cookie,再去请求需要cookie的网页
下载中间件的使用
- DownloaderMiddlewares:
process_request(self,request,spider):
当每个request请求通过下载中间件的时候,该方法调用, UA伪造,代理
request.headers['User-Agent'] = 'ua'
request.meta['proxy'] = '代理' https / http 看爬取的网站是什么
process_response(self,request,response,spider):
当下载器完成http请求,传递响应给引擎的时候调用
return response
process_exception(request,exception,spider)
出错时调用
scrapy发送post请求
scrapy.FormRequest(url,formdata,callback)
scrapy.FormRequest.from_response(response,formdata={user,pwd},callback) # 简单
# input用户名 name的值作为键 fromid formname 定位form表单
问题
数据重复怎么办
- 后一次循坏会改变前一次的结果,item同时会被操作,而且使用的item来之同一个
- 使用深copy复制item
url地址js生成怎么办
- 寻找规律
- 在响应中会有当前页码数和总的页码数
crawlspider
- 如何使用
1 scrapy startproject namepro
2 scrapy genspider -t crawl name
3 完善rules 一个元组 一个Rule linkExtractor callback follow
4 完善callback
- 使用场景
1 url的规则能够通过正则或者xpath
2 最终页面有全部数据的时候使用,如果没有,在callback中手动构造请求
-注意点
1 parse函数不能定义
2 继承自CrawlSpider
下载中间件
process_request()
处理请求
添加cookie
添加ua request.headers['u-a']
添加代理 request.meta['proxy']
不需要return
process_response()
处理响应
需要 return response
模拟登录
- 携带cookie登录
scrapy.request(url,callback,cookies={})
不能吧cookies放在headers中
- 使用FormRequest
scrapy.FormRequest(url,formdata={},callback) formdata 请求体
- 自动寻找form表单中的action的url
scrapy.FormRequest.form_response(response,formdata={},callback) formdata 用户名,密码
补充url地址
urllib.parse.urljoin(response.url, item['url'])
response的常见属性.
url
status_code
request.headers 响应对象对应的请求头
headers
request._cookies
request.cookies 答应响应的中的cookies
json()
request
get params
post data
在headers携带cookie header = {'Cookie':'xx'}
timeout 参数使用 timeout=3 3s不响应报错
proxies = {'https':'https://127.0.0.1:8080'}
verify参数忽略CA证书 verify=False
post数据来源
1.固定值 抓包不变值
2.输入值 抓包笔记根据自身变化
3.预设值-静态文件中 需要提前从静态文件获取 re
4.预设值-发请求 需要对指定地址发送请求获取数据
5.在客户端生成 分析js文件,模拟生成数据
session使用方法 保持会话 多次连续的请求
session = requests.session() 实例化
response = session.get(url,headers)
response = session.post(url,headers)
数据提取
jsonpath 多层嵌套的复杂字典直接提取
from jsonpath import jsonpath
ret = jsonpath(a,'语法') $根节点 .直接子节点 ..内部任意位置
lxml模块 xpath
/ // name text() ..父节点 .当前节点 @ 选取属性 *通配任意一个节点
//title/[@lang="eng"] 选取lang属性值为eng的title标签
/div[last()-1] 选取最后第二个div标签
/div[text()='导演'] 选取div文本为导演的标签
/h1/div[price>20]/title 选取h1标签下div的price价格大于20的title标签
1.通过索引来选择节点 [1]
2.通过属性值来选择节点 [@class="xx"]
3.通过子节点的值来选择节点 //span[ul>200] //div[span[2]>200]
4.通过包含修饰 //div[contains(@id,'xxx')] //div[contains(text(),'下一页')]
找翻页url 不用使用索引
浏览器进入内容被注释的解决方法
换个请求UA low的
response.decode().replace("",'') 替换掉
scrapy框架中
response.url 当前响应url
response.request.url 当前响应对应的url
response.headers 响应头 对面url的
response.request.headers当前响应的请求头 我方的
response.body 响应体,bytes类型
response.status 状态
response.urljoin 拼接url
保存数据 pipelines.py 对数据进行操作 process_item
在setting.py里面进行开启管道操作
数据建模 Items.py 里面确定目标
开发流程:
1 创建项目
2 明确目标
3 创建爬虫
4 保存数据
翻页请求如何处理
1 找到下一页的url
2 构造请求 scrapy.Request(url,callback,meta)
scrapy.Request() 更多参数
callback 指定回调函数
meta 参数传递 有一个固定的键 proxy 表示代理
method 指定post get请求
headers 接受一个字典,不包括cookie
cookies 接受一个字典,专门放cookie
body 接受json字符串,为post数据
dont_filter 设置过滤
scrapy模拟登录
cookies参数
模拟登录
start_requests 重写 在这个方法得到一个cookie的字典 得到这个cookie在去重新请求url
yield scrapy.Request(url=url,callback=self.parse,cookies=cookie)
scrapy.FormRequest() 能够发送post请求,和ajax请求 url,formdata,callback
cookie = response.headers.getlist('Set-Cookie')
scrapy 管道的使用
process_item(self,item,spider) 对数据item处理 必须return item
在settings中能够开启多个管道,为什么需要开启多个
- 不同的pipeline可以处理不同的爬虫的数据,通过spider.name来区分
- 不同的pipeline能够对一个或多个进行不同的数据处理的操作,比如一个数据清洗,数据保存
- 同一个也可以处理不同爬虫的数据,通过spider.name来区分
crawlspider
- 继承Spider类
- 自动根据规则链接并且发送给引擎
scrapy中间件的使用 预处理请求对象和响应对象
- 对header以及cookie进行更换和处理
- 使用代理ip等
- 对请求进行定制化操作
Downloader_Middlewares下载中间件
process_request
当每个request通过下载中间件时,该方法进行调用
None 如果所有的下载中间件都返回None,则请求最终被交给下载器处理
request 如果返回请求,则将请求返回给调度器
response 将响应对象返回给spider,进行解析
process_response
当下载器完成http请求,传递响应给引擎的时候调度
request 如果返回请求,则将请求返回给调度器
response 将响应对象返回给spider,进行解析
1 在middleware.py定义中间件方法
2 在中间件类中,重写处理或者响应方法
3 在setting中开启中间件的使用
代理ip使用
- 代理添加的位置: request.meta增加proxy字段
- 获取一个代理ip,赋值给 request.meta['proxy'] ip:port
代理池中随机选择ip
代理ip的weiapi发送请求获取一个ip
中间件使用selenium
见scrapy_middle UApro

浙公网安备 33010602011771号