天天看点

Python Requests爬虫库的基本用法

简单介绍

目前很多的教程中都会有讲到

requests

,但它们通常从整个爬虫的原理讲起,讲到这部分知识时更多的注重于呈现运行结果。这里我将结合自身的使用做一个简单总结,对需要特别注意的点进行标注,代码很少,但其模式已经足够适用于大部分目标。

使用方法

基本用法(

GET

)

GET

请求方式是最常用的方式:

import requests

url = "http://www.httpbin.org/ip"
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
} 

res = requests.get(url=url, headers=headers)
print(res.text)      # 得到响应的文本格式(unicode),用res.content可以获取二进制文件如图片
           

基本用法(

POST

)

POST

方式常用在登陆及json获取时:

import requests

url = "http://www.httpbin.org/post"
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
} 

data = {        # 构造data数据
    'user': 'test_name',
    'passwd': 'test_passwd'
}   

res = requests.post(url=url, headers=headers, data=data)
print(res.text)
           

基本的用法如上所示,十分简单,唯一值得注意的是

headers

,绝大多数网站会检测请求头,这基本上是爬虫的第一道关卡。通常仅设置一个

User-Agent

就可以访问一些简单的站点,但是更多的网站可能会借助其它字段进行一个人机判断。常见的请求头格式如下:

headers = {
    "Accept": "application/json",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Connection": "close",
    "Content-Length": "0",
    "Cookie": "_gauges_unique_year=1; _gauges_unique=1; _gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1",
    "Host": "www.httpbin.org",
    "Origin": "http://www.httpbin.org",
    "Referer": "http://www.httpbin.org/",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
}
           

关于请求头的设置,建议是从浏览器全部复制(对于新手一定是宁多勿少,也有例外,如编码,后面会将),除非你能明确其中一部分是对身份判断无关的,而这通常是试出来的,具有被封禁的危险,特别是对应内容分发服务器地址时尤为注意。

乱码的解决思路

方法1:

# 查看`headers`中是否设置:
'accept-encoding': 'gzip, deflate, br',
# 如果有,修改为:
'accept-encoding': 'gzip',
           

方法2:

安装brotlipy,依照文档使用。

原因为你同意了该种压缩方式后,有的服务器便采用了

br

这种压缩方法。

当然如果还是乱码,可以从编码方面下手做解决思路,此处不做论述。只是建议首先尝试上述的方式,这通常已经能解决问题了。

Cookies

的使用

cookies

参数配合字典:

cookies = dict('test_token': '_123456')  

res = requests.get(url=url, headers=headers, cookies=cookies)
           

cookies

参数配合

RequestCookiesJar

:

cookies_jar = requests.cookies.RequestsCookieJar()
cookies_jar = cookies_jar.set('test_token', '_123456', domain='httpbin.org', path='/')

res = requests.get(url, headers=headers, cookies=cookies_jar)

           

代理的使用

proxies = {
    'http': '134.xxx.xxx.xxx:xxx'       # 代理iP的ip地址
}

res = requests.get(url=url, headers=headers, cookies=cookies, proxies=proxies)

           

如果需要使用代理,这里需要设置代理

IP

,对代理池有兴趣可以参考我的另一篇文章:利用Python建立和维护爬虫代理IP池,或直接在我的

github

上查看代理池源码,此处不展开。

超时设置

这一点我想重点强调,因为这是很容易忽视的一个问题,特别是当你还没有遇到这个问题时。

先说设置,设置很简单,如下:

res = requests.get(url=url, headers=headers, cookies=cookies, proxies=proxies, timeout=5)    # 连接和读取超时均设置为5s
res = requests.get(url=url, headers=headers, cookies=cookies, proxies=proxies, timeout=(3, 5))   # 连接超时3s,读取超时5s
           

再说原因,

requests

默认参数是无限等待,如果你没有超时检测机制(事实上好多教程也没有提),那么当你得意洋洋的让你的爬虫在服务器上跑了几小时几天,然后打开一看的结果,很有可能是:停了!

这个小细节很重要,请务必记住。但是我也不明白它为什么在文档的最后…

Session

的使用

这里先说两个典型的场景:

  1. 账号登入后维持

    cookies

    ,达到复用的效果。
  2. 同一个网站为了防止账号被封,同时登入多个账号有序抓取。

Session

便是解决这些问题的,它会在同一个实例发出的所有请求之间保持

cookie

。配置如下:

import requests

url = "http://www.httpbin.org/ip"
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
} 

cookies = {     # 实际使用中建议敏感信息放置在不共享的配置文件中,通过导入读取
    'user': 'xxx',
    'auth': 'xxx',
}     

s = requests.session()  # 创建session
requests.utils.add_dict_to_cookiejar(s.cookies, cookeis)    # 为session添加cookies

res = s.get(url=url, headers=headers, timeout=60)   # 通过session访问链接
print(res.text)
           

注意实际环境中,关于账号的

cookies

很可能是通过

post

方法请求某个页面(如登陆页)得到的,而不是提前就准备好的。因为

cookie

通常具有时效性,我们常用的方式是在一定的时间周期内请求更新一次,避免失效。

下面是通过访问页面获取

cookies

结合

session

的代码演示:

"""仅作示范提供思路,login_url并未配置,配置后参数也需要根据实际修改"""

import requests

def get_cookies(username, passwd):
    """从登陆页获取cookeis_jar"""
    login_url = ""      # 登陆链接
    headers = {}        # 登陆页的请求头
    login_data = {      # 登陆post data
        'username': 'test_name',
        'password': 'test_password',
    }
    
    res = requests.post(url=login_url, headers=headers, data=data)
    ck_jar = res.cookies   # 获取返回的cookies_jar
    
    return ck_jar


def edit_cookies(cookiejar):
    """编辑cookiejar,构造需要的cookie"""
    ck_dict = requests.utils.dict_from_cookiejar(ck_jar)    # 转换为字典
    cookies = {
        "name": ck_dict['name'],    
        "auth": ck_dict['auth'],    # 提取出name和auth组成一个新cookies
    }
    
    return cookies
    
    
def gen_session(cookies):
    """构造session"""
    s = requests.session()
    requests.utils.add_dict_to_cookiejar(s.cookies, cookeis)  # 配置session的cookeis参数
    return s
    
        
if __name__ == "__main__":

    url = "http://www.httpbin.org/cookies"
    headers = {     # 内容页的请求头(此处为方便理解设置为一样,实际不同的页面中可能不同)
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
    }    
    
    s1 =  gen_session(edit_cookies(get_cookies(username="user1", password="123")))   # 构造session1
    s1 =  gen_session(edit_cookies(get_cookies(username="user2", password="456")))   # 构造session2
    
    s1.get(url=url, headers=headers, timeout=60)    # 账号1访问url
    s2.get(url=url, headers=headers, timeout=60)    # 账号2访问url
    
    print(s1.cookies)
    print(s2.cookies)

           

其它

  • 通过检测返回状态码,可以判断是否访问成功,增加相应的容错
  • 建议把

    requests

    访问部分封装成一个函数或类方法,在里面增加错误捕捉,错误时休眠及循环访问的功能,一劳永逸。
总结

以上的几点已经涵盖我目前使用

requests

的大部分场景了,对于其它一些的需求都是特定场景下才需要了,在文档中均有涵盖,建议大家收藏Requests文档,遇到问题时可以直接查阅。