攝影或3C

Python 爬蟲入門:從 HTML 到 JSON 的快速定位法

# Python 爬蟲入門:從 HTML 到 JSON 的快速定位法

當你在爬資料時,常見卡關點不是「怎麼抓到網頁」,而是「HTML 太長太亂,不知道要找什麼」。

這篇用最小範例示範三件事:

1. 先判斷要抓 **原始 HTML** 還是 **JS 動態載入後的內容**

2. 用 BeautifulSoup 快速定位元素並抽取資料

3. 把「一小塊 DOM」整理成 **JSON**,讓 tag/屬性/文字更好看(也更好決定 selector)

## 1) 先搞清楚:你要的是「View Source」還是「Elements」

很多網站是 SPA / 前端框架頁面:

**View Page Source(Ctrl+U)**:初始 HTML(可能只有空殼)

**DevTools → Elements**:JS 跑完後的 DOM(你肉眼看到的內容在這裡)

**DevTools → Network → Fetch/XHR**:前端實際呼叫的 API(常是 JSON)

**最佳策略:能抓 API JSON 就別硬 parse HTML**,更穩定也更快。

## 2) 取得 HTML(requests)

import requests

url = "https://example.com"
resp = requests.get(url, timeout=(10, 30))
resp.raise_for_status()
html = resp.text

> 注意:如果網站需要登入、或內容由 JS 動態載入,`requests` 拿到的 HTML 可能不含你要的資料。

## 3) 解析 HTML(BeautifulSoup)

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, "html.parser")

#  title
print(soup.title.get_text(strip=True))

# 抓所有連結
for a in soup.select("a[href]"):
    print(a["href"], a.get_text(" ", strip=True))
# 補充get_text(" ", strip=True)
# - 第一個參數 " " 是分隔符separator):把不同文字節點用空格隔開避免字黏在一起
# - strip=True去掉每段文字前後多餘空白

## 4) HTML 太亂?把「重點區塊」轉成 JSON 來觀察

這招的目的不是把整頁變 JSON,而是:

– 你先挑到「看起來像主內容」的節點(例如某個 card / product / article)

– 再把它的 tag/attrs/子節點資訊 dump 成 JSON

– 你會更容易看出:應該用哪個 `class` / `data-*` / 層級關係來寫 selector

### 範例:把節點摘要成 JSON

import json
from bs4 import BeautifulSoup

html = """
<div class='product' data-sku='W-001'>
  <h1>Widget</h1>
  <span class='price' data-currency='USD'>$19.99</span>
  <ul class='spec'>
    <li data-k='color'>red</li>
    <li data-k='size'>M</li>
  </ul>
</div>
"""

soup = BeautifulSoup(html, "html.parser")
node = soup.select_one("div.product")
# node.attrs 的型別是 bs4.element.AttributeDictdict-like
# - 讀取時可當作 dict 使用node.attrs.get("data-sku")、node["data-sku"]
# - 轉成 dict(...) 通常是為了做快照方便 JSON 序列化/輸出
view = {
    "tag": node.name,
    "attrs": dict(node.attrs),
    "text": node.get_text(" ", strip=True),

    # 只看第一層 childrenrecursive=False),避免資訊爆炸
    # - node.find_all() 若不給 tag/屬性條件代表範圍內全部 tag 都抓
    # - recursive=False 代表只抓直屬子節點」(不往更深層的孫節點找
    "children": [
        {"tag": c.name, "attrs": dict(c.attrs), 
        "text": c.get_text(" ", strip=True)}
        for c in node.find_all(recursive=False)
    ],
}

print(json.dumps(view, ensure_ascii=False, indent=2))

你會得到清楚的輸出,例如:

– 主容器是 `div`,並且有屬性(attribute)例如 `class`、`data-sku`

  – `class` / `data-sku` 是「屬性名」,`product` / `W-001` 是「屬性值」

  – 注意:在 BeautifulSoup 裡
`class` 通常會以 list 呈現(因為 HTML 允許多個 class),
例如 `{“class”: [“product”]}`

– 價格在 `span.price[data-currency]`

– 規格在 `.spec li[data-k]`

接下來 selector 就很容易寫。

## 5) 從 HTML 直接抓 JSON(最常見:JSON-LD / 內嵌 JSON)

很多網站會把關鍵資料直接塞在 `<script>` 裡(這通常比 parse DOM 更穩)。

### 5.1 JSON-LD(SEO 結構化資料)

import json
from bs4 import BeautifulSoup

html = """
<script type="application/ld+json">
  {"@context":"https://schema.org","@type":"Product","name":"Widget","sku":"W-001"}
</script>
"""

soup = BeautifulSoup(html, "html.parser")
ld = soup.select_one('script[type="application/ld+json"]')
data = json.loads(ld.string)
print(data["@type"], data.get("name"), data.get("sku"))

### 5.2 內嵌 JSON(SPA/SSR 常見)

import json
from bs4 import BeautifulSoup

html = """
<script id="__DATA__" type="application/json">
  {"apiUrl":"/api/items","user":{"id":123,"name":"Ada"}}
</script>
"""

soup = BeautifulSoup(html, "html.parser")
raw = soup.select_one('script#__DATA__[type="application/json"]').string
embedded = json.loads(raw)
print(embedded["apiUrl"], embedded["user"]["name"])

## 6) 小結:什麼時候用「JSON」幫助你爬蟲?

**你不知道要怎麼寫 selector**:把「一小塊 DOM」dump 成 JSON → 快速看出關鍵 attrs

**網站本來就藏 JSON**:優先抓 `application/ld+json` / `application/json` / `__NEXT_DATA__`

**網站由 API 驅動**:去 Network 找 XHR → 直接打 JSON API(最穩)

## 參考:快速安裝依賴

pip install requests beautifulsoup4

> 補充:`bs4` 是你在程式裡 `from bs4 import BeautifulSoup` 的模組名;用 pip 安裝時請裝 `beautifulsoup4`(而不是 `bs4`)。

>

> 想要解析更快/更穩也可以再裝解析器:`pip install lxml`,並把 parser 改成 `BeautifulSoup(html, “lxml”)`。

推薦hahow線上學習python: https://igrape.net/30afN

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡