【Python 網路爬蟲筆記】Requests Library - part 2 === 目錄(Table of Contents): [TOC] --- 感謝你點進本篇文章!!我是 LukeTseng,一個熱愛資訊的無名創作者,由於近期大學開設大數據分析程式設計這門課程,裡面談到了爬蟲概念,讓我激起一些興趣,因而製作本系列筆記。 聲明:本篇筆記僅供個人學習用途,斟酌參考。 另外本篇筆記使用 VSCode 環境進行編寫,部分模組(函式庫)需自行下載。 ## 安裝 Requests 函式庫 Colab 及 Anaconda 環境無須安裝,內建即有。 若不確定自己有裝的話,可以輸入 `pip list` 查看已安裝的所有模組。 使用指令 `pip install requests`。 ![pip_list](https://hackmd.io/_uploads/HyBt063oxg.png) 像我已經安裝過了,再安裝一次他會跟你說 Requirement already satisfied,表示你裝過了。 ![pip_install_requests](https://hackmd.io/_uploads/B1A9RThjxg.png) 另外一個測試有沒有安裝過該模組的方法,可以打開 VSCode 或其他環境,輸入以下指令並執行即可: ```python= import requests print(requests.__version__) ``` 執行後會在最下面出現版本資訊。 ![vscode_example](https://hackmd.io/_uploads/BJGAJA3jgg.png) ## Requests 基礎用法 使用前須引入模組 `import requests`。 打 `from requests import *` 之後就免在 method 前面打上繁瑣的 requests。 先來看個表: | Methods | 敘述 | | -------- | -------- | | get(url, params, args) | 向指定 URL 發送 GET 請求 | | post(url, data, json, args) | 向指定 URL 發送 POST 請求 | | put(url, data, args) | 向指定 URL 發送 PUT 請求(將新資料取代目標資源) | | delete(url, args) | 向指定 URL 發送 DELETE 請求 | | head(url, args) | 向指定 URL 發送 HEAD 請求(僅取得 Headers 資訊,沒有 Body) | | patch(url, data, args) | 向指定 URL 發送 PATCH 請求 | | request(method, url, args) | 向指定 URL 發送指定方法的請求 | > table from W3Schools:https://www.w3schools.com/python/module_requests.asp 我們先從最簡單的 get 請求開始做起,範例網址:https://luketsengtw.github.io/ ```python= import requests url = 'https://luketsengtw.github.io/' response = requests.get(url) print(response) ``` Output: ``` <Response [200]> ``` 最後輸出了 `<Response [200]>`,這個 200 是 Status Code,表示網站運作正常的意思。 那我們可以在後綴加上 `.text` 看看輸出的內容會是怎樣: ```python= import requests url = 'https://luketsengtw.github.io/' response = requests.get(url) print(response.text) # modify ``` Output: ![image](https://hackmd.io/_uploads/SyAckxpixl.png) 答案就是一長串,超級多的 HTML 內碼 XD。然後我們就成功爬取到這個網站的 HTML 資訊了。 像剛剛的 Status Code 也可以寫成方法單獨輸出(`.status_code`): ```python= import requests url = 'https://luketsengtw.github.io/' response = requests.get(url) print(response.status_code) ``` Output: ``` 200 ``` 既然講到了 `.status_code` 以及 `.text`,那我們就列個完整表給這些 Response 方法吧: | Methods | 敘述 | | -------- | -------- | | .headers | 回傳 response headers 的字典 | | .encoding | 回傳用於解碼 response.content 的編碼 | | .elapsed | 回傳一個 timedelta 物件,其中包含從發送請求到回應到達所經過的時間 | | .close() | 關閉與伺服器的連線 | | .content | 以位元組(bytes)為單位回傳回應的內容 | | .cookies | 回傳一個 CookieJar 物件,其中包含從伺服器發回的 cookie | | .history | 回傳儲存請求(URL)歷史記錄的回應物件列表 | | .is_permanent_redirect | 如果回應是永久重新導向的 url,則回傳 True,否則回傳 False | | .is_redirect | 如果回應被重新導向,則回傳 True,否則回傳 False | | .json() | 回傳結果的 JSON 物件(如果結果是以 JSON 格式寫入的,如果不是則會引發錯誤) | | .url | 回傳回應的 URL | | .text | 以 unicode 格式回傳回應的內容 | | .request | 回傳請求此回應的請求物件 | | .reason | 回傳與 status code 對應的文字 | | .ok | 如果 status code < 400 且 >= 200,則回傳 True;否則,回傳 False | | .links | 回傳 headers 連結 | > table from GeeksForGeeks:https://www.geeksforgeeks.org/python/python-requests-tutorial/ ### POST 發送 POST 請求方法類似於新增、更新操作,會隱密傳送資料給指定的資源。 註:`https://httpbin.org/post` 這個網址是用於測試用的。 ```python= import requests # 發送基本 POST 請求 response = requests.post('https://httpbin.org/post', data={'key': 'value'}) print(f"狀態碼: {response.status_code}") print(f"響應內容: {response.text}") ``` Output: ``` 狀態碼: 200 響應內容: { "args": {}, "data": "", "files": {}, "form": { "key": "value" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, zstd", "Content-Length": "9", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.32.5", "X-Amzn-Trace-Id": "Root=1-68cf7a42-667a646642bff88525ef3450" }, "json": null, "origin": "180.176.79.173", "url": "https://httpbin.org/post" } ``` 上述方式帶了一個參數 `data={'key' : 'value'}`,用 POST 請求方法發送給 `https://httpbin.org/post` 這個網址。 從響應內容中可以看到有我們剛剛輸入的參數: ``` "form": { "key": "value" }, ``` POST 提交表單: ```python= import requests # 表單資料 form_data = { 'username': 'XXX', 'password': 'thisismypassword', 'email': 'xxx@example.com' } # 發送表單資料 response = requests.post('https://httpbin.org/post', data=form_data) # 檢查結果 if response.status_code == 200: print("表單提交成功!") print(response.text) else: print(f"請求失敗,狀態碼: {response.status_code}") ``` Output: ``` 表單提交成功! { "args": {}, "data": "", "files": {}, "form": { "email": "xxx@example.com", "password": "thisismypassword", "username": "XXX" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, zstd", "Content-Length": "62", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.32.5", "X-Amzn-Trace-Id": "Root=1-68cf7be7-1dc37d90043a6d9606ce14bc" }, "json": null, "origin": "180.176.79.173", "url": "https://httpbin.org/post" } ``` ### 避免亂碼 透過網站的標籤 `<meta charset="UTF-8">` 可以得知是使用何種編碼,這邊以我的個人網站做測試:https://luketsengtw.github.io/ 如果亂碼可以先透過檢查工具查看是使用何種編碼,並使用方法 `.encoding` 去換編碼。 範例: ```python= import requests response = requests.get('https://luketsengtw.github.io/') response.encoding = 'utf-8' # modify print(response.text) ``` ## API 爬取開放式資料 (政府資料開放平台)以下範例使用「YouBike2.0臺北市公共自行車即時資訊」進行爬取:https://data.gov.tw/dataset/137993 JSON 連結:https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json ```python= import requests response = requests.get('https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json') print(response.json()) ``` Output: ![image](https://hackmd.io/_uploads/B1ob2MTsle.png) ## HTTP 狀態碼 以下列了幾種常見的 HTTP 狀態碼(status code): | status code | 敘述 | | -------- | -------- | | 200 | OK / 網頁狀態正常(OK / Success) | | 301 | 永久重新導向(網頁搬家)(Permanent Redirect) | | 302 | 暫時性重新導向(Temporary Redirect) | | 400 | 錯誤請求(Bad Request) | | 401 | 未授權(Unauthorized Error) | | 403 | 沒有權限進入(Forbidden) | | 404 | 找不到網站(Not Found) | | 500 | 內部伺服器錯誤(Internal Server Error) | | 504 | 伺服器沒有回應(Gateway Timeout) | 詳細請見:https://zh.wikipedia.org/zh-tw/HTTP%E7%8A%B6%E6%80%81%E7%A0%81 範例: ```python= import requests response = requests.get('https://httpbin.org/get') statusCode = response.status_code print(f'Status Code : {statusCode}') if statusCode == 200: print('Success to request') print(f'Content : {response.text[:100]}...') elif statusCode == 404: print('Not Found') elif statusCode >= 500: print('Server Error') ``` Output: ``` Status Code : 200 Success to request Content : { "args": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, zstd", ... ``` ## 總結 ### HTTP 請求方法 - GET: - GET 是最常用的 HTTP 方法,用於從伺服器獲取資料。 - 基本語法:`requests.get(url)`,回傳的 Response 物件包含**狀態碼**和**內容**。 - 如:請求網頁時會得到 `<Response [200]>`,其中 200 表示請求成功。 - POST: - POST 方法用於向伺服器傳送資料,常用於**表單提交**或 **API 呼叫**。 - 可用 **data** 參數傳送表單資料,或 json 參數傳送 JSON 格式資料。 - POST 請求會將資料隱密地傳送給指定資源,適合用於新增或更新操作。 ### Response 物件屬性及方法 | Methods | 敘述 | | -------- | -------- | | .headers | 回傳 response headers 的字典 | | .encoding | 回傳用於解碼 response.content 的編碼 | | .elapsed | 回傳一個 timedelta 物件,其中包含從發送請求到回應到達所經過的時間 | | .close() | 關閉與伺服器的連線 | | .content | 以位元組(bytes)為單位回傳回應的內容 | | .cookies | 回傳一個 CookieJar 物件,其中包含從伺服器發回的 cookie | | .history | 回傳儲存請求(URL)歷史記錄的回應物件列表 | | .is_permanent_redirect | 如果回應是永久重新導向的 url,則回傳 True,否則回傳 False | | .is_redirect | 如果回應被重新導向,則回傳 True,否則回傳 False | | .json() | 回傳結果的 JSON 物件(如果結果是以 JSON 格式寫入的,如果不是則會引發錯誤) | | .url | 回傳回應的 URL | | .text | 以 unicode 格式回傳回應的內容 | | .request | 回傳請求此回應的請求物件 | | .reason | 回傳與 status code 對應的文字 | | .ok | 如果 status code < 400 且 >= 200,則回傳 True;否則,回傳 False | | .links | 回傳 headers 連結 | ### 編碼處理 網頁爬取時常遇到編碼問題(可能出現亂碼),可透過檢查網頁 HTML 的 `<meta charset>` 標籤確認編碼格式。 使用 `response.encoding = 'utf-8'` 可手動設定編碼,避免中文亂碼問題。 ### API 資料爬取 Requests 非常適合爬取開放式 API 資料。 以政府資料開放平台為例,其可直接請求 JSON API 端點,使用 `response.json()` 方法將回應轉換為 Python 字典格式,便於後續資料處理和分析。 ### HTTP 狀態碼 HTTP 狀態碼(Status Code)為三位數字,用於指示請求(Requests)結果,常見的如下: | status code | 敘述 | | -------- | -------- | | 200 | OK / 網頁狀態正常(OK / Success) | | 301 | 永久重新導向(網頁搬家)(Permanent Redirect) | | 302 | 暫時性重新導向(Temporary Redirect) | | 400 | 錯誤請求(Bad Request) | | 401 | 未授權(Unauthorized Error) | | 403 | 沒有權限進入(Forbidden) | | 404 | 找不到網站(Not Found) | | 500 | 內部伺服器錯誤(Internal Server Error) | | 504 | 伺服器沒有回應(Gateway Timeout) | ## Reference [Requests 函式庫 - Python 網路爬蟲教學 | STEAM 教育學習網](https://steam.oxxostudio.tw/category/python/spider/requests.html) [Python Requests post Method](https://www.w3schools.com/python/ref_requests_post.asp) [response.status_code - Python requests - GeeksforGeeks](https://www.geeksforgeeks.org/python/response-status_code-python-requests/) [Python Requests - GeeksforGeeks](https://www.geeksforgeeks.org/python/python-requests-tutorial/) [Python Requests Module](https://www.w3schools.com/python/module_requests.asp) [Requests: HTTP for Humans™ — Requests 2.32.5 documentation](https://requests.readthedocs.io/en/latest/)