爬虫
爬虫开篇
何为爬虫?
爬虫是通过编写程序,模拟浏览器,对互联网数据进行抓取的过程
爬虫的应用场景
- 通用爬虫 :抓取系统的重要组成部分,抓取的是一整张页面数据
- 聚焦爬虫 :建立在通用爬虫的基础上 ,抓取的是页面中的特定的局部内容
- 增量式爬虫 :检查网站中数据更新的情况,只会抓取网站中最新的数据
爬虫的矛与盾
- 反爬机制 : 门户网站,可以通过指定相应的策略或者技术手段,防止爬虫程序进行网站数据的爬取
- 反反爬策略 : 爬虫程序可以通过指定相关的策略或者技术手段,破解门户网站中的反爬机制,从而可以获取门户网站的数据
robots.txt协议
- 定义:也称君子协议。规定了网站中那些数据可以被爬虫爬取,哪些禁止爬取
- 查看方式: 在访问网站后加上rebots.txt即可看到。例如:
Http协议
概念:服务端和客户端进行数据交互的一种形式
常用请求头信息:
- User-Agent :请求载体的身份标识
- Contention :请求完毕后,设定是否断开链接
常用响应头信息:
- Content-Type :服务端响应客户端的数据类型
HTTPS协议
Http在数据传输过程是明文状态的,为了保证数据的安全性,创建了HTTPS协议
两者的区别就是:http数据未加密状态,https数据是加密状态
加密方式:
- 对称秘钥加密 :
- 秘钥 :公开秘钥
- 加密过程 :
- 客户端和服务端约定同一种加密方式,客户端加密数据之后,把秘钥和数据要一起发送给服务端,服务端会根据秘钥进行解密
- 优缺点:
- 优点:一定程度上保证了数据的安全性
- 缺点:发送秘钥时,容易被劫持,所以无法根本上还是无法保证数据的安全性
- 非对称秘钥加密 :
- 秘钥:
- 私有秘钥
- 公开秘钥
- 加密过程:
- 服务端告诉客户端自己的加密方式,即公开秘钥。客户端通过公开秘钥加密发送给服务端之后,服务端会根据私有秘钥进行解密
- 优缺点:
- 优点:保证了数据的安全性
- 缺点:
- 不能保证接受端向发送端发送的秘钥就是预先发送的, 因为只要发送秘钥就有被劫持的风险
- 由于每次传输都需要加密解密,降低了通信速度
- 秘钥:
- 证书秘钥加密 :
- 数字证书加密
- 加密过程:
- 服务端开发者携带公钥向可信任的数字证书认证机构提出公开秘钥的申请 ,认证机构在审核申请者的身份之后,对开发者提供的公开秘钥进行数字签名,然后将已签名的公开秘钥与数字证书绑定到一起。
- 服务端向客户端发送数字证书,客户端通过数字证书中的数字签名来验证公钥的真伪,验证通过之后客户端就会对报文通过公钥进行加密传输,服务端接受到之后使用自己的私钥进行解密
- 一般认证机构都是信任度高的,所以基本不会出现证书伪造情况。
Requests模块
常用方法:
-
requests.text:获取requests 的字符串类型的文本内容
-
requests.json():获取requests的json类型的文本内容
请求方式:
- requests.get(url, params, headers)
- requests.post(url, data, headers)
数据分析
1. 正则解析
re_path = '<div class="recmd-right"><a .*? href="(.*?)" target.*?</div>' # href="/article/123124303" article_href_list = re.findall(re_path, page_html, re.S)
2. BeautifulSoup
安装
pip install bs4 # 安装bs4 from bs4 import BeautifulSoup 导入BeautifulSoup
入门使用
1. 实例化
- 实例化本地对象
- fp = open() soup = BeautifulSoup(fp, "lxml") # fp为文件句柄 lxml为固定参数
- 实例化网页
- BeautifulSoup(html, "lxml")
示例:
# 本地文件: fp = open(" example", "lxml:) soup = BeautifulSoup(fp, "lxml") # 网页 soup = BeautifulSoup(page_html, "lxml")
2. 常用方法调用
1. 使用TagName定位
# 使用标签tagName定位 返回文档中第一个标签 print(soup.title) # <title>测试bs4</title> print(soup.a) # <a href="https://www.sogou.com/"></a>
2. find() 方法
# 获取类属性为content的div print(soup.find("div", class_="content")) # 获取上述div中的 文本 print(soup.find("div", class_="content").text) # 天地悠悠 ex # 获取上述div中的a标签文本 print(soup.find("div", class_="content").a.text) # ex
3. find_all() 方法
# find_all方法 # 返回多个数据 以列表的形式 print(soup.find_all("a"))
4. select() 方法
# select方法 层级选择 以列表的形式返回多个数据 # 单个层级选择 print(soup.select(".content >span >a")) # [<a href="ex.html"> ex </a>, <a href="qiutuimg.py"> qiutuimg </a>] # 多个层级选择 即跨级选择 print(soup.select(".content a")) # [<a href="ex.html"> ex </a>, <a href="qiutuimg.py"> qiutuimg </a>]
5. 获取标签中的文本数据
# 获取标签中的文本数据 print(soup.div.text) # 搜狗 360 百度 谷歌 print(soup.div.get_text()) # 同上 print(soup.div.string) # None ''' 三者的区别: text/get_text() 可以获取标签内的 string 只会获取直系文本 '''
6. 获取标签中的属性值
# 获取标签中的属性值 print(soup.select(".content >span >a")[0]["href"]) # ex.html
3. xpath 解析
解析原理:
- 实例化一个etree对象,将需要被解析的页面源码数据加载到该对象中
- 调用etree对象的xpath方法结合xpath表达式实现标签的定位和内容的获取
解析器:
pip install lxml
实例化对象:
- 实例化本地HTML对象:
- etree .parse(filepath) # filepath为本地文件路径
- 实例化网络HTML对象:
- etree.prase("html_text") # html_text 为从网络上爬取的网页源码
xpath (xpath表达式):
层级定位:
4.解决中文乱码
1、对整个响应页面进行编码
# 解决中文乱码 方法一 对获得的整个页面进行编码 page_text = requests.get(url=url, headers=headers).encode("utf-8").text
2、对部分乱码进行编码
# 方法二 对乱码内容进行编码 img_title = a.xpath("./img/@alt")[0] + ".jpg" img_title = img_title.encode("iso-8859-1").decode("gbk")
requests高级用法
Cookie 和 session
在爬虫程序中,当你访进行用户登录请求后,再访问用户相关的页面时,会出现让你再次登录的提示。
原因是http是无状态协议,它不会自动保存登录用户的相关信息,所以为了解决这个问题,我们就需要用到Cookie和session
由于Cookie的安全性较低,所以目前都是使用session来进行保存会话
Session的使用
1、 创建session对象
# 创建session对象 session = requests.Session()
2、使用session发起登录请求
使用此方式登录之后,用户的相关信息就会自动存储到headers中,后续访问用户相关页面就不用再次登录了
# 使用session发起POST请求 用户登录 response = session.post(url=url, headers=headers, data=data)
3、使用带有Cookie的session发起其他请求
# 使用带有Cookie的session对象发起get请求 preson_pagetext = session.get(url=person_url, headers=headers).text
代理IP
现在大部分网站为了防止网站资源被恶意占用都会设置反爬机制,比如:“ip访问频率限制”。
为了解决这个反爬机制,我们就需要进行反反爬策略,对于限制ip这种机制,我们可以使用“ 代理IP ”进行解决。
代理的作用:
- 突破自身IP访问的限制
- 隐藏自身的真是IP
代理相关网站:
- 快代理
- 西祠代理
- www.goubanjia.com
代理IP的类型:
- http :适用于使用Http协议的网站
- https:适用于使用https的网站
代理IP的匿名度:
- 透 明: 服务端知道该次请求是代理,可以看到真实ip
- 匿 名:服务端知道使用了代理,但是看不到真实IP
- 高匿名:服务端不知道是否使用了代理,也不知道真实IP
如何使用?
示例:
import requests url = "https://www.baidu.com/s?wd=ip" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36' } # 未使用代理 page_text = requests.get(url=url, headers=headers).text # 使用代理 page_text = requests.get(url=url, headers=headers, proxies={"https": "113.194.28.99:9999"}).text