Python爬虫——requests库、动态爬取html网页
目录
一、爬虫基础知识
百度搜索引擎是一个很大的爬虫
模拟客户端发送网络请求,接收请求响应,一种按照一定的规则,自动抓取互联网信息的程序。
12306抢票、网站投票、短信轰炸
-
爬虫的流程:
url–>发送请求、获取响应—>提取数据—>保存
发送请求,获取响应—>提取url
-
页面上的数据在哪
- 当前url地址对应的响应中
- 其他url地址对应的响应中
- 比如ajax请求
- js生成的
- 部分数据在响应中
- 全部通过js生成
二、爬虫的分类
- 通用爬虫:通常指搜索引擎的爬虫
- 聚焦爬虫:针对特定网站的爬虫
三、HTTP和HTTPS
- HTTP
- 超文本传输协议
- 默认端口号:80
- HTTPS
- HTTP+SSL(安全套接字层)
- 默认端口号:443
- 发送数据之前对数据进行加密,服务端拿到后再进行解密
HTTPS比HTTP更安全,但是性能更低
-
浏览器发送HTTP请求的过程
HTTP常见请求头
- Host(主机和端口号)
- Connection(链接类型)
- Upgrade-Insecure-Requests(升级为HTTP请求)
- User-Agent(浏览器名称)-------可以用于判断PC端、手机端等
- Referer(页面跳转处)
- Accept-Encoding(文件编解码格式)
- Cookie
- x-requested-wth:XMLHttpRequest(Ajax异步请求)
响应状态码(status code):
- 200:成功
- 302:临时转移至新的url
- 307:临时转移至新的url
- 404:not found
- 500:服务器内部错误
四、url的形式
形式:scheme://host[:port#]/path/…/[?query-string][#anchor]
- scheme:协议
- http
- https
- ftp
- host:服务器端口
- 80
- 443
- path:访问资源的路径
- query-string:参数,发送给http服务器的数据
- anchor:锚,转跳到网页的指定锚点位置
Cookie保存在浏览器本地,session保存在服务器
五、字符串
-
字符串类型的区别和转化
-
str类型和bytes类型
- bytes:二进制
- 互联网上的数据都是以二进制的方式传输的
- str:unicode的呈现形式
- bytes:二进制
-
Unicode UTF8 ASCII
- 字符char
- 字符集character set(字符的集合)
- 字符集的种类
- ASCII
- GB2312
- GB18030
- Unicode
- ASCII编码是1个字节,Unicode通常2个字节
- UTF-8是Unicode实现方式之一,UTF-8是一种变长的编码方式,可以是1,2,3个字节
-
编码方式和解码方式必须一致,否则会乱码
六、request发送请求和获取页面字符串
import requests # 导入包
# -----------------------简单获取数据--------------------#
response = request.get("http://www.baidu.com") # 发送request请求
response.encoding # 获取编码方式
response.encoding = "utf-8" # 自定义编码方式
# 解码方式,三种都可以,可以反复尝试,选择其中一种
response.text # 解码1
response.content.decode() # 解码2
response.content.decode("gbk") # 解码3
# 不带headers只能获取部分的数据信息
# ---------------------获取图片信息---------------------- #
# requests保存图片
response = requests.get("地址.png")
# 保存
with open("a.png","wb") as f:
f.write(response.content)
# ---------------------请求和响应信息---------------------- #
response = requests.get("http://www.baidu.com")
response.status_code # 查看状态码
assert response.status_code == 200 # 判断请求是否成功
response.headers # 获取响应头,返回的是一个字典(dict)
response.request.headers # 获取请求头,返回的是一个字典(dict)
# -------------------发送带headers的请求------------------ #
headers = {请求头headers的信息}
response = requests.get("http://www.baidu.com",headers=headers) #发送带headers的请求
response.content.decode() # 解码
# -------------------发送携带参数的请求------------------ #
headers = {请求头headers的信息}
#方式一
p = {"wd":"python"}
url_temp = "https://www.baidu.com/s" # 定义请求模板
response = requests.get("http://www.baidu.com",headers=headers,params=p) #发送带参数的请求
#方式二
url = "https://www.baidu.com/s?wd={}".format("python")
response = requests.get(url,headers=headers) #发送带参数的请求
response.content.decode() # 解码
reponse.text和response.content的区别
- response.text
- 类型:str
- 解码类型:根据HTTP头部对响应的编码做出有根据的推测,推测的文本编码
- 修改编码方式:response.encoding=“gbk”
- response.content
- 类型:bytes
- 解码类型:没有指定
- 修改编码方式:response.content.decode(“utf8”)
七、requests深入----发送POST请求
哪些地方会用到POST请求:
- 登录注册(POST比GET更安全)
- 需要传输大文本内容的时候
- data和headers可以直接到界面上F12拿
用法:
import requests
import json
#data为字典(dict)
headers = {} # headers信息从浏览器上F12找
post_data = {} # data信息在浏览器上F12找
# 通过POST请求页面信息
response = requests.post("http://fanyi.www.baidu.com/basebreans",data=post_data,headers=headers)
print(response.content.decode()) # 输出解码后的数据,找到我们需要的数据
dict_ret = json.loads(r.content.decode())
ret = dict_ret["trans"][0]["dst"] # 在json数据中,找到想要的数据信息
八、request使用代理
为什么使用代理?
- 让服务器以为不是同一个客户端在请求
- 防止我们的真实地址泄露,防止被追究
用法:
requests.get("http://www.baidu.com",proxies=proxies)
# proxies格式:字典(dict)
# 代理IP可以去网上找
proxies = {
"http" : "http://12.34.56.79:9527",
"https" : "https://12.34.56.79:9527"
}
使用代理IP
-
得到一堆ip地址,组成ip池,随机选择一个ip来使用
-
随机选择代理ip
- {“ip”:ip,“time”:0}
- [{},{},{}]对这个ip列表进行排序,按照使用次数排序
- 选择使用次数较少的10个ip,从中随机选择一个
-
检查IP的可用性
- 可以使用requests添加超时参数,判断IP地址的质量
- 在线代理ip网站测试
九、cookie和session区别
- cookie数据存放在客户的浏览器上,session数据放在服务器上
- cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗
- session会在一定时间内保存在服务器上,到访问增多,会比较占用服务器的性能你
- 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点,最多保存20个cookie
爬虫处理cookie和session
-
带上cookie、session的好处
能够请求到登录之后的页面
-
带上cookie、session的弊端
一套cookie和session往往和一个用户对应
请求太快,请求次数太多,容易被服务器识别出来
获取登录后的页面的三种方式
- 实例化session,使用session发送post请求,在使用他获取登录后的界面
- headers添加cookie键,值为cookie字符串
- 在请求方法中添加cookies参数,接收字典形式的cookie。字典形式的cookie是cookie的name,值是cookievalue
requests获取响应的url地址和请求url的地址,如何发送post请求
response.url
response.request.url
requests.post(url,data={})
发送带headers的请求和params的请求
requests.get(url,headers={})
requests.get(url,params={})
使用代理,正向代理和反向代理的区别
requests.get(url,proxies={协议:协议+ip+端口})
# 正向代理:客户端知道最终服务器的地址
# 反向代理:客户端不知道最终服务器的地址
模拟登录的三种方式
-
session
-
实例化session(session具有的方法和requests一样)
-
session发送请求post请求,对方服务器设置的cookie会保存在session
-
session请求登录后能够访问的页面
-
-
cookie放在headers中
- headers = {“Cookie”:“cookie字符串”}
-
Cookie转化为字典放在请求方法中
requests.get(url,cookies={“name的值”:“values的值”})
import requests
import json
class Test:
def __init__(self,trans_str):
self.trans_str = trans_str
self.lang_detect_url = "http://fanyi.baidu.com/langdetect"
self.trans_url = "http://fanyi.baidu.com/basetrans"
self.headers = {"User-Agen":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40"}
def parse_url(self,url,data):
response = requests.post(url,data=data,headers=self.headers)
return json.loads(response.content.decode())
def get_ret(self,dict_response):#提取翻译的结果
ret = dict_response["trans"][0]["dst"]
print("result in :",ret)
def run(self): # 实现主要逻辑
# 1.获取语言类型
# 1.1 准备post的url地址,post_data
lang_detect_data = {"query":self.trans_str}
# 1.2 发送post请求,获取响应
lang = self.parse_url(self.lang_detect_url,lang_detect_data)["lan"]
# 1.3 提取语言类型
# 2.准备post的数据
trans_data = {"query":self.trans_str,"from":"zh","to","en"} if lang == "zh" else\
{"query":self.trans_str,"from":"en","to":"zh"}
# 3.发送请求,获取响应
dict_response = self.parse_url(self.trans_url.trans_data)
# 4.提取翻译的结果
self.get_ret(dict_response)
if __name__ == '__main__':
trans_str = sys.argv[1]
test = Test(trans_str)
test.run()