01_爬虫的基本概念
str与bytes如何转换
- str 使用
encode
方法转化为 bytes (二进制字符串)
encode
编码 的意思 把一个字符串编码成 二进制字符串
- bytes 通过
decode
转化为 str
decode
解码 的意思,解码时候可以带上解码方式的参数,例如:b.decode('utf-8')
b.decode('gbk')
- 注意:编码方式和解码方式 必须一样,否则就会出现乱码,我们经常先使用
decode
进行解码,然后再使用 encode
进行编码成其他编码
http & https
- https 比 http 更安全,但是性能更低,默认端口分别是 https–>443 & http–>80
url格式与http请求格式
- url格式
- 我们经常在一个url地址中会看到
#anchor
这种形式的字段,我们称之为 锚点,用于跳转到网页指定的位置
- 注意:一个url地址带
#
锚点和不带锚点的响应结果是一样的,所以我们在查找爬虫url地址的时候可以把没用的锚点内容删除,从而简化我们需要的url地址
HTTP请求的形式
- HTTP请求的格式
- 注意: 请求数据 在
POST请求
中出现
User-Agent
可以理解为 模拟浏览器的代理,反爬手段会用到这个参数
Cookie
是用来保存用户信息的,保存在浏览器本地,Session
保存在服务器端,Cookie在爬虫中可以用于反爬和登录网站
HTTP常见请求头
- 请求头字段说明
Referer
是指当前url地址是从哪个url地址跳转过来的
常见的请求方法
- 常见的请求方法有
GET POST
- 带数据的请求一般使用
POST
(表单提交,传输大文本)
响应状态码(status code)
- 常见的响应状态码
爬虫的分类
- 通用爬虫:通常指搜索引擎的爬虫
- 聚焦爬虫:针对特定网站的爬虫
- 通用爬虫和聚焦爬虫工作流程
- 爬虫的流程
- url --> 发送请求,获取响应 --> 提取数据 --> 保存
- 发送请求,获取响应 --> 提取url(下一页,详情页)重新请求
- robots 是一个爬虫协议,用于规定爬虫允许爬取的范围或内容
浏览器发送请求的流程
- 我们通常通过 Chrome 浏览器的 检查 来查看页面
- 注意:在
Network
中Response
和Elements
中的内容很可能是不一样的,因为Elements
中的内容是包含了浏览器加载渲染后的内容,我们在做爬虫的时候注意这一点
- 爬虫要根据当前url地址对应的响应为准,当前url地址的elements的内容和url的响应不一样
- 总结:浏览器渲染出来的页面和爬虫请求的页面并不一样
爬虫要根据当前url地址对应的响应为准
- 爬虫只会请求当前这个url,但是不会请求js
- 浏览器拿到的内容,我们在浏览器中看到的内容是elements里面的内容
- elements=url对应的响应+js+css+图片
页面上的数据在哪里
- 当前url地址对应的响应中
- 其他的url地址对应的响应中
js
生成的
02_爬虫requests库
- 为什么选择使用requests模块
发送简单的请求
requests
发送请求
response = requests.get(url)
是requests模块发送请求的方式
response.text
返回的是一个 unicode
型的文本数据
- 很多时候
response.text
并不能成功的进行解码,是因为其默认的解码方式和实际的解码方式不一致
- 可以使用
response.encoding
来查看程序当前猜测的编码方式
- 使用
response.encoding="UTF-8"
来指定编码方式
- 指定编码方式之后再使用
response.text
,你会发现获取的页面是成功解码了的页面
- text和content的区别
- content保存二进制图片示例
response.content
返回的是 bytes
型的二进制数据,所以我们需要对其进行decode
解码
response.content.decode()
,默认使用utf-8的方式进行解码
response.content.decode("gbk")
response.content
返回的是二进制响应内容,response.text
则是默认”iso-8859-1”编码
- 也就是说:想获取文本数据可以用
response.text
,想获取图片等多媒体文件可以通过 response.content
response.status_code
获取状态码(一般:2开头表示正常,3开头表示重定向,4开头表示页面错误,5开头表示服务器内容错误)
- 判断请求是否成功
assert response.status_code==200
response.request.headers
返回的是 请求的headers
response.headers
返回的是 响应的headers
发送带headers的请求
- ++
requests.get(url,headers=headers)
++ 发送带headers请求的格式
- 注意:headers需要用变量保存使用,header必须是字典的形式
发送带参数的请求
- 一般情况下在url地址中
?
后面的是参数
- 在
requests.get()
代码中,我们可以使用 params
来添加参数,参数必须是字典的形式
- 有时候我们代码获取得的url地址可能经过了url编码,我们需要通过解码工具才能看到真是的url地址(常常出现在带有中文的时候)
import requests
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}
par = {"wd":"xiaoqiangclub"}
url_temp = "https://www.baidu.com/s"
response = requests.get(url_temp,headers=headers,params=par)
print(response)
print(response.request.url)
- 除了通过参数的形式外,我们还可以使用
format
拼接 的方式来实现,例如
import requests
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}
url = "https://www.baidu.com/s?wd={}".format("xiaoqiangclub")
response = requests.get(url,headers=headers)
print(response.request.url)
- 这里我们可能需要复习一下
format
的使用方法
format字符串格式化
"好好{}习,天天{}上".format("学","向")
发送POST请求
- 哪些情况下会用到POST请求
- post请求格式
- GET请求和POST请求在代码上最主要的区别是:POST请求多了一个,这个data参数必须是字典的形式
使用代理
- 使用代理的原理
- 代理分类
- 知道服务器的地址叫正向代理,不知道服务器地址的是反向代理
- 使用代理
- 使用代理我们只需要添加一个
proxies
参数,且须是字典形式的,其中字典的健表示的是代理类型,值是代理的服务器和端口
- 代理类型需要和我们访问的url地址类型一致,如,都是http,或者https
- 为什么使用代理
随机选择代理ip地址思路
- 准备一堆代理ip地址,组成ip池,随机选择一个ip来使用。
- 使用代理IP的时候我们需要先进行一次筛选
- 检查ip的可用性
- 可以使用requests添加超时参数,判断ip地址的质量
- 通过在线代理ip质量检测的网站测试代理ip
- 如何随机选择代理ip,让使用次数较少的ip地址有更大的可能性被用到
- {“ip”:ip,“times”:0}
- [{},{},{},{},{}],对这个ip的列表进行排序,按照使用次数进行排序sort()
- 选择是哦那个次数较少的10个ip,从中随机选择一个
模拟登录
- cookie和session的区别
- 爬虫处理cookie和session
- 携带一堆cookie进行请求,把cookie组成cookie池,让程序随机选择使用次数较少的cookie进行使用
- 判断cookie时候过期,过期后需要使用账号密码重新获取cookie
- 能不用cookie的时候尽量不带cookie
处理cookie和session请求
- session类的使用方法
使用requests提供的session类来请求登陆之后的网站的思路
- 实例化session
- 想使用session发送请求,登陆对应网站(使用
session.post()
登陆保存cookie),把cookie保存在session中
- 再使用session请求登陆之后才能访问的网站,session能够自动的携带登陆成功时保存在其中的cookie进行请求
不发送post请求,直接使用cookie获取登陆后的页面
- cookie过期时间很长的网站
- 在cookie过期之前能够拿到所有数据,下次需要重新更新cookie,很麻烦
- 配合其他程序一起使用,其他程序专门获取cookie,当前程序专门请求页面
- 字典推导式
cookies = "BIDUPSID=1ED91AD3A35211B5798955A9CA264DD4; PSTM=1580260692; BAIDUID=1ED91AD3A35211B519FD7949163C3AAF:FG=1; BD_UPN=12314753; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; yjs_js_security_passport=7909124920aecbce31c9a673abd9f24182255e7e_1580646531_js; BD_HOME=1; delPer=0; BD_CK_SAM=1; ASUV=1.2.126; SE_LAUNCH=5%3A26345024; MSA_WH=400_343; MSA_PBT=146; MSA_ZOOM=1056; wpr=0; PSINO=6"
cookies = {i.split("=")[0]:i.split("=")[1] for i in cookies.split(";")}
print(cookies)
小结:获取登陆后页面的三种方式
- 实例化session,使用session发送post请求,再使用它获取登陆后的页面
- headers中添加cookie键,值为cookie字符串
- 在请求方法中添加cookies参数,接收字典形式的cookie。字典形式的cookie中的键是cookie的name对应的值,值是cookie的value对应的值
03_chrome分析post与json
寻找登陆的post地址
- 在form表单中寻找action对应的url地址
- post的数据是input标签中name的值作为键,真正的用户名密码作为值的字典,post的url地址就是action对应的url地址
- 抓包,寻找登陆的url地址
- 输入错误的账户或者密码
- 勾选perserve log按钮,防止页面跳转找不到url
- 寻找post数据,确定参数
- 参数不会变,直接用,比如密码不是动态加密的时候
- 参数会变的情况下
定位想要的js
- 选择会触发js事件的按钮,点击event listener,找到js的位置
- 通过chrome中的search all file来搜索url中的关键字
- 添加断点的方式来查看js的操作,通过python来进行同样的操作
Requests的小技巧
requests.util.dict_from_cookiejar
把cookie对象转化为字典
requests.util.unquote
可以对url地址进行解码
requests.util.quote
反过来可以对url地址进行编码
response=requests.get(url,timeout=10)
设置超时参数
安装第三方模块
- pip install
- 下载源码解码,进入解压后的目录,
python setup.py install
***.whl
安装方法pip install ***.whl