文章目录
一、前言
- requests模块用法简单,抓取校验规则简单的网站很好用,但是规则复杂难以破解的网站建议使用selenium模拟浏览器
- requests抓下来的html结构可以使用如下几种方式解析:
<1>使用re模块正则匹配
<2>使用etree解析【推荐】
<3>使用beautifulsoup解析 - xpath教程可以参考这里:https://www.runoob.com/xpath/xpath-tutorial.html
二、安装模块
pip install requests lxml
三、使用方法
1.导包
import requests
from lxml import etree # 解析html
import json # 解析json
2.发送请求
<1>get
# url
url = 'http://xxxx'
# 参数
params = {
"searchKey": "东野圭吾",
"pageNo": "10"
}
# 请求
res = requests.get(url=url, params=params)
<2>post
# url
url ='http://xxxx'
# 参数
data = {
"searchKey": "东野圭吾",
"pageNo": "10"
}
# 请求[作为data-format传参]
res = requests.get(url=url, data=data)
# 请求[作为json传参]
res = requests.get(url=url, json=data)
ps:put、delete 使用方法跟 post 差不多,很少用到
3.接收参数
<1>返回数据为json
# 自动匹配返回数据编码,可以避免出现解码错误产生的乱码
# 如果还是出现乱码,就指定为具体的编码格式
# 如果依然是乱码,那可能是加密了,需要在前端页面的js里找到那个解密的方法
res.encoding = "unicode_escape"
# 请求失败抛异常结束
if not res.status_code == 200:
raise Exception("请求失败")
# 解析json
dataJson = json.loads(res.text)
print(dataJson)
# {'Status': 0, 'Data': {'videoTotal': 1401, 'courseTotal': 17, 'count': 1401, 'row' ...
# 取出数据
videoTotal = dataJson['Data']['videoTotal']
courseTotal = dataJson['Data']['courseTotal']
<2>返回数据为html
# 自动匹配返回数据编码,可以避免出现解码错误产生的乱码
# 如果还是出现乱码,就指定为具体的编码格式
# 如果依然是乱码,那可能是加密了,需要在前端页面的js里找到那个解密的方法
res.encoding = "unicode_escape"
# 请求失败抛异常结束
if not res.status_code == 200:
raise Exception("请求失败")
# 解析html
dom = etree.HTML(res.text)
# 取出单个数据 --------------------------------------------------------
total = dom.xpath('//*[@class="record"]/*[@id="searchlist"]/text()') # xpath解析,返回一个结果数组
print(total) # [" 451 "]
# 这里可以使用total[0]来取出结果,但是你不能保证一定可以取出数据,如果返回的是一个空数组[],那么直接按下标取会抛异常
# 可以用三元表达式判断total数组不为空的情况再取数据否则返回None
# 字符串.strip()用于去除两端空格
# int()转整数
total = int(total[0].strip()) if total else None
print(total) # 451
# -------------------------------------------------------------------
# 取出多个数据 --------------------------------------------------------------
urlList = dom.xpath('//*[@id="searchlist"]//*[@class="datafw"]//@href') # xpath解析,返回一个结果数组
print(urlList) # ["http://xx1", "http://xx2", "http://xx3", "http://xx4"]
# -------------------------------------------------------------------------
# xpath二次解析 ----------------------------------------------------------------
bookDomList = dom.xpath('//*[@id="searchlist"]//*[@class="datafw"]') # 取出一个dom数组
book_list = []
for bookDom in bookDomList: # 遍历当前dom数组进行二次解析
title = bookDom.xpath('.//*[@dmcode="1987051001"]//text()')
title = ''.join(title)
# print(title)
author = bookDom.xpath('.//div[@class="mdcontainer"]/p[2]//font/text()')
author = ''.join(author)
# print(author)
book = {} # 加入字典
book['title'] = title
book['author'] = author
book_list.append(book) # 插入数组
print(book_list)
# [
# {"title": "大学生计算机应用基础", "author": "刘志成,陈佳"},
# {"title": "计算机组装与维护立体化教程(微课版)", "author": "汪鹏飞,赖作华"}
# ....
# ]
# -----------------------------------------------------------------------------
4.注意事项
总结几个常见的情况
<1>设置请求最大等待时长
res = requests.get(url="http://xxx", timeout=5) # 最多等5秒,否则抛出请求失败异常
<2>设置不校验ssl证书
res = requests.post(url="https://xxx", verify=False)
<3>请求头添加随机User-Agent
可以用这个随机ua的方法:https://blog.csdn.net/weixin_43721000/article/details/120695975
from uaUtil import get_user_agent
headers = {
'User-Agent': get_user_agent()
}
res = requests.post(url="https://xxx", headers=headers)
<4>请求头添加Referer、Host、Cookie、Accept-Encoding
如果按照以上方法请求数据没有正常返回,那么检查如下几个请求头中的参数:
- Referer:请求来源
- Host:当前主机
- Accept-Encoding:声明浏览器编码类型
- Cookie:浏览器存储
F12看一下页面上的请求怎么设置的,跟他一样就行了,需要注意的是Cookie可能是加密的或者是一串随机数,如果找不到规律的话只能使用 selenium 了,但是能用 requests 尽量使用 requests 毕竟 selenium 要启动一个浏览器驱动,那样会很慢
<5>设置代理
当请求过于频繁导致ip被封禁的时候,可以使用代理ip,每家代理ip的使用方法不同,需要参照对方提供的api进行设置,但是尽量不要去使用代理ip而是控制好爬虫的频率比较好。
一般有两种办法:
- 全局设置代理
proxy_ip_port = 'ip:端口号'
os.environ.update(HTTP_PROXY=f'http://{proxy_ip_port}', HTTPS_PROXY=f'http://{proxy_ip_port}')
# os.environ.update(HTTP_PROXY='http://127.0.0.1:7890', HTTPS_PROXY='http://127.0.0.1:7890')
- 单次请求设置
proxy_ip_port = 'ip:端口号'
proxies = {
'http': f'http://{proxy_ip_port}',
'https': f'http://{proxy_ip_port}',
}
res = requests.get('http://www.baidu.com', proxies=proxies)