【Python 網路爬蟲筆記】Requests Library - part 2
===
目錄(Table of Contents):
[TOC]
---
感謝你點進本篇文章!!我是 LukeTseng,一個熱愛資訊的無名創作者,由於近期大學開設大數據分析程式設計這門課程,裡面談到了爬蟲概念,讓我激起一些興趣,因而製作本系列筆記。
聲明:本篇筆記僅供個人學習用途,斟酌參考。
另外本篇筆記使用 VSCode 環境進行編寫,部分模組(函式庫)需自行下載。
## 安裝 Requests 函式庫
Colab 及 Anaconda 環境無須安裝,內建即有。
若不確定自己有裝的話,可以輸入 `pip list` 查看已安裝的所有模組。
使用指令 `pip install requests`。

像我已經安裝過了,再安裝一次他會跟你說 Requirement already satisfied,表示你裝過了。

另外一個測試有沒有安裝過該模組的方法,可以打開 VSCode 或其他環境,輸入以下指令並執行即可:
```python=
import requests
print(requests.__version__)
```
執行後會在最下面出現版本資訊。

## 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:

答案就是一長串,超級多的 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:

## 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/)