说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
Requests 是一个针对人类的优雅而简单的Python HTTP库。可以实现网络数据获取的爬虫功能。所谓针对人类,是指人性化的,可直观理解的。官网 和 github 。
Requests 完全满足当今 web 的需求。
Requests 是网络访问请求,所以在使用时需要了解 http 协议内容,在解析获取到的数据内容需要了解 json、html、js 等前端网络知识、最近流行的网站架构知识,同时还需要了解正则的使用方法。
获取网络数据一般有两种情况:
有些内容需要登录,还需要了解网络的登录、鉴权机制。
对于需要渲染有页面,推荐使用 requests-html
、Selenium
库。
pip install requests
我们发起一次 get 请求,使用用户名和密码,将结果赋值给变量 r :
import requests
r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
# r = requests.get('https://api.github.com')
r.status_code # 状态码 200 是成功
# 200
# 由于布尔方法被重写,可以通过真假判断是否登录成功
r.__bool__()
# True
HTTP POST 请求,一般用于登录和提交数据:
r = requests.post('http://httpbin.org/post', data = {'key':'value'})
# 其他
requests.post('https://httpbin.org/post', data={'key':'value'})
requests.put('https://httpbin.org/put', data={'key':'value'})
requests.delete('https://httpbin.org/delete')
requests.head('https://httpbin.org/get')
requests.patch('https://httpbin.org/patch', data={'key':'value'})
requests.options('https://httpbin.org/get')
可查看 r.request
信息:
r = requests.post('https://httpbin.org/post', json={'key':'value'})
r.request.headers['Content-Type']
# 'application/json'
r.request.url
# 'https://httpbin.org/post'
r.request.body
# b'{"key": "value"}'
r.request.method
# 'POST'
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
r.url # 看一下拼接好的 url
# http://httpbin.org/get?key2=value2&key1=value1
字典里值为 None 的键都不会被添加到 URL 的查询字符串里。你还可以将一个列表作为值传入:
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.url)
# http://httpbin.org/get?key1=value1&key2=value2&key2=value3
登录一般是HTTP POST 请求,如果没有验证码的话非常简单(需要使用图像识别相关库),典型代码为:
import requests
import json
headers = {'user-agent': 'Mozilla/5.0...',
# 无格式要求不指定
'Content-Type': 'application/json;charset=UTF-8'}
# 其他 {'Content-Type': 'application/x-www-form-urlencoded'}
s = requests.session()
login_data = dict(userName='xxx', password='xxxx')
s.post('http://www.gairuo.com/user_login', # 示意假网址
data=json.dumps(login_data), # 无格式要求直接传 login_data
headers=headers)
# 获取网页内容
r = s.get('http://www.gairuo.com')
POST一个多部分编码(Multipart-Encoded)的文件,Requests 使得上传多部分编码文件变得很简单:
>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
>>> r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
你可以显式地设置文件名,文件类型和请求头:
url = 'http://httpbin.org/post'
files = {'file': ('report.xls', open('report.xls', 'rb'),
'application/vnd.ms-excel',
{'Expires': '0'})
}
r = requests.post(url, files=files)
r.text
'''
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
'''
如果你发送一个非常大的文件作为 multipart/form-data 请求,你可能希望将请求做成数据流。默认下 requests 不支持, 但有个第三方包 requests-toolbelt 是支持的。你可以阅读 toolbelt 文档 来了解使用方法。
通过以上进行访问后,可以获取以下内容:
r.headers # 头信息
# {'date': 'Wed, 22 J...
r.headers['content-type'] # 头信息中的内容类型
# 'application/json; charset=utf8'
r.encoding # 编码
# 'utf-8'
r.encoding = 'ISO-8859-1' # 可以修改编码
r.content # 二进制响应内容
# b'{"type":"User"...'
r.text # 格式化内容
# u'{"type":"User"...'
r.json() # json 化
# {u'private_gists': 419, u'total_private_repos': 77, ...}
接下来,重点需要解析 r.text 中的 html 内容,一般使用 beautifulsoup4 进行解析(后续会介绍 todo)。对于 json 格式,推荐使用 pandas 中的 pd.read_json()
进行解析。
如果某个响应中包含一些 cookie,你可以快速访问它们:
url = 'http://example.com/some/cookie/setting/url'
r = requests.get(url)
r.cookies['example_cookie_name']
# 'example_cookie_value'
要想发送你的cookies到服务器,可以使用 cookies 参数:
url = 'http://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
r.text
# '{"cookies": {"cookies_are": "working"}}'
Cookie 的返回对象为 RequestsCookieJar,它的行为和字典类似,但接口更为完整,适合跨域名跨路径使用。你还可以把 Cookie Jar 传到 Requests 中:
jar = requests.cookies.RequestsCookieJar()
jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
url = 'http://httpbin.org/cookies'
r = requests.get(url, cookies=jar)
r.text
# '{"cookies": {"tasty_cookie": "yum"}}'
由于 Selenium 太慢,可以用多线程解决。以下是一个简单的多线程用户示例:
# 爬虫
def get_data(page_id):
url = f'https://xxxPage?Id='
r = s.get(url)
df = pd.DataFrame(r.json()['data']['items'])
df.to_csv(f'card/xxx-{page_id}.csv')
print(f'{page_id}页已获取')
# 定义好爬虫及传值范围
def run(start, end):
for i in range(start, end+1):
get_data(i)
# 引入相关库
import threading
import time
# 分批同时执行
%%time
t1 = threading.Thread(target=run, args=(1, 100))
t2 = threading.Thread(target=run, args=(101, 200))
t3 = threading.Thread(target=run, args=(201, 300))
t1.start()
t2.start()
t3.start()
todo
s = requests.session()
s.get('https://www.gairuo.com', timeout=0.001) # 设置最大超时秒数
# 将连接适配器注册到前缀, 适配器按前缀长度降序排列
# 设置最大重试次数
from requests.adapters import HTTPAdapter
s.mount('http://', HTTPAdapter(max_retries=8))
s.mount('https://', HTTPAdapter(max_retries=8))
todo
遇到网络问题(如:DNS 查询失败、拒绝连接等)时,Requests 会抛出一个 ConnectionError 异常。
如果 HTTP 请求返回了不成功的状态码, Response.raise_for_status() 会抛出一个 HTTPError 异常。
若请求超时,则抛出一个 Timeout 异常。
若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects 异常。
所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException 。
更新时间:2022-12-11 19:29:05 标签:python requests 爬虫