requests模塊


一、介紹

#介紹:使用requests可以模擬瀏覽器的請求,比起之前用到的urllib,requests模塊的api更加便捷(本質就是封裝了urllib3)

#注意:requests庫發送請求將網頁內容下載下來以后,並不會執行js代碼,這需要我們自己分析目標站點然后發起新的request請求

#安裝:pip3 install requests

#各種請求方式:常用的就是requests.get()和requests.post()
>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r = requests.post('http://httpbin.org/post', data = {'key':'value'})
>>> r = requests.put('http://httpbin.org/put', data = {'key':'value'})
>>> r = requests.delete('http://httpbin.org/delete')
>>> r = requests.head('http://httpbin.org/get')
>>> r = requests.options('http://httpbin.org/get')

#建議在正式學習requests前,先熟悉下HTTP協議
http://www.cnblogs.com/linhaifeng/p/6266327.html

二、基於GET請求

1、基本請求

import requests
response=requests.get('http:/www.baidu.com/')
print(response.text)

2、帶參數的GET請求->params

 1 #在請求頭內將自己偽裝成瀏覽器,否則百度不會正常返回頁面內容
 2 import requests
 3 response=requests.get('https://www.baidu.com/s?wd=python&pn=1',
 4                       headers={
 5                         'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',
 6                       })
 7 print(response.text)
 8 
 9 
10 #如果查詢關鍵詞是中文或者有其他特殊符號,則不得不進行url編碼
11 from urllib.parse import urlencode
12 wb = "haiyan海燕"
13 encode_res = urlencode({"k":wb},encoding="utf-8")
14 print(encode_res)  #k=haiyan%E6%B5%B7%E7%87%95
15 keywords = encode_res.split("=")[1]  #haiyan%E6%B5%B7%E7%87%95
16 url = "https://www.baidu.com/s?wd=%s&pn=1"%(keywords)
17 # url = "https://www.baidu.com/s?"+encode_res
18 print(url)
19 # 然后拼接成url
20 response = requests.get(
21     url,
22     headers = {
23         "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",
24     }
25 )
自己拼接GET參數
 1 #上述操作可以用requests模塊的一個params參數搞定,本質還是調用urlencode
 2 from urllib.parse import urlencode
 3 wd='海燕nnn'
 4 pn=1
 5 
 6 response=requests.get('https://www.baidu.com/s',
 7                       params={
 8                           'wd':wd,
 9                           'pn':pn
10                       },
11                       headers={
12                         'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',
13                       })
14 res2=response.text
15 
16 #驗證結果,打開a.html與b.html頁面內容一樣
17 with open('a.html','w',encoding='utf-8') as f:
18     f.write(res1) 
19 with open('b.html', 'w', encoding='utf-8') as f:
20     f.write(res2)
21 
22 params參數的使用
params參數的使用

3、帶參數的GET請求->headers

#通常我們在發送請求時都需要帶上請求頭,請求頭是將自身偽裝成瀏覽器的關鍵,常見的有用的請求頭如下
Host
Referer #大型網站通常都會根據該參數判斷請求的來源
User-Agent #客戶端
Cookie #Cookie信息雖然包含在請求頭里,但requests模塊有單獨的參數來處理他,headers={}內就不要放它了
#添加headers(瀏覽器會識別請求頭,不加可能會被拒絕訪問,比如訪問https://www.zhihu.com/explore)
import requests
response=requests.get('https://www.zhihu.com/explore')
response.status_code #500


#自己定制headers
headers={
    'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36',

}
respone=requests.get('https://www.zhihu.com/explore',
                     headers=headers)
print(respone.status_code) #200

4、帶參數的GET請求->cookies

#登錄github,然后從瀏覽器中獲取cookies,以后就可以直接拿着cookie登錄了,無需輸入用戶名密碼
#用戶名:egonlin 郵箱378533872@qq.com 密碼lhf@123

import requests

Cookies={   'user_session':'wGMHFJKgDcmRIVvcA14_Wrt_3xaUyJNsBnPbYzEL6L0bHcfc',
}

response=requests.get('https://github.com/settings/emails',
             cookies=Cookies) #github對請求頭沒有什么限制,我們無需定制user-agent,對於其他網站可能還需要定制


print('378533872@qq.com' in response.text) #True

三、基於POST請求

1、介紹

#GET請求
HTTP默認的請求方法就是GET
     * 沒有請求體
     * 數據必須在1K之內!
     * GET請求數據會暴露在瀏覽器的地址欄中

GET請求常用的操作:
       1. 在瀏覽器的地址欄中直接給出URL,那么就一定是GET請求
       2. 點擊頁面上的超鏈接也一定是GET請求
       3. 提交表單時,表單默認使用GET請求,但可以設置為POST


#POST請求
(1). 數據不會出現在地址欄中
(2). 數據的大小沒有上限
(3). 有請求體
(4). 請求體中如果存在中文,會使用URL編碼!


#!!!requests.post()用法與requests.get()完全一致,特殊的是requests.post()有一個data參數,用來存放請求體數據

2、發送post請求,模擬瀏覽器的登錄行為

注意:
 1、對於登錄來說,應該輸錯用戶名或密碼然后分析抓包流程,用腦子想一想,輸對了瀏覽器就跳轉了,還分析個毛線,累死你也找不到包

  2、要做登錄的時候一定記得要把cookie先清除;
  3、requests.session():中間的cookie都不用自己分析了,有用的沒用的都給放進來了、
  4、response.cookie.get_dict()    #獲取cookie

 1 '''
 2 一 目標站點分析
 3     瀏覽器輸入https://github.com/login
 4     然后輸入錯誤的賬號密碼,抓包
 5     發現登錄行為是post提交到:https://github.com/session
 6     而且請求頭包含cookie
 7     而且請求體包含:
 8         commit:Sign in
 9         utf8:✓
10         authenticity_token:lbI8IJCwGslZS8qJPnof5e7ZkCoSoMn6jmDTsL1r/m06NLyIbw7vCrpwrFAPzHMep3Tmf/TSJVoXWrvDZaVwxQ==
11         login:egonlin
12         password:123
13 
14 
15 二 流程分析
16     先GET:https://github.com/login拿到初始cookie與authenticity_token
17     返回POST:https://github.com/session, 帶上初始cookie,帶上請求體(authenticity_token,用戶名,密碼等)
18     最后拿到登錄cookie
19 
20     ps:如果密碼時密文形式,則可以先輸錯賬號,輸對密碼,然后到瀏覽器中拿到加密后的密碼,github的密碼是明文
21 '''
22 
23 import requests
24 import re
25 
26 #第一次請求
27 r1=requests.get('https://github.com/login')
28 r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授權)
29 authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #從頁面中拿到CSRF TOKEN
30 
31 #第二次請求:帶着初始cookie和TOKEN發送POST請求給登錄頁面,帶上賬號密碼
32 data={
33     'commit':'Sign in',
34     'utf8':'',
35     'authenticity_token':authenticity_token,
36     'login':'317828332@qq.com',
37     'password':'alex3714'
38 }
39 r2=requests.post('https://github.com/session',
40              data=data,
41              cookies=r1_cookie
42              )
43 
44 
45 login_cookie=r2.cookies.get_dict()
46 
47 
48 #第三次請求:以后的登錄,拿着login_cookie就可以,比如訪問一些個人配置
49 r3=requests.get('https://github.com/settings/emails',
50                 cookies=login_cookie)
51 
52 print('317828332@qq.com' in r3.text) #True
53 
54 自動登錄github(自己處理cookie信息)
自動登錄github(自己處理cookie信息)
 1 import requests
 2 import re
 3 
 4 session=requests.session()
 5 #第一次請求
 6 r1=session.get('https://github.com/login')
 7 authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #從頁面中拿到CSRF TOKEN
 8 
 9 #第二次請求
10 data={
11     'commit':'Sign in',
12     'utf8':'',
13     'authenticity_token':authenticity_token,
14     'login':'317828332@qq.com',
15     'password':'alex3714'
16 }
17 r2=session.post('https://github.com/session',
18              data=data,
19              )
20 
21 #第三次請求
22 r3=session.get('https://github.com/settings/emails')
23 
24 print('317828332@qq.com' in r3.text) #True
requests.session()自動幫我們保存cookie信息

登錄github小應用

import requests
import re
#第一次請求
    # GET請求
    # 請求頭
    #    - 獲取token和
    #    - User-agent
    #    - cookie
# 第二次請求
    #POST請求
    #請求頭
        # referer
        # User-agent
    #請求體
        #獲取data
# 第三次請求,登錄成功之后
    #- 請求之前自己先登錄一下,看一下有沒有referer
    #- 請求新的url,進行其他操作
    #- 查看用戶名在不在里面
#第一次請求
response1 = requests.get(
    "https://github.com/login",
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",
    },
)
authenticity_token = re.findall('name="authenticity_token".*?value="(.*?)"',response1.text,re.S)
r1_cookies =  response1.cookies.get_dict()
# print(r1_cookies,"cookie")  #獲取到的cookie

#第二次請求
response2 = requests.post(
    "https://github.com/session",
    headers = {
        "Referer": "https://github.com/",
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",
    },
    data={
            "commit":"Sign in",
            "utf8":"",
            "authenticity_token":authenticity_token,
            "login":"haiyanzzz",
            "password":"xxxx",
zhy..azjash1234
    },
    cookies = r1_cookies
)
print(response2.status_code)
print(response2.history)  #跳轉的歷史狀態碼

#第三次請求,登錄成功之后,訪問其他頁面
r2_cookies = response2.cookies.get_dict()  #拿上cookie,知道是你登錄了,就開始訪問頁面
response3 = requests.get(
    "https://github.com/settings/emails",
    headers = {
        "Referer": "https://github.com/",
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36",
    },
    cookies = r2_cookies,
)
print(response3.text)
print("haiyanzzz" in response3.text)   #True返回True說明就成功了

3、補充

 1 requests.post(url='xxxxxxxx',
 2               data={'xxx':'yyy'}) #沒有指定請求頭,#默認的請求頭:application/x-www-form-urlencoed
 3 
 4 #如果我們自定義請求頭是application/json,並且用data傳值, 則服務端取不到值
 5 requests.post(url='',
 6               data={'':1,},
 7               headers={
 8                   'content-type':'application/json'
 9               })
10 
11 
12 requests.post(url='',
13               json={'':1,},
14               ) #默認的請求頭:application/json
View Code

四、響應Response

1、response屬性

import requests
respone=requests.get('http://www.jianshu.com')
# respone屬性
print(respone.text)
print(respone.content)

print(respone.status_code)
print(respone.headers)
print(respone.cookies)
print(respone.cookies.get_dict())
print(respone.cookies.items())

print(respone.url)
print(respone.history)

print(respone.encoding)

#關閉:response.close()
from contextlib import closing
with closing(requests.get('xxx',stream=True)) as response:
    for line in response.iter_content():
    pass

 

2、編碼問題

#編碼問題
import requests
response=requests.get('http://www.autohome.com/news')
# response.encoding='gbk' #汽車之家網站返回的頁面內容為gb2312編碼的,而requests的默認編碼為ISO-8859-1,如果不設置成gbk則中文亂碼
print(response.text)

 

3、獲取二進制數據

import requests

response=requests.get('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1509868306530&di=712e4ef3ab258b3
6e9f4b48e85a81c9d&imgtype=0&src=http%3A%2F%2Fc.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F11385343fbf2b211e1fb58a1c08065380dd78e0c.jpg
') with open('a.jpg','wb') as f: f.write(response.content)

 

stream參數:一點一點的取,比如下載視頻時,如果視頻100G,用response.content然后一下子寫到文件中是不合理的
 1 #stream參數:一點一點的取,比如下載視頻時,如果視頻100G,用response.content然后一下子寫到文件中是不合理的
 2 
 3 import requests
 4 
 5 response=requests.get('https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo-transcode/1767502_56ec685f9c7ec542eeaf6eac93a65dc7_6fe25cd1347c_3.mp4',
 6                       stream=True)
 7 
 8 with open('b.mp4','wb') as f:
 9     for line in response.iter_content():
10         f.write(line)
獲取二進制流(iter_content)

 

4、解析json

#解析json
import requests
response=requests.get('http://httpbin.org/get')

import json
res1=json.loads(response.text) #太麻煩

res2=response.json() #直接獲取json數據


print(res1 == res2) #True

 

 

 

5、Redirection and History

 1 By default Requests will perform location redirection for all verbs except HEAD.
 2 
 3 We can use the history property of the Response object to track redirection.
 4 
 5 The Response.history list contains the Response objects that were created in order to complete the request. The list is sorted from the oldest to the most recent response.
 6 
 7 For example, GitHub redirects all HTTP requests to HTTPS:
 8 
 9 >>> r = requests.get('http://github.com')
10 
11 >>> r.url
12 'https://github.com/'
13 
14 >>> r.status_code
15 
16 >>> r.history
17 [<Response [301]>]
18 If you're using GET, OPTIONS, POST, PUT, PATCH or DELETE, you can disable redirection handling with the allow_redirects parameter:
19 
20 >>> r = requests.get('http://github.com', allow_redirects=False)
21 
22 >>> r.status_code
23 
24 >>> r.history
25 []
26 If you're using HEAD, you can enable redirection as well:
27 
28 >>> r = requests.head('http://github.com', allow_redirects=True)
29 
30 >>> r.url
31 'https://github.com/'
32 
33 >>> r.history
34 [<Response [301]>]
35 
36 先看官網的解釋
View Code

 

import requests
import re

#第一次請求
r1=requests.get('https://github.com/login')
r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授權)
authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #從頁面中拿到CSRF TOKEN

#第二次請求:帶着初始cookie和TOKEN發送POST請求給登錄頁面,帶上賬號密碼
data={
    'commit':'Sign in',
    'utf8':'',
    'authenticity_token':authenticity_token,
    'login':'317828332@qq.com',
    'password':'alex3714'
}






#測試一:沒有指定allow_redirects=False,則響應頭中出現Location就跳轉到新頁面,r2代表新頁面的response
r2=requests.post('https://github.com/session',
             data=data,
             cookies=r1_cookie
             )

print(r2.status_code) #200
print(r2.url) #看到的是跳轉后的頁面
print(r2.history) #看到的是跳轉前的response
print(r2.history[0].text) #看到的是跳轉前的response.text


#測試二:指定allow_redirects=False,則響應頭中即便出現Location也不會跳轉到新頁面,r2代表的仍然是老頁面的response
r2=requests.post('https://github.com/session',
             data=data,
             cookies=r1_cookie,
             allow_redirects=False
             )


print(r2.status_code) #302
print(r2.url) #看到的是跳轉前的頁面https://github.com/session
print(r2.history) #[]

利用github登錄后跳轉到主頁面的例子來驗證它

 

五、高級用法

1、SSL Cert Verification

 1 #證書驗證(大部分網站都是https)
 2 import requests
 3 respone=requests.get('https://www.12306.cn') #如果是ssl請求,首先檢查證書是否合法,不合法則報錯,程序終端
 4 
 5 
 6 #改進1:去掉報錯,但是會報警告
 7 import requests
 8 respone=requests.get('https://www.12306.cn',verify=False) #不驗證證書,報警告,返回200
 9 print(respone.status_code)
10 
11 
12 #改進2:去掉報錯,並且去掉警報信息
13 import requests
14 from requests.packages import urllib3
15 urllib3.disable_warnings() #關閉警告
16 respone=requests.get('https://www.12306.cn',verify=False)
17 print(respone.status_code)
18 
19 #改進3:加上證書
20 #很多網站都是https,但是不用證書也可以訪問,大多數情況都是可以攜帶也可以不攜帶證書
21 #知乎\百度等都是可帶可不帶
22 #有硬性要求的,則必須帶,比如對於定向的用戶,拿到證書后才有權限訪問某個特定網站
23 import requests
24 respone=requests.get('https://www.12306.cn',
25                      cert=('/path/server.crt',
26                            '/path/key'))
27 print(respone.status_code)
View Code

 

2、使用代理

 1 #官網鏈接: http://docs.python-requests.org/en/master/user/advanced/#proxies
 2 
 3 #代理設置:先發送請求給代理,然后由代理幫忙發送(封ip是常見的事情)
 4 import requests
 5 proxies={
 6     'http':'http://egon:123@localhost:9743',#帶用戶名密碼的代理,@符號前是用戶名與密碼
 7     'http':'http://localhost:9743',
 8     'https':'https://localhost:9743',
 9 }
10 respone=requests.get('https://www.12306.cn',
11                      proxies=proxies)
12 
13 print(respone.status_code)
14 
15 
16 
17 #支持socks代理,安裝:pip install requests[socks]
18 import requests
19 proxies = {
20     'http': 'socks5://user:pass@host:port',
21     'https': 'socks5://user:pass@host:port'
22 }
23 respone=requests.get('https://www.12306.cn',
24                      proxies=proxies)
25 
26 print(respone.status_code)
View Code

 

3、超時設置

1 #超時設置
2 #兩種超時:float or tuple
3 #timeout=0.1 #代表接收數據的超時時間
4 #timeout=(0.1,0.2)#0.1代表鏈接超時  0.2代表接收數據的超時時間
5 
6 import requests
7 respone=requests.get('https://www.baidu.com',
8                      timeout=0.0001)
View Code

 

4、 認證設置

 1 #官網鏈接:http://docs.python-requests.org/en/master/user/authentication/
 2 
 3 #認證設置:登陸網站是,彈出一個框,要求你輸入用戶名密碼(與alter很類似),此時是無法獲取html的
 4 # 但本質原理是拼接成請求頭發送
 5 #         r.headers['Authorization'] = _basic_auth_str(self.username, self.password)
 6 # 一般的網站都不用默認的加密方式,都是自己寫
 7 # 那么我們就需要按照網站的加密方式,自己寫一個類似於_basic_auth_str的方法
 8 # 得到加密字符串后添加到請求頭
 9 #         r.headers['Authorization'] =func('.....')
10 
11 #看一看默認的加密方式吧,通常網站都不會用默認的加密設置
12 import requests
13 from requests.auth import HTTPBasicAuth
14 r=requests.get('xxx',auth=HTTPBasicAuth('user','password'))
15 print(r.status_code)
16 
17 #HTTPBasicAuth可以簡寫為如下格式
18 import requests
19 r=requests.get('xxx',auth=('user','password'))
20 print(r.status_code)
View Code

 

5、異常處理

 1 #異常處理
 2 import requests
 3 from requests.exceptions import * #可以查看requests.exceptions獲取異常類型
 4 
 5 try:
 6     r=requests.get('http://www.baidu.com',timeout=0.00001)
 7 except ReadTimeout:
 8     print('===:')
 9 # except ConnectionError: #網絡不通
10 #     print('-----')
11 # except Timeout:
12 #     print('aaaaa')
13 
14 except RequestException:
15     print('Error')
View Code

 

6、上傳文件

 

 

1 import requests
2 files={'file':open('a.jpg','rb')}
3 respone=requests.post('http://httpbin.org/post',files=files)
4 print(respone.status_code)
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM