摘要
本文内容转自网络,个人学习记录使用,请勿传播
爬虫中期复习
requests模块
爬虫的分类
- 通用爬虫:将一整张页面进行数据采集
- 聚焦爬虫:可以将页面中局部或指定的数据进行采集
- 聚焦爬虫是需要建立在通用的基础上来实现
- 功能爬虫:基于selenium实现的浏览器自动化的操作
- 分布式爬虫:使用分布式机群可以对一组资源进行联合且分布的爬取
- 增量式爬虫:监测网站数据更新的情况,以便爬取到网站最新更新出来的数据
反爬机制,反反爬策略
robots协议:君子协议。
requests模块是用来模拟浏览器发请求,因此可以基于requests模块实现爬虫的数据采集相关操作。
- 注意:如果爬虫程序采集不到我们想要的数据,唯一的原因:爬虫程序模拟浏览器的力度不够!
- 模拟力度重点体现在哪里?
- 请求头:
- User-Agent:请求载体的身份标识
- Cookie
- refere
- 其他
- 请求参数
- 重点关注动态变化的请求参数
- 如何检测请求参数是否动态变化的?
- 基于抓包工具多尝试抓取几次该数据包,检测不同时刻抓取数据包中的请求参数是否有变动。
- 如何检测请求参数是否动态变化的?
- 重点关注动态变化的请求参数
- 请求头:
- 模拟力度重点体现在哪里?
- 注意:如果爬虫程序采集不到我们想要的数据,唯一的原因:爬虫程序模拟浏览器的力度不够!
requests模块中常用的两个方法:
get:发起get请求
- 重要的方法参数:
- url:发起请求的url
- headers:请求头的伪装
- params:请求参数
- proxies:指定代理
- 重要的方法参数:
post:发起post请求
url
headers
data:请求参数。如果抓包工具中的请求参数为键值对,则使用data参数
1
2name:bobo
password:123456
json:如果抓包工具中的请求参数为字符串形式的键值对,则使用json参数
1
"{'name':'bobo','password':'123456'}"
proxies
动态加载数据
- 有哪些方式可以实现动态加载数据?
- 通过ajax请求生成动态加载的数据(常见)
- 通过js生成动态加载的数据
- 如何获取js生成的动态加载数据?(极为少见)
- 逆向。
- 如何获取js生成的动态加载数据?(极为少见)
- 在对一个陌生的网站进行数据爬取前,首先做什么?
- 检测你想要爬取的数据是否为动态加载数据?
- 如何检测?
- 基于抓包工具进行局部搜索,如果搜索不到则说明数据是动态加载的。
- 如何获取动态加载数据?
- 基于抓包工具进行全局搜索!
- 如何检测?
- 问题:如果基于抓包工具进行全局搜索,发现没有搜索到,说明说明?
- 说明该组数据被加密了。那就需要逆向操作。
- 检测你想要爬取的数据是否为动态加载数据?
- 有哪些方式可以实现动态加载数据?
数据解析
数据解析的作用是什么?
- 是为了实现聚焦爬虫!
如何实现数据解析呢?
- Bs4,xpath,正则
数据解析的通用原理是什么?
- 1.实现标签定位
- 2.提取定位到标签中的数据
bs4实现数据解析的流程:
1.实例化一个BeautifulSoup对象,然后把即将被解析的html页面加载到该对象中。
2.调用BeautifulSoup对象相关的属性和方法进行标签定位和数据提取
常见的属性或方法有哪些?
- find(属性定位),find_all(属性定位),select(选择器定位)
- text,string:获取定位到标签中的数据值
需求:想要将页面中的一组指定标签的html代码获取,如何实现?
1
2
3<html>
<div>hello bobo</div> #如何可以解析到该一整行数据(包含标签的数据)
</html>直接使用bs4定位到div标签,然后进行打印输出即可!
xpath实现数据解析的流程:
- xpath表达式进行标签定位和数据提取
- 注意:
- 如果xpath表达式中存在tbody标签,则无法实现标签定位和数据提取
- 直接将tbody从xpath表达式中删除即可
- //div/a/tbody/span/text()
- //div/a//span/text()
- 直接将tbody从xpath表达式中删除即可
- 可以在xpath表达式中使用|符号,来增加xpath表达式的通用性。
- //div | //span/div :|左右两侧的某一个xpath表达式生效,即可进行标签定位
- 如果xpath表达式中存在tbody标签,则无法实现标签定位和数据提取
requests高级
- cookie
- 处理cookie的方式
- 手动处理:将抓包工具中的cookie写在headers中即可
- 自动处理:使用session对象。该对象在进行请求发送的过程中,如果产生了cookie,则会自动将cookie存储到该对象中。
- 注意:Session对象处理cookie不是万能。
- 辅助方式:通过selenium实时获取cookie,然后将cookie写到requests程序的headers中(稳妥)
- 处理cookie的方式
- 代理:
- 代理服务器的作用:可以转发请求和响应。
- 可以使用get或者post方法的proxies实现代理操作。
- 注意:get(proxies={‘http’:’ip:port’}) or get(proxies={‘http://‘:’ip:port’})
- 代理的类型:http和https
- 代理的匿名度:透明,匿名,高匿
- 验证码
- 将验证码下载到本地,基于相关的打码平台进行识别即可!
- 模拟登录
- 有些网站数据,是需要登录后在可以查看的,因此需要进行程序的模拟登录。
selenium
不同的浏览器是需要使用不同的驱动程序!!!
基于浏览器自动化的模块。
- 常见操作:
- 请求操作:get
- 交互操作:
- click,send_keys…
- 标签定位操作
- find系列的函数
- 获取页面源码:page_source
- cookie:获取cookie
- 无头浏览器:没有可视化界面的浏览器
- 动作链:ActionChains
- 内部封装了很多比较复杂的动作。
- 规避检测的方法
- 较新的规避检测的方法去哪里找?
- GitHub,百度(效率低)
- 较新的规避检测的方法去哪里找?
- 在爬虫中,为什么需要使用selenium?(selenium和爬虫之间的关联是什么)
- selenium可以便捷的获取动态加载/加密数据(可见即可得)
- 实现便捷的模拟登录
- 缺点:效率较低,无法很好的使用异步操作。
异步操作
- 多线程
- 推荐大家使用线程池(Pool)
- 重要函数map:
- map(callback,alist):可以将alist列表中的每一个元素以此传递给callback这个回调函数的参数,然后会异步的调用callback函数完成相关任务操作。
- callback调用的次数完全取决于alist元素的个数。
- map(callback,alist):可以将alist列表中的每一个元素以此传递给callback这个回调函数的参数,然后会异步的调用callback函数完成相关任务操作。
- 协程(重点)
- 特殊的函数
- 被ascyc关键字修饰的函数定义,该函数就是一个特殊的函数
- 特殊之处:
- 该函数被调用会函数内部的函数体语句不会被立即执行
- 函数调用后会返回一个协程对象。
- 协程
- 协程对象 == 特殊的函数 == 一组指定形式的操作
- 协程对象 == 一组指定形式的操作
- 任务对象
- 高级的协程对象,高级之处就在于可以给任务对象绑定一个回调函数。
- 任务对象==协程对象==一组指定形式的操作
- 任务对象==一组指定形式的操作
- 绑定回调函数:
- 可以使用add_done_callback函数给任务对象绑定一个回调函数,记住:回调函数是在任务对象表示的这组操作执行完毕后,才可以执行回调函数的相关操作!
- 回调函数的重点:
- 回调函数只可以有一个参数,该参数表示的是就是当前的任务对象。
- 任务对象.result():result方法返回的就是特殊函数内部的返回值!
- 在爬虫中,一般情况下,任务对象的回调函数使用来进行数据解析或者持久化存储!
- 高级的协程对象,高级之处就在于可以给任务对象绑定一个回调函数。
- 事件循环
- loop这个事件循环对象,可以当做是一个容器,该容器内部存放一个或者多个任务对象。如果一个或者多个任务对象放置在了loop这个容器中,当loop启动,则其内部存放的任务对象就可以被异步的执行了!
- 注意:在特殊函数内部,不可以出现不支持异步模块的代码,否则会中断整个协程的异步效果。
- 因此在协程异步环节中,不可以使用requests,使用aiohttp这个支持异步的网络请求模块进行请求发送!
- req = aiohttp.ClinetSession() 创建请求对象
- response = req.get/post()进行请求发送
- response.text()返回字符串形式的响应数据,response.read()返回二进制形式的响应数据,response.json()返回json格式的响应数据。
- 因此在协程异步环节中,不可以使用requests,使用aiohttp这个支持异步的网络请求模块进行请求发送!
- 特殊的函数
scrapy
- 数据解析机制:
- 通常使用xpath进行数据解析,只不过,必须让xpath结合这extract()或者extract_first()进行联合解析!
- 持久化存储
- 基于终端指令的持久化存储
- 只可以将parse方法的返回值存储到指定后缀的文本文件中
- 指令:scrapy crawl spiderName -o filePath
- 基于管道的持久化存储
- 在爬虫文件中进行数据解析
- 将解析到的数据存储封装到item类型的对象中
- 将item对象通过yield关键字提交给管道
- 在管道中调用process_item进行item对象的接收,且可以将接收到的数据存储到任意的平台中。
- 在配置文件中开启管道机制。
- 注意:
- process_item方法调用次数取决于爬虫文件向管道提交item的次数。
- 如果将二进制形式的数据进行持久化存储如何操作?
- 基于ImagesPipeLine该管道类实现二进制数据的持久化存储!
- 在爬虫文件中,只需要将多媒体文件的路径和名字封装到item中,提交给ImagesPipeLine管道类即可。
- 基于ImagesPipeLine该管道类实现二进制数据的持久化存储!
- 基于终端指令的持久化存储
- 手动请求发送:
- 可以将url放置在start_urls这个列表中,该列表会对其内部的url发起get请求
- 手动发起请求:
- yield scrapy.Request():发起get请求
- yield scrapy.FormRequest():发起post请求
- 请求传参:
- 作用:可以实现深度爬取(爬取的数据没有存在于同一张页面中)
- 如何实现:
- Yield scrapy.Request(url,callback,meta):meta是一个字典,meta可以将自身传递给callback这个回调函数。
- 在回调函数中,可以通过response.meta获取传递过来的meta字典
- 中间件:
- 作用:拦截到所有的请求和响应
- 常用的功能:
- 设置请求代理(常用)
- cookie设置
全站数据爬取(将所有页码对应页面的数据进行爬取)
- CrawlSpider技术
- 可以创建一个基于CrawlSpider的爬虫类
- scrapy genspider -t crawl spiderName www.xxx.com
- 链接提取器LinkExtractor(rule=’正则’):
- 可以根据正则匹配的要求在页面中提取指定的链接(url)
- 规则解析器Rule(link,callback,follow=True):
- Rule可以将链接提取器提取到的链接进行请求发送,然后根据指定规则(callback)对请求到的数据进行数据解析
- 发现:链接提取器提取到链接的个数就是callback这个回调函数调用的次数。
- 可以创建一个基于CrawlSpider的爬虫类
- CrawlSpider技术
分布式:
- 编码流程:
- 导包:在爬虫文件中导入RedisCrawlSpider
- 将爬虫类的父类修改为RedisCrawlSpider
- 将start_urls替换成redis_key属性(调度器队列的名称)
- 数据解析解析和item提交管道操作
- settings中配置可以被共享的管道类和调度器类即可
- settings配置redis数据库的访问接口
- 配置redis数据库的配置文件(redis.window.conf)
- 取消127.0.0.1的默认绑定
- 取消保护模式:protected mode = no
- 启动redis的服务端和客户端
- 启动scrapy的分布式项目
- 将起始的url扔入到redis-key表示的调度器队列中即可
- 编码流程:
- 增量式
- 核心:去重
- 如何去重?
- 使用一个记录表
- 记录表需要具备两个功能:1.可以去重 2.可以持久化存储
- 因此使用redis的set充当记录表
- 使用一个记录表
- 如何去重?
- 数据指纹:
- 记录表中通常存储的是数据指纹
- 数据指纹:爬取到的数据的唯一标识
- 使用数据的md5值
- 详情页的url
- 核心:去重
web逆向
- 什么叫做逆向?
- 将js代码改写成python代码,这个过程就是逆向。
- 为什么要把js代码改写成python代码?
- 网站中,有些数据是通过js代码生成的,因此,需要将生成该数据的js代码运行,获取运行结果,该结果就是我们要爬取的数据。
- 如何将js代码改写成python代码?
- 手动改写:不选择
- 自动改写:PyExceJs模块实现基于python代码执行js代码
- 逆向通产用来处理什么样的问题?
- 处理动态变化的请求参数
- 破解加密的响应数据
- 处理动态变化的cookie值(终极武器)