1. 程式人生 > >請求庫之requests

請求庫之requests

esp inux gsl with 初始 delete color 例子 登錄

一 介紹

#介紹:使用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://dig.chouti.com/)
print(response.text)

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

技術分享圖片
#在請求頭內將自己偽裝成瀏覽器,否則百度不會正常返回頁面內容
import requests
response=requests.get(https://www.baidu.com/s?wd=python&pn=1
, headers={ User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36, }) print(response.text) #如果查詢關鍵詞是中文或者有其他特殊符號,則不得不進行url編碼 from urllib.parse import urlencode wd=egon老師 encode_res=urlencode({k:wd},encoding=utf-8) keyword=encode_res.split(=)[1] print(keyword) # 然後拼接成url url=https://www.baidu.com/s?wd=%s&pn=1 %keyword response=requests.get(url, headers={ User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36, }) res1=response.text
自己拼接GET參數 技術分享圖片
#上述操作可以用requests模塊的一個params參數搞定,本質還是調用urlencode
from urllib.parse import urlencode
wd=egon老師
pn=1

response=requests.get(https://www.baidu.com/s,
                      params={
                          wd:wd,
                          pn:pn
                      },
                      headers={
                        User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36,
                      })
res2=response.text

#驗證結果,打開a.html與b.html頁面內容一樣
with open(a.html,w,encoding=utf-8) as f:
    f.write(res1) 
with open(b.html, w, encoding=utf-8) as f:
    f.write(res2)
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
View Code

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

#登錄github,然後從瀏覽器中獲取cookies,以後就可以直接拿著cookie登錄了,無需輸入用戶名密碼
#用戶名:egonlin 郵箱[email protected] 密碼lhf@123

import requests

Cookies={   user_session:wGMHFJKgDcmRIVvcA14_Wrt_3xaUyJNsBnPbYzEL6L0bHcfc,
}

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


print([email protected] 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請求,模擬瀏覽器的登錄行為

#對於登錄來說,應該輸錯用戶名或密碼然後分析抓包流程,用腦子想一想,輸對了瀏覽器就跳轉了,還分析個毛線,累死你也找不到包
技術分享圖片
‘‘‘
一 目標站點分析
    瀏覽器輸入https://github.com/login
    然後輸入錯誤的賬號密碼,抓包
    發現登錄行為是post提交到:https://github.com/session
    而且請求頭包含cookie
    而且請求體包含:
        commit:Sign in
        utf8:?
        authenticity_token:lbI8IJCwGslZS8qJPnof5e7ZkCoSoMn6jmDTsL1r/m06NLyIbw7vCrpwrFAPzHMep3Tmf/TSJVoXWrvDZaVwxQ==
        login:egonlin
        password:123


二 流程分析
    先GET:https://github.com/login拿到初始cookie與authenticity_token
    返回POST:https://github.com/session, 帶上初始cookie,帶上請求體(authenticity_token,用戶名,密碼等)
    最後拿到登錄cookie

    ps:如果密碼時密文形式,則可以先輸錯賬號,輸對密碼,然後到瀏覽器中拿到加密後的密碼,github的密碼是明文
‘‘‘

import requests
import re

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

#第二次請求:帶著初始cookie和TOKEN發送POST請求給登錄頁面,帶上賬號密碼
data={
    commit:Sign in,
    utf8:?,
    authenticity_token:authenticity_token,
    login:[email protected],
    password:alex3714
}
r2=requests.post(https://github.com/session,
             data=data,
             cookies=r1_cookie
             )


login_cookie=r2.cookies.get_dict()


#第三次請求:以後的登錄,拿著login_cookie就可以,比如訪問一些個人配置
r3=requests.get(https://github.com/settings/emails,
                cookies=login_cookie)

print([email protected] in r3.text) #True
自動登錄github(自己處理cookie信息) 技術分享圖片
import requests
import re

session=requests.session()
#第一次請求
r1=session.get(https://github.com/login)
authenticity_token=re.findall(rname="authenticity_token".*?value="(.*?)",r1.text)[0] #從頁面中拿到CSRF TOKEN

#第二次請求
data={
    commit:Sign in,
    utf8:?,
    authenticity_token:authenticity_token,
    login:[email protected],
    password:alex3714
}
r2=session.post(https://github.com/session,
             data=data,
             )

#第三次請求
r3=session.get(https://github.com/settings/emails)

print([email protected] in r3.text) #True
requests.session()自動幫我們保存cookie信息

3、補充

技術分享圖片
requests.post(url=xxxxxxxx,
              data={xxx:yyy}) #沒有指定請求頭,#默認的請求頭:application/x-www-form-urlencoed

#如果我們自定義請求頭是application/json,並且用data傳值, 則服務端取不到值
requests.post(url=‘‘,
              data={‘‘:1,},
              headers={
                  content-type:application/json
              })


requests.post(url=‘‘,
              json={‘‘:1,},
              ) #默認的請求頭: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
View Code

2、編碼問題

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

3、獲取二進制數據

技術分享圖片
import requests

response=requests.get(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1509868306530&di=712e4ef3ab258b36e9f4b48e85a81c9d&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)
View Code 技術分享圖片
#stream參數:一點一點的取,比如下載視頻時,如果視頻100G,用response.content然後一下子寫到文件中是不合理的

import requests

response=requests.get(https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo-transcode/1767502_56ec685f9c7ec542eeaf6eac93a65dc7_6fe25cd1347c_3.mp4,
                      stream=True)

with open(b.mp4,wb) as f:
    for line in response.iter_content():
        f.write(line)
獲取二進制流

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
View Code

5、Redirection and History

技術分享圖片
By default Requests will perform location redirection for all verbs except HEAD.

We can use the history property of the Response object to track redirection.

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.

For example, GitHub redirects all HTTP requests to HTTPS:

>>> r = requests.get(http://github.com)

>>> r.url
https://github.com/

>>> r.status_code

>>> r.history
[<Response [301]>]
If youre using GET, OPTIONS, POST, PUT, PATCH or DELETE, you can disable redirection handling with the allow_redirects parameter:

>>> r = requests.get(http://github.com, allow_redirects=False)

>>> r.status_code

>>> r.history
[]
If youre using HEAD, you can enable redirection as well:

>>> r = requests.head(http://github.com, allow_redirects=True)

>>> r.url
https://github.com/

>>> r.history
[<Response [301]>]
先看官網的解釋 技術分享圖片
import requests
import re

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

#第二次請求:帶著初始cookie和TOKEN發送POST請求給登錄頁面,帶上賬號密碼
data={
    commit:Sign in,
    utf8:?,
    authenticity_token:authenticity_token,
    login:[email protected],
    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登錄後跳轉到主頁面的例子來驗證它

請求庫之requests