跳至主要内容

6 篇文章 含有標籤「python」

檢視所有標籤

· 閱讀時間約 2 分鐘
Willis Chen

image

介紹

在這篇文章中,我們將探討如何使用 GitHub Codespace 快速有效地建立和部署 LINE Bot。GitHub Codespace 提供了一個雲端開發環境,使得開發人員可以在任何地方進行開發和部署。這種方式的好處是不需要本地環境配置,且環境變數的設置增加了項目的安全性。

步驟一:設置 GitHub Codespace

首先,你需要在 GitHub 上啟用 Codespace 並克隆你的專案。

  1. 登入你的 GitHub 帳號。
  2. 找到你的專案倉庫,點擊 "Code" 按鈕,選擇 "Open with Codespaces"。
  3. 選擇 "New codespace" 來建立一個新的開發環境。 image

步驟二:設置環境變數

在 Codespace 中設置你的 LINE Bot 的環境變數:

  1. 創建一個 .env 檔案。

  2. 加入以下環境變數:

    LINE_CHANNEL_SECRET=你的channel_secret
    LINE_CHANNEL_ACCESS_TOKEN=你的access_token
  3. 在這個示範專案,可以將MediaSystem-Python-Course\06.Line-bot-fly-flask\config-templete.py另存為config.py,也就是環境變數儲存在config.py的檔案裡,這是一個簡易用法不建議正式使用,使用環境變數對機密資訊才有較佳的保護。

步驟三:安裝依賴

在 Codespace 的終端機運行以下命令安裝所需依賴:

pip install -r requirements.txt

步驟四:編輯程式碼

使用 GitHub Copilot 來協助編寫和優化程式碼。例如,以下是一個簡單的 Flask 應用來回應 LINE Bot 的訊息:

from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage

app = Flask(__name__)

line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')

@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
line_bot_api.reply_message(
event.reply_token, TextSendMessage(text=event.message.text))

if __name__ == "__main__":
app.run()`

步驟五:測試與部署

啟動你的 Flask 應用並進行測試。你不需要使用 ngrok 來建立 TLS 認證。

  1. 在 Codespace 的終端機運行你的 Flask 應用。
  2. 使用 LINE Bot 進行測試,確保一切運行正常。

結語

使用 GitHub Codespace 來建立和部署 LINE Bot 是一個高效且安全的方法。這種方式不僅節省了設置本地開發環境的時間,還提供了一個穩定和安全的開發平台。希望這篇文章能夠幫助你順利完成 LINE Bot 的開發和部署。

· 閱讀時間約 9 分鐘
Willis Chen

老師們現在不僅對教學充滿熱情,也愈來愈善於運用科技工具,如LINE官方帳號,來與學生和家長保持緊密的溝通。這些努力無疑是朝著以下兩大目標邁進:

  1. 激發學生的好奇心:鼓勵學生主動提問,並引導他們思考解決問題的方法。
  2. 個別化教學:深入了解每位學生的學習進度和思維方式,以因材施教。

🤖 專案介紹

這個專案的核心目的是要讓老師們能在已有的LINE官方帳號上,快速加入一個AI助教—使用ChatGPT技術。這樣一來,AI助教能夠第一時間回應學生的問題,如果遇到AI不能解決的問題,它還會建議學生直接聯繫老師。這讓老師有更多的時間和空間來專注於其他重要的教學任務。

🛠️ 如何開始?

這個專案極力降低相關的技術門檻。實際上,在幾乎不需要寫任何程式碼的情況下,老師就能設置起這個AI助教服務。你只需完成以下幾個簡單的步驟:

  1. 註冊本服務
  2. 在LINE官方帳號後台進行相應設定
  3. 啟用ChatGPT作為你的AI助教

完成以上步驟後,你就能讓ChatGPT開始擔任你的AI助教,預先回答學生的問題。

👉 歡迎各位老師運用,打造更智慧、更高效、教學相長的教學環境!

📚 在開始之前,你需要了解的

在你開始使用這個專案之前,有一些基礎的技術和費用信息你需要知道。

技術環境

  • 涉及的技術和環境如下:
    • 程式語言: Python
    • 伺服器後端框架: Flask
    • FaaS雲端服務: Vercel
    • AI對話功能: OpenAI API (ChatGPT-3.5-tubo)
    • 聊天環境: LINE (LINE Message API)

花費預估

  • Vercel

    • Hobby方案允許你免費建立最多3個專案。
    • 注意:如果伺服器處理時間超過10秒,將會被判定為Time Out。
    • Vercel 費用詳情
  • OpenAI API

    • 初次註冊有免費額度,API使用需綁信用卡。
    • 本專案預設使用的是2023/11釋出的 GPT-4-1106-preview
    • OpenAI 費用詳情
    • OpenAI Cost
  • LINE 主動訊息

    • 額度內免費,目前是200則訊息(2023/9月前為500則)。
    • 由使用者提問的回覆(Reply)免費。
    • 老師主動發送的訊息(Push)有200則限制。
    • LINE 費用詳情
    • LINE Cost1
    • LINE Cost2

    提醒您: 所有的費用和限制可能會隨著各個服務供應商的政策改變而變動,建議定期查看官方網站以獲取最新資訊。

如何建立自己的 LINE AI助教?

這份指南將引領您從LINE 官方帳號開始,不同於開發者通常從 LINE Developers 開始。不過,不管從哪裡出發,最終目標相同:建立一個集成 ChatGPT 的 LINE 官方帳號。

🌟 步驟1:初始化 LINE 官方帳號 🌟

首先,我們需要建立一個基本的、無AI功能的 LINE 官方帳號。學生們可以即刻加入這個帳號。這個帳號初期僅支持手動聊天,AI 功能將在後續逐步加入。

  1. 前往 LINE 官方帳號管理頁面

  2. 填寫必要資訊:這些資訊也會是學生看到的名稱。

  3. 選擇「稍後認證官方帳號」:這個認證過程不會影響本專案。

  4. (選擇性)建立圖文選單:利用圖文選單可提供班級公告、相片集等。

    • 主頁 > 圖文選單 > 參考說明
  5. 啟用 Webhook 🔗

    • Webhook 是一個可用程式處理訊息的通道。
    • 通過 Webhook,我們將使用 Vercel 平台、Python Flask 框架和 OpenAI API。

🌟 步驟2:註冊必要的平台並獲取 API Token

  1. 註冊必要平台:包括 GitHubVercelOpenAI APILINE Developers
  2. 獲取 OpenAI API Token:保存好這個 Token,它是一次性的。

🌟 步驟3:設置 LINE Developer Channel 及獲取 Secret, Token 🌟

3.1 獲取 Channel Secret 🔒

  • 從 LINE 官方帳號或 LINE Developer Channel 都可獲取。

3.2 獲取 Channel Access Token 🔑

  • 在 LINE Developer Channel 下生成。

🌟 步驟4:Fork GitHub 專案 🌟

  • Fork 這個專案至您自己的 GitHub 儲存庫。

🌟 步驟5:部署至 Vercel 🌟

  1. 建立 Vercel 專案
  2. 連接 GitHub 和選擇專案
  3. 設定環境變數並部署
  • 您需要設定的環境變數為OPENAI_API_KEYLINE_CHANNEL_ACCESS_TOKENLINE_CHANNEL_SECRET,在這裡的環境變數能受到較佳的保護,至少比放在程式碼裡安全許多。

  1. 修正支援的Nodejs版本
  • 如果遇到Python安裝版本問題,依據官方文件,Vercel預設的Node.js版本為20.x,不支援Python,請在專案的設定>一般的選項裡,將Node.js改選為18.x版本。 image

  • 修改後請選擇部署,或到專案的佈署歷程中選擇再次部署,就會改用Node.js 18.x版再跑一次。 image

🎉 完成! 🎉

恭喜您,現在您已經成功建立了自己的 AI 助教!現在可以透過 LINE 官方帳號進行測試。

🔧 進階設定:打造個性化的AI助手

  • 若要讓AI助手更符合你的需求和風格,OpenAI API提供了一個彈性的方式讓你自行設定AI的角色。具體來說,你只需要在對話設定中添加 messages: [{ role: "system", content: "你的AI助手人設" }] 即可。
  • 進行這項設定只需前往api/prompt.py並在AI_GUIDELINES後修改提示文字即可。不過,因為Vercel的免費版有10秒的運行時限制,過長的提示可能會導致Time Out,因此建議不要設置過於複雜的指引。
  • 本專案經過精心測試後,已經內建一組最佳實踐的AI_GUIDELINES,但你也可以隨心所欲地進行調整:
    AI_GUIDELINES = '你是一個AI助教,專門使用蘇格拉底教學法來回答學生的問題,如果有需要,會建議學生與老師進一步確認。'
  • 修改方式也非常簡單,只需登入你的GitHub帳號,找到該專案的api/prompt.py文件,點擊右側的鋼筆圖示✏️即可進行線上編輯。 編輯
  • 完成後,選擇“Commit Changes”並填入適當的描述。 提交更改 描述

🚀 專案成果

  • 出色的問答回應: 這個AI助手自2023年11月7日OpenAI大幅降低費率後,採用GPT 4模型,更能通順的、即時地回應學生的問題。 出色回應

  • 問題過濾: 對於需要更深層次討論的問題,AI助手會提供適當的處理建議,協助老師過濾和分類問題,同時也啟發老師改進教學。 問題過濾

  • 引導學生思考: 透過蘇格拉底教學法,AI助手不僅回答問題,還能引導學生學會如何提問和解決問題。

    同學A 老師我想要問BMI的python程式怎麼寫
    ----
    AI助教 嗨!關於BMI的Python程式,我可以幫你一起思考。首先,你知道BMI是什麼嗎?
    ----
    同學A BMI=體重/身高平方
    ----
    AI助教 沒錯!BMI是體重除以身高的平方。那麼,你想要寫一個計算BMI的Python程式對吧?你已經有身高和體重的數值了嗎?
    ----
    同學A 70/(1.73**2)
    ----
    AI助教 沒錯!你可以使用這個公式來計算BMI。現在我們可以開始寫一個Python程式來計算BMI。你想要將身高和體重作為變數輸入嗎?
    ----
    同學A 想
    ----
    AI助教 好的!我們可以寫一個簡單的Python函數來計算BMI。以下是一個範例程式碼:

    ```python
    def calculate_bmi(weight, height):
    bmi = weight / (height ** 2)
    return bmi

    weight = float(input("請輸入您的體重(公斤):"))
    height = float(input("請輸入您的身高(公尺):"))

    bmi = calculate_bmi(weight, height)
    print("您的BMI為:", bmi)
    ```

    這個程式會要求使用者輸入體重和身高,然後使用`calculate_bmi`函數計算BMI並輸出結果。請注意,身高的單位應該是公尺,體重的單位應該是公斤。
    ----
    同學A 請幫我也寫出測試碼,之後會用pytest測試
    ----
    AI助教 當然!我們可以寫一些測試碼來驗證我們的BMI計算函數是否正確。以下是一個範例的測試碼:

    ```python
    import pytest

    def calculate_bmi(weight, height):
    bmi = weight / (height ** 2)
    return bmi

    def test_calculate_bmi():
    assert calculate_bmi(70, 1.73) == pytest.approx(23.39, 0.01)
    assert calculate_bmi(80, 1.65) == pytest.approx(29.38, 0.01)
    assert calculate_bmi(60, 1.80) == pytest.approx(18.52, 0.01)

    if __name__ == "__main__":
    pytest.main()
    ```

    這個測試碼使用了pytest套件來執行測試。我們定義了一個`test_calculate_bmi`函數,其中包含了幾個斷言語句,用來驗證`calculate_bmi`函數的輸出是否符合預期。每個斷言語句都使用了`pytest.approx`函數來比較浮點數的近似值,並指定了一個容忍誤差範圍。

    你可以將這個測試碼保存為一個.py檔案,然後使用pytest運行測試。如果所有的測試通過,則表示你的BMI計算函數正確無誤。
    ----
    同學A 謝謝老師,我的超人
    ----
    AI助教 不客氣!如果你有任何其他問題,隨時都可以問我。祝你一切順利!

    培養思考 成果展示 更多示例

專案成果

  1. 出色的回應學生問題: 這個功能不僅可以即時解答學生的問題,還可以減輕老師的負擔。
  2. 過濾問題: 能過濾並指導學生如何更有效地提問,是一個對教師非常有幫助的功能。
  3. 引導學生思考: 這是最讓人印象深刻的部分,因為不僅解答了問題,還教會了學生如何解決問題。

這個專案不僅具有高度的實用性,也很有教育意義。它不只是一個問答工具,更是一個能夠協助教學和學習的平台。

參考資料

· 閱讀時間約 4 分鐘
Willis Chen

🐍 Python 是一種非常流行和強大的程式語言,它有許多優秀的套件可以幫助我們完成各種任務,例如資料分析、機器學習、網頁開發等。然而,如果我們同時在不同的專案中使用 Python,我們可能會遇到一些問題,例如:

  • 不同的專案可能需要不同的 Python 版本或套件版本,這可能會造成版本衝突和相依性問題。
  • 如果我們在全域環境中安裝或移除套件,可能會影響其他專案的運作。
  • 如果我們想要部署或分享我們的專案,我們需要記錄和安裝所有需要的套件和版本,這可能會很麻煩和耗時。

為了解決這些問題,我們可以使用虛擬環境管理工具來創建和管理不同的 Python 環境。虛擬環境是一個隔離的 Python 環境,它可以讓我們在不同的專案中使用不同的 Python 版本和套件,而不會互相干擾。這樣,我們就可以更方便和安全地開發和部署我們的 Python 專案。

目前,有許多虛擬環境管理工具可以選擇,例如 virtualenv, conda, pyenv 等。在這篇文章中,我將重點介紹 pipenv 和 venv 這兩種工具,並且比較它們的優缺點。

pipenv

  • pipenv 是目前 Python 官方推薦的套件管理工具,它集成了 pipvirtualenv 的功能,並且改進了它們的一些缺陷 。
  • pip 使用 PipfilePipfile.lock 來記錄套件的資訊,而不是使用 requirements.txt。
    • Pipfile.lock 包含了套件的Hash值,可以確保安裝的套件是一致和安全的 。
    • pipenv 可以自動產生和更新 PipfilePipfile.lock,不需要手動維護 。
  • 可以區分開發和生產環境的套件,只需要在安裝時加上 --dev 參數即可 。
  • 可並行(parallel)同步安裝套件,提升安裝速度。
  • pipenv 可以透過 .env 自動載入不同環境變數。
  • pipenv 的指令比較簡單和直觀,例如
    • pipenv install 如同 pip install
    • pipenv uninstall
    • pipenv shell 如同 source venv/bin/activate 進入虛擬環。
    • pipenv run 可以執行虛擬環境內容

venv

  • venv 是 Python 3.3 之後內建的虛擬環境模組,它可以創建一個隔離的 Python 環境,但是不包含任何套件管理功能。
  • venv 使用 python -m venv {虛擬機命名} 來創建虛擬環境,然後使用 source venv/bin/activate 來啟動虛擬環境(Windows 以 venv/Scripts/activate 進入)。
  • venv 需要配合 piprequirements.txt 來管理套件,因為venv跟pip是兩回事,這可能會造成版本衝突和相依性問題。

比較 pipenv 和 venv 差異

以下用表格比較 pipenv 和 venv 的差異,我用表格的方式來比較它們的特點:

特點pipenvvenv
Python 官方推薦曾經是
集成 pip 和 virtualenv
使用 Pipfile 和 Pipfile.lock
自動產生和更新 Pipfile 和 Pipfile.lock
包含套件的哈希值
區分開發和生產環境的套件
使用並行同步安裝套件
自動載入不同環境變數
指令簡單和直觀

從表格中,我們可以看出 pipenv 是一個更先進和完善的虛擬環境管理工具,它可以讓我們更方便和安全地開發 Python 專案。如果你想了解更多關於 pipenv 的資訊,但在基礎Python教學時,我更傾向以venv為主,因為你看到的網路專案大多還是venv + pip install -r requirements.txt 來示範的。可以參考以下的連結:

感謝你閱讀這篇文章,如果你有任何問題或建議,歡迎在下方留言。Enjoy Python。再見!

· 閱讀時間約 2 分鐘
Willis Chen

如果你對如何將 LINE 聊天機器人與 HackMD 結合有興趣,這篇文章正是你需要的。這次,我們將使用 Render 這個雲端平台來部署我們的應用。

前置作業:準備你的 GitHub 倉庫

  1. Fork 專案:首先,請到這個 GitHub Repo 進行 fork,這樣你就有了一個屬於自己的副本。

    Fork Repo

Render 設定

登入和選擇服務

  1. 登入 Render:前往 Render 的網站 並用 GitHub 帳號登入。

    登入 Render

  2. 選擇 Web 服務:在 Render 的 dashboard,選擇 "Web Service"。

    選擇 Web Service

設定部署參數

  1. 基本設定:填入應用的名稱和其他基本資訊。在這裡,我們選擇免費的方案。如果你的主程式檔名不是 app.py,記得修改 gunicorn 的指令。

    基本設定 更多設定

  2. 設定環境變數:在 .env 檔案中填入所有需要的環境變數。

    環境變數設定

  3. 等待部署完成:設定完成後,Render 會自動進行部署。

    部署狀態

需要的 API 金鑰和資訊

HackMD API

  • 請參考 HackMD 的官方文件以獲得 API 金鑰。

OpenAI API

  1. 訪問 OpenAI API 官網

  2. 生成一個一次性的 API 金鑰。注意:一旦關閉視窗,這個金鑰將不再顯示。

    OpenAI API API 金鑰

LINE Message API 和 Imgur API

  • 請依照各自平台的文件申請 API 金鑰。

環境變數在 Python 中的使用

你可以使用以下程式碼來讀取環境變數。

import os
api_key = os.environ.get('KEY')`

配置 LINE Webhook

最後,回到 LINE Channel 設定中加入 webhook。

LINE Webhook

這樣你就完成了整個部署過程!如果你有任何問題或建議,歡迎在下方留言。祝學習愉快!

· 閱讀時間約 3 分鐘
Willis Chen
  • Selenium 是一個自動化測試框架,專門用於測試 Web 應用程式。作為一位經常需要隨著套件更新來調整教學內容的講師。將針對最近升級至 4.x 版本的 Selenium 進行比較,以及如何解決版本更新的程式碼問題。

預期 Selenium 版本更新會遇到的狀況

在過去,我預期會遇到以下幾種情況:

  • 需要更新至新版的 webdriver。
  • 程式參數更新,需要查看 log 以解決問題。

然而,升級至 Selenium 4.x 後,我發現了一些令人驚喜的改變。

1. webdriver管理更聰明了

舊版流程

在 Selenium 4.x 版本之前,安裝 Selenium 是一件相對繁瑣的事情。你需要:

  1. pip install 安裝 Selenium 主要套件。
    pip install selenium
  2. 然後,你還需要手動下載與你的 Chrome 版本相對應的 WebDriver。
  3. 解壓縮 WebDriver,然後將其放入指定目錄。

過渡版本- 需額外的 webdriver_manager

  • 在2023年之前的一段時間簡化了上述流程,透過pip install webdriver_manager直接安裝好對應的測試瀏覽器,不用找對應的瀏覽器與版本,但需要引入webdriver_manager套件。

    pip install webdriver_manager
  • 然後,使用webdriver_manager的範例如下:

    from selenium import webdriver
    from webdriver_manager.chrome import ChromeDriverManager

    options = webdriver.ChromeOptions()
    # options.add_argument('--headless')

    wd = webdriver.Chrome(ChromeDriverManager().install(), options=options)
    wd.get("https://www.google.com")
    wd.save_screenshot("google_homepage.png")
    wd.quit()

新版流程

  • 現在,在 Selenium 4.x 版本,你只需執行一個指令即可:

    pip install selenium
  • 這個改變意味著,你不再需要手動去管理 WebDriver,Selenium 會為你處理一切。

2. selenium.webdriver.Chrome()`參數簡化

舊版用法

  • 在舊版中,初始化 Chrome WebDriver 的代碼通常會看起來像這樣:

    from selenium import webdriver

    options = webdriver.ChromeOptions()
    options.add_argument('--headless')

    wd = webdriver.Chrome('path/to/chromedriver', chrome_options=options)

新版用法

  • 在新版中,由於 WebDriver 已經被整合,你可以簡單地這樣做:

    from selenium import webdriver

    options = webdriver.ChromeOptions()
    options.add_argument('--headless')

    wd = webdriver.Chrome(options=options)

Selenium 搜尋 PTT 指定列表範例

如你所見,新版省去了指定 chromedriver 路徑的需求,使得代碼更為簡潔,最後分享一個這學期調整的selenium範例:

from selenium import webdriver
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup


def make_webdriver() -> Chrome:
options = create_options()
driver = Chrome(options=options) #簡化參數
return driver


def create_options() -> Options:
options = Options()
options.add_argument("--headless")
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument("--start-maximized")
return options


def get_ptt_board_list(board) -> list:
url = f"https://www.ptt.cc/bbs/{board}/index.html"
wd = make_webdriver()
wd.get(url=url)
soup = BeautifulSoup(wd.page_source,"html.parser")
links = soup.select('div.title > a')
res = [{
'title': link.get_text(),
'href': f'https://www.ptt.cc{link.get("href")}'
} for link in links if '公告' not in link.get_text() ]
wd.quit()
return res

if __name__ == '__main__':
res = get_ptt_board_list('movie')
print(res)

小結

Selenium 4.x 版本帶來了許多便利性的提升,尤其是在 WebDriver 管理和參數簡化方面。這對於減少教學備課的負擔以及提高自動化測試的效率都有很大的幫助。

我個人非常推薦升級至這個版本,以便能夠利用這些新的特性和優化。

· 閱讀時間約 5 分鐘
Willis Chen

在這篇文章中,將探討如何使用Python的PlayWright模組來抓取巴哈姆特動漫瘋的彈幕數據。 目標如下:

  • 認識PlayWright
  • 如何安裝PlayWright。
  • 如何利用PlayWright控制網頁行為。
  • 如何改寫腳本,抓取、整理和儲存需要的數據。

什麼是PlayWright?

PlayWright 是Microsoft推出的開源專案,是一個Python用戶端,讓我們能夠自動化Web瀏覽器的行為,包括Chrome, Firefox, 和Safari等主流瀏覽器。你可以使用它來進行網站測試、抓取資料,甚至製作自動化的網頁腳本。透過PlayWright,你能控制整個瀏覽過程,包括產生彈幕等動態內容。

如何安裝PlayWright

安裝PlayWright相當簡單,只需要在你的命令列工具 (例如:終端機或Command Prompt) 輸入以下命令即可:

> pip install playwright

如何利用PlayWright控制網頁行為

首先,我們需要啟動一個PlayWright的實例,並且以我們選定的瀏覽器來執行我們的程式。以下是一個以Chromium瀏覽器為例的程式碼,同理也可以使用webkit瀏覽器:

> python -m playwright codegen -b chromium

執行上述命令後,您將開啟一個Chromium瀏覽器並開始與其互動。你的每一個操作,都會自動生成對應的Python程式碼。

codegen命令包含一些可用的參數,例如:

  • --target: 設定你的程式語言,如 python、JavaScript等。
  • -o: 指定存放生成程式碼的檔案名稱。
  • -b: 選擇你想要使用的瀏覽器,如 chromium、firefox或webkit。

以下是一個實際的例子,使用webkit瀏覽器抓取巴哈姆特動漫瘋網站並將程式碼儲存在damun.py文件中:

> python -m playwright codegen --target python -o damun.py -b webkit https://ani.gamer.com.tw/

此時的damun.py內容參考如下:


from playwright.sync_api import Playwright, sync_playwright
from bs4 import BeautifulSoup
import json
import sys
import time


def run(playwright: Playwright, sn) -> None:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()

page.goto(f"https://ani.gamer.com.tw/animeVideo.php?sn={sn}")
time.sleep(5)

# screenshot
page.screenshot(path='ani.jpg', full_page = True)

### 稍後加上網頁解析
### 稍後加上內容萃取
### 稍後加上資料儲存

page.close()

# ---------------------
context.close()
browser.close()


with sync_playwright() as playwright:
run(playwright, sys.argv[1])

修改PlayWright腳本

為了包含抓取後的解析及整理,可以在前面透過點選產製的damun.py腳本中,新增解析的程式

  • 網頁解析: page內容為HTML,將其轉換成BeautifulSoup物件,方便後續操作。

    from bs4 import BeautifulSoup

    soup = BeautifulSoup(page.content(), 'lxml')
  • 內容萃取: 這邊藏的一個很關鍵的做法,用For迴圈直接將結果設計為JSON like的Python Dictionary格式。

    • 每次回圈的過程一次性的將擷取對象整理好。
      # for-loops
      res = []
      k = {}
      for li in soup.select('.sub-list-li'):
      k['userid'] = li.select_one('.name > span').text.strip()
      k['text'] = li.select_one('.sub_content').text.strip()
      k['msg_time'] = li.select_one('b').text.strip()
      print(k)
      res.append(k)
    • 如果你熟悉列表推導式(list comprehension),以下改寫更為直觀:
          res = [ {
      'userid': li.select_one('.name > span').text.strip(),
      'text' : li.select_one('.sub_content').text.strip(),
      'msg_time' : li.select_one('b').text.strip()
      } for li in soup.select('.sub-list-li')]
  • 資料儲存: 將Dict樣式存成JSON格式,方便後續運用。

    import json

    with open(f'damun_{sn}.json', 'w') as f:
    json.dump(res, f)
  • 最終的damun.py腳本內容:


from playwright.sync_api import Playwright, sync_playwright
from bs4 import BeautifulSoup
import json
import sys
import time


def run(playwright: Playwright, sn) -> None:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()

page.goto(f"https://ani.gamer.com.tw/animeVideo.php?sn={sn}")
time.sleep(5)

# screenshot
page.screenshot(path='ani.jpg', full_page = True)

# 網頁解析
soup = BeautifulSoup(page.content(), 'lxml')

# 內容萃取(列表推導式)
res = [ {
'userid': li.select_one('.name > span').text.strip(),
'text' : li.select_one('.sub_content').text.strip(),
'msg_time' : li.select_one('b').text.strip()
} for li in soup.select('.sub-list-li')]

print(res)


# 資料儲存(JSON檔)
with open(f'damun_{sn}.json', 'w') as f:
json.dump(res, f)

page.close()

# ---------------------
context.close()
browser.close()
return res


with sync_playwright() as playwright:
run(playwright, sys.argv[1])

執行playwright腳本

接下來,執行我們生成的腳本,可以在命令列執行腳本。

33846為動畫的編號,可以更換成想要分析的動畫序號。

python damun.py 33846

然後,使用Python的ast模組將結果轉換為Python對象。以下是一個實際的例子:

# 此欄位內容於ipynb執行
res = ! python damun.py 33846
import ast
res = [ast.literal_eval(i) for i in res]
print(res)

將內容存為page.json

有兩種方式可以將我們獲得的結果儲存為json格式。一種方式是使用linux的命令行將結果重定向到一個json檔案中。例如:

> python damun.py 33846 > page.json

另一種方式是直接在Python腳本中將結果儲存為json檔案。以下是一個實際的例子:

import json

file_name = 'damun_33846.json'

with open(file_name, 'r', encoding='utf-8') as f:
my_data = json.loads(f.read())

print(my_data)

print(type(my_data))

解析的結果為:

擷取完成!

重點精華

  • PlayWright可以輕鬆的將使用者操作流程紀錄為程式碼。
  • PlayWright與Selenium最大的差異,不用刻意搜尋並安裝對應版本的模擬瀏覽器。
  • 結合常用的Beautiful可以快速解析內容,我偏好用類似CSS Selec。
  • 用列表推導式將爬梳的資料整理成字典,語法相當簡潔。
  • 將結果儲存成JSON2檔案,方便後續運用

小結

在上述的Python腳本中,首先定義了我們的檔案名稱。然後,我們使用Python的內建函數open讀取該檔案。最後,我們使用json模組的loads函數將讀取到的資料轉換為Python物件。

以上就是如何使用PlayWright抓取並分析巴哈姆特動漫瘋的彈幕數據的全過程。透過這個過程,我們不僅學習到如何使用PlayWright,如果有興趣,後續再介紹如何進一步分析數據,歡迎留言讓我知道。