iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
生成式 AI

一起來打造 PTT 文章智慧問答系統!系列 第 6

【Day 06】探索 PTT 結構與版面資料抓取 – 從 HTML 中提取文章資訊

  • 分享至 

  • xImage
  •  

Hi大家好,
這是我參加 iT 邦幫忙鐵人賽的第 1 次挑戰,這次的主題聚焦在結合 Python 爬蟲、RAG(檢索增強生成)與 AI,打造一套 PTT 文章智慧問答系統。在過程中,我會依照每天進度上傳程式碼到 GitHub ,方便大家參考學習。也歡迎留言或來信討論,我的信箱是 gerryearth@gmail.com


在昨日完成了環境與容器建置後,今天我們將動手開始第一個核心功能:PTT 文章爬蟲


本日目標

  1. 了解 PTT Web 結構與擋爬機制
  2. 使用 Python + requests + BeautifulSoup 擷取文章列表與內容
  3. 撰寫初步爬蟲函式,抓取指定看板的文章標題與連結

PTT 是怎麼組成的?

PTT 網頁版的網址格式如下:

https://www.ptt.cc/bbs/<版名>/index.html

每個看板都由數百個頁面組成,頁碼會不斷遞增,例如:

  • Gossiping(八卦版) 第38000頁: https://www.ptt.cc/bbs/Gossiping/index38000.html
  • NBA 最新一頁: https://www.ptt.cc/bbs/NBA/index.html

每頁包含約 20 篇文章,點擊進入後可看到文章內容與推文。

網頁結構重點:

文章列表頁(如 Gossiping)中,每篇文章是一個 .r-ent 區塊,以下顯示主要內容架構:

<div class="r-ent">
    <div class="title">
        <a href="/bbs/Gossiping/M.1716000000.A.000.html">[問卦] 今天天氣好嗎?</a>
    </div>
    <div class="meta">
        <div class="author">pttuser</div>
        <div class="date"> 5/22</div>
    </div>
</div>

這裡我們只要想辦法取得文章網址就好了!


擋爬提示:年齡驗證機制

PTT 有簡單的 age check 頁面(未滿 18 禁止進入),需要在 request 時處理 cookies。

若直接抓取 PTT Gossiping 會看到:

請按下「我同意」以繼續瀏覽。

解法是:送出 cookies 中加入 over18=1

這部分明天會有 code 與相關說明。


實作步驟

步驟一: 安裝爬蟲套件

pip install requests beautifulsoup4

步驟二: 撰寫爬蟲程式

裝完套件後我們建立 scraper.py 來寫爬蟲程式,基本上會用到套件:

import requests
from bs4 import BeautifulSoup

爬蟲程式建議可以自行練習,以下範本僅供參考,這裡我先寫架構,明天再一起對答案吧!

  1. 我們先撰寫主要爬蟲架構如下:
def ptt_scrape(board: str) -> list:
    board_url = 'https://www.ptt.cc/bbs/' + board + '/index.html'  # 首先建立看板網址
    board_html = get_html(board_url)  # 由看板網址取得 html
    article_urls = get_urls_from_board_html(board_html)  # 由看板 html 取得文章網址
    article_datas = []
    for article_url in article_urls:
        article_html = get_html(article_url)  # 由文章網址取得 html
        article_data = get_data_from_article_html(article_html)  # 由文章 html 取得文章資訊
        article_data.update({'board': board})  # 加入版面名稱資訊
        article_datas.append(article_data)  # 將文章資訊蒐集起來
    return article_datas  # 回傳文章資訊列表

這裡我只爬取最新一頁看板文章網址。

  1. 撰寫 get_html 由網址取得 html :
def get_html(url: str) -> str:
    ...

這個函式可以抓取 PTT 網頁內容,自動通過滿18歲的驗證,回傳 HTML 原始碼。

  1. 撰寫 get_urls_from_board_html 由看板 html 取得文章網址 :
def get_urls_from_board_html(html: str) -> list:
    ...

從 PTT 看板的 HTML 中提取所有文章的網址,回傳網址列表。

  1. 撰寫 get_data_from_article_html 由文章 html 取得文章資訊 :
def get_data_from_article_html(html: str) -> dict:
    ...

這個函式會從 PTT 的文章 HTML 中擷取標題、作者、發文時間與文章內容,回傳文章資訊字典。

步驟三: 測試抓取文章列表

如果都寫完了可先自行測試:

if __name__ == "__main__":
    article_datas = ptt_scrape("Gossiping")
    for article_data in article_datas:
        print(article_data)

明天【Day 07】:建立基本爬蟲抓取文章列表與內容 – 自動擷取 PTT 文章的第一步,我們將把 PTT 文章完整擷取下來並稍作整理!


上一篇
【Day 05】Docker 環境建置 - 建立可攜式開發與執行環境 (下)
下一篇
【Day 07】建立基本爬蟲抓取文章列表與內容 – 寫出完整爬蟲程式
系列文
一起來打造 PTT 文章智慧問答系統!14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言