Python Requests library redirect new url

Posted in :

我想去猜演唱會門票的購買URL, 使用 requests 來判斷 url 是否存在,遇到 server side 會使用 http code 302 來 redirect. 變成結論都是存在的網頁。但我想測試是不是404。

解法:可以看一下 history 裡有沒有資料。

requests 使用方法:
https://requests.readthedocs.io/en/master/

The response.history attribute is a list of responses that led to the final URL, which can be found in response.url.

import requests
response = requests.get(someurl)
if response.history:
    print("Request was redirected")
    for resp in response.history:
        print resp.status_code, resp.url
    print("Final destination:",response.status_code, response.url)
else:
    print("Request was not redirected")

print(response.content)

Demo:

>>> import requests
>>> response = requests.get('http://httpbin.org/redirect/3')
>>> response.history
(<Response [302]>, <Response [302]>, <Response [302]>)
>>> for resp in response.history:
...     print resp.status_code, resp.url
... 
302 http://httpbin.org/redirect/3
302 http://httpbin.org/redirect/2
302 http://httpbin.org/redirect/1
>>> print response.status_code, response.url
200 http://httpbin.org/get

requests 模組可以使用 pip 來安裝:

# 安裝 Python 2 的 requests 模組
pip install requests

# 安裝 Python 3 的 requests 模組
pip3 install requests2

自訂請求表頭

在進階的網路爬蟲程式中,自訂請求表頭也是一個很常被使用的技術,以下是一個簡單的範例:

# 自訂表頭
my_headers = {'user-agent': 'my-app/0.0.1'}

# 將自訂表頭加入 GET 請求中
r = requests.get('http://httpbin.org/get', headers = my_headers)

帳號密碼登入

若遇到需要帳號與密碼登入後才能看的網頁(HTTP 基本認證),可以使用 auth 參數指定帳號與密碼:

# 需要帳號登入的網頁
r = requests.get('https://api.github.com/user', auth=('user', 'pass'))

POST 請求

POST 請求也是很常用的 HTTP 請求,只要是網頁中有讓使用者填入資料的表單,大部分都會需要用 POST 請求來處理,以下是一個簡單的範例:

# 資料
my_data = {'key1': 'value1', 'key2': 'value2'}

# 將資料加入 POST 請求中
r = requests.post('http://httpbin.org/post', data = my_data)

若有遇到重複鍵值(key)的 HTML 表單欄位,可以這樣處理:

# 具有重複鍵值的資料
my_data = (('key1', 'value1'), ('key1', 'value2'))

# 將資料加入 POST 請求中
r = requests.post('http://httpbin.org/post', data = my_data)

伺服器回傳值

使用 r.content 取得傳回的資料,直接印出 r 只能拿到 header

r = requests.get("http://www.google.com")
print(r.content)

上傳檔案

若要上傳檔案,也可以使用 POST 請求來處理,這是一個上傳 Word 文件的範例:

# 要上傳的檔案
my_files = {'my_filename': open('my_file.docx', 'rb')}

# 將檔案加入 POST 請求中
r = requests.post('http://httpbin.org/post', files = my_files)

Cookie

如果伺服器傳回的網頁資料中含有 cookies,requests 也可以輕鬆取出 cookies 的資料:

# 含有 cookie 的內容
r = requests.get("http://my.server.com/has/cookies")

# 取出 cookie
print(r.cookies['my_cookie_name'])

若要將自己設定的 cookies 放進 GET 請求中送給伺服器,可以這樣寫:

# 設定 cookie
my_cookies = dict(my_cookie_name='G. T. Wang')

# 將 cookie 加入 GET 請求
r = requests.get("http://httpbin.org/cookies", cookies = my_cookies)

常見問題

這裡列出一些實務上常見的問題與解決方式。

等待逾時

requests 預設會一直等待直到伺服器完成回應為止,如果想改變等待逾時設定,可以用 timeout 設定(單位為秒):

# 等待 3 秒無回應則放棄
requests.get('http://github.com/', timeout = 3)

等待逾時設定是指伺服器無回應的狀態下所等待的時間,更精確的說就是完全沒有收到任何資料的狀況下,可等待的最常時間。

自簽(不合格)憑證

當我們在自架網頁伺服器進行測試時,HTTPS 時常會有憑證不合格的問題,當 requests 遇到這種伺服器就容易會出現 requests.exceptions.SSLError 這樣的錯誤,解決的方式就是加上 verify=False,關閉 requests 的憑證檢查功能:

# 關閉憑證檢查 import warnings  from requests.packages.urllib3.exceptions import InsecureRequestWarning  warnings.simplefilter('ignore',InsecureRequestWarning) r = requests.get('https://my.server.com/', verify = False)

參考資料:

requests 使用方法:
https://requests.readthedocs.io/en/master/

>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
u'{"type":"User"...'
>>> r.json()
{u'private_gists': 419, u'total_private_repos': 77, ...}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *