微博爬蟲JSON API + requests + Cookie
Visit Weibo
⭐ 入門🍪 需要 Cookie📡 JSON APISICSS Singapore 2023

微博用戶貼文
JSON API 爬蟲教學

本教學改編自 SICSS Singapore 2023 工作坊代碼。 微博使用 JSON API(非傳統 HTML), 直接返回結構化數據,不需要 XPath 解析。 爬取指定用戶在特定時間段內的所有貼文,提取 10 個字段

📡 API 端點
GET https://weibo.com/ajax/statuses/searchProfile
參數:uid(用戶ID)page(頁碼)starttime / endtime(Unix 時間戳)
🍪需要 Cookie 才能運行⚠️ Cookie 有效期約 7 天,過期需重新獲取
  1. 1. 用 Chrome 登入 weibo.com
  2. 2. 按 F12 → Network 分頁 → 刷新頁面
  3. 3. 點擊任意 weibo.com 請求 → Headers → 找 Cookie:
  4. 4. 複製整行值,貼入 Cell 3 的 COOKIE_STR
JSON FIELDS — 微博貼文,共 10 個字段
字段名JSON 取值路徑說明
_ideach_weibo['id']微博唯一 ID
weibo_url'https://weibo.com/' + user_id + '/' + mblogid拼接完整 URL
user_ideach_weibo['user']['id']嵌套 JSON 取用戶 ID
created_ateach_weibo['created_at']發布時間(UTC 字符串)
sourceeach_weibo['source']發布來源(iPhone/Android/網頁版)
like_numeach_weibo['attitudes_count']點讚數
repost_numeach_weibo['reposts_count']轉發數
comment_numeach_weibo['comments_count']評論數
contenteach_weibo['text_raw']純文字內容(不含 HTML 標籤)
geo_infoeach_weibo['geo']地理位置(可選,多數為 null)
🔍 如何找到用戶 UID
方法 1:打開用戶主頁 → URL 中的數字即為 UID,如 weibo.com/u/2793117267
方法 2:F12 → Console → 輸入 $CONFIG.uid(在用戶主頁執行)
方法 3:搜尋 weibo.com/ajax/profile/info?uid=... 的 Network 請求
Setup📦 Cell 1 — 安裝套件
安裝 requests(HTTP 請求)、datetime(日期處理)。注意:json 是 Python 內建模組,不需要 pip 安裝,直接 import 即可。
# 安裝所需套件
# 注意:json 是 Python 內建模組,不需要 pip 安裝!
!pip install requests   # HTTP 請求庫
# datetime 也是 Python 內建模組,不需要 pip 安裝

import os
print("工作目錄:", os.getcwd())
Import📚 Cell 2 — 導入套件
導入所有需要的 Python 套件。微博爬蟲使用 JSON API,不需要 lxml XPath,但需要 json 模組解析回應。
import requests   # 發送 HTTP 請求
import datetime  # 將日期字符串轉換為 Unix 時間戳
import json      # 解析微博 API 回傳的 JSON 數據
import csv       # 儲存為 CSV 格式
import os        # 文件路徑操作

print("✅ 所有套件導入完成")
Cookie⚙️ Cell 3 — Cookie + 參數設定(必須)
微博 API 需要登入 Cookie 才能訪問。同時設定目標用戶 ID、時間範圍、頁碼等參數。Cookie 有效期約 7 天,過期需重新獲取。
# ═══════════════════════════════════════════════════════
# 如何獲取 Cookie(必讀):
# 1. 用 Chrome 登入 https://weibo.com
# 2. 按 F12 → Network 分頁 → 刷新頁面
# 3. 點擊任意 weibo.com 請求 → Headers → 找 "Cookie:"
# 4. 複製整行 Cookie 值,貼到下方 COOKIE_STR
# ═══════════════════════════════════════════════════════

COOKIE_STR = "SCF=Av5pDLQkZ9ZlxHgaag1MAaUUyaxG2-5DK7nlXjJvpZsj9NuZ2pMQTQ0a3Aze3DMsyoi4OEnr9bsjKt4j6rVowcA.; SINAGLOBAL=9907163292993.223.1751026142282; UOR=,,login.sina.com.cn; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WFYz2N3N-pzMGw55dfaf__s5JpX5KMhUgL.Fo-NSK2NSoBceh52dJLoIpfFHCH81C-41C-R1FH8SCHWxC-R1CH8SEHF1C-ReBtt; ULV=1772725555092:20:2:2:6279291782624.625.1772725554898:1772441874527; XSRF-TOKEN=-kxxzRn39W1i04b1nmsVT2rO; ALF=1776269269; SUB=_2A25EvFqFDeRhGeNJ7lMW9irKyzyIHXVnsNJNrDV8PUJbkNANLRfYkW1NS9Us91NdbNrIxiubyfsbwmSoyYTVsEc-; WBPSESS=9BNQRUw_qfhmyP_PgW7d1L64bIfGo2ey0LhxkWfSBoYg1CR5KvOorvcWNoS8mfMmzxbSI_NxRyzNS5AN5azAo5x7rkPTdpTyffiHD4KMMCjPxTmxzOEfOZLkLuvdkOjCkIjg1UnUqdECUSdGzlSVAA=="

# 自動從 Cookie 中提取 XSRF-TOKEN(微博防範 CSRF 攻擊用)
def get_xsrf_token(cookie_str):
    for part in cookie_str.split(';'):
        part = part.strip()
        if part.startswith('XSRF-TOKEN='):
            return part.split('=', 1)[1].strip()
    return ''

XSRF_TOKEN = get_xsrf_token(COOKIE_STR)

# ── 爬取參數設定(必須在 HEADERS 之前定義,因為 Referer 需要 USER_ID)──
USER_ID    = "2793117267"   # 目標用戶的微博 UID(在用戶主頁 URL 中可找到)
START_DATE = '2023-04-07'   # 開始日期(格式:YYYY-MM-DD)
END_DATE   = '2023-06-08'   # 結束日期(格式:YYYY-MM-DD)
MAX_PAGES  = 3              # 最多爬幾頁(每頁約 10-20 條)
OUTPUT_CSV = 'weibo_posts.csv'

# HTTP Headers:模擬真實 Chrome 瀏覽器
# 關鍵:微博 API 需要 Referer + X-XSRF-TOKEN 才能通過 403 驗證
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
    'Accept': 'application/json, text/plain, */*',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
    'Cookie': COOKIE_STR,
    'Referer': 'https://weibo.com/u/' + USER_ID,  # 必須!告訴服務器請求來自哪裡
    'X-XSRF-TOKEN': XSRF_TOKEN,                   # 必須!防止 CSRF 攻擊驗證
    'X-Requested-With': 'XMLHttpRequest',           # 標記為 AJAX 請求
}

# ── 將日期轉換為 Unix 時間戳(微博 API 要求)────────────
date_start = datetime.datetime.strptime(START_DATE, '%Y-%m-%d')
ds = int(datetime.datetime.timestamp(date_start))  # 開始時間戳
date_end   = datetime.datetime.strptime(END_DATE, '%Y-%m-%d')
de = int(datetime.datetime.timestamp(date_end))    # 結束時間戳

print("✅ 參數設定完成")
print("用戶 ID:", USER_ID)
print("時間範圍:", START_DATE, "→", END_DATE)
print("時間戳:", ds, "→", de)
API Request🌐 Cell 4 — 發送 API 請求並解析 JSON
微博使用 JSON API(非傳統 HTML),直接返回結構化數據。API 端點:/ajax/statuses/searchProfile,支持按用戶 ID + 時間範圍查詢。
# ═══════════════════════════════════════════════════════
# 微博 API 說明:
# 端點:https://weibo.com/ajax/statuses/searchProfile
# 參數:uid(用戶ID)、page(頁碼)、starttime/endtime(Unix時間戳)
#       hasori=1(原創)、hasret=1(轉發)、hastext=1(有文字)
#       haspic=1(有圖片)、hasvideo=1(有視頻)、hasmusic=1(有音樂)
# 注意:這是 JSON API,不是 HTML,不需要 XPath 解析
# ═══════════════════════════════════════════════════════

all_weibos = []  # 儲存所有頁的微博

for page_num in range(1, MAX_PAGES + 1):
    print("正在爬取第", page_num, "頁...")

    # 構建 API URL(用 .format() 填入參數)
    url = (
        'https://weibo.com/ajax/statuses/searchProfile'
        '?uid={}&page={}&starttime={}&endtime={}'
        '&hasori=1&hasret=1&hastext=1&haspic=1&hasvideo=1&hasmusic=1'
    ).format(USER_ID, page_num, ds, de)

    # 發送 GET 請求(帶 Cookie 認證)
    response = requests.get(url, headers=HEADERS)

    # 檢查回應狀態
    if response.status_code != 200:
        print("  ✗ 請求失敗,狀態碼:", response.status_code)
        break

    # 將 JSON 字符串解析為 Python dict
    data = json.loads(response.text)

    # 取出微博列表(在 data['data']['list'] 中)
    weibo_list = data.get('data', {}).get('list', [])
    print("  → 找到", len(weibo_list), "條微博")

    if not weibo_list:
        print("  → 沒有更多數據,停止爬取")
        break

    all_weibos.extend(weibo_list)

    # 加入延遲,避免被封鎖
    import time
    time.sleep(1.5)

print("\n✅ 共收集", len(all_weibos), "條微博")

# 預覽第一條微博的 JSON 結構(了解數據格式)
if all_weibos:
    first = all_weibos[0]
    print("\n第一條微博預覽:")
    print("  ID:", first.get('id'))
    print("  用戶:", first.get('user', {}).get('screen_name'))
    print("  時間:", first.get('created_at'))
    print("  內容:", str(first.get('text_raw', ''))[:50], "...")
JSON Parse🔍 Cell 5 — 提取字段(JSON 解析)
從每條微博的 JSON 中提取 10 個字段。微博 API 返回嵌套 JSON,需要用 dict['key'] 或 .get() 方法取值。
# ── 提取 10 個字段 ────────────────────────────────────
weibo_records = []

for each_weibo in all_weibos:
    item = {}

    # 字段 1:微博唯一 ID
    item['_id'] = each_weibo.get('id', '')

    # 字段 2:微博完整 URL(拼接用戶 ID + mblogid)
    user_id_val = each_weibo.get('user', {}).get('id', '')
    mblogid     = each_weibo.get('mblogid', '')
    item['weibo_url'] = 'https://weibo.com/' + str(user_id_val) + '/' + str(mblogid)

    # 字段 3:用戶 ID(嵌套在 user 對象中)
    item['user_id'] = user_id_val

    # 字段 4:用戶暱稱
    item['screen_name'] = each_weibo.get('user', {}).get('screen_name', '')

    # 字段 5:發布時間(UTC 字符串,如 "Fri Apr 07 10:30:00 +0800 2023")
    item['created_at'] = each_weibo.get('created_at', '')

    # 字段 6:發布來源(如 "iPhone客户端"、"微博 weibo.com")
    item['source'] = each_weibo.get('source', '')

    # 字段 7:點讚數(attitudes = 態度 = 點讚)
    item['like_num'] = each_weibo.get('attitudes_count', 0)

    # 字段 8:轉發數
    item['repost_num'] = each_weibo.get('reposts_count', 0)

    # 字段 9:評論數
    item['comment_num'] = each_weibo.get('comments_count', 0)

    # 字段 10:純文字內容(text_raw 不含 HTML 標籤,比 text 更乾淨)
    item['content'] = each_weibo.get('text_raw', '')

    # 字段 11(可選):地理位置(多數為 null)
    item['geo_info'] = str(each_weibo.get('geo', ''))

    weibo_records.append(item)

print("✅ 已解析", len(weibo_records), "條微博")
if weibo_records:
    print("\n前 3 條預覽:")
    for r in weibo_records[:3]:
        print("  [", r['_id'], "]", r['screen_name'], "|", r['created_at'][:10], "|", str(r['content'])[:30], "...")
Export💾 Cell 6 — 儲存 CSV 並自動下載
將微博數據儲存為 CSV,並在 Google Colab 中自動觸發下載。使用 JavaScript 觸發下載,同時提供備用手動下載連結。
# ── 儲存為 CSV ────────────────────────────────────────
if not weibo_records:
    print("❌ 錯誤:weibo_records 為空!請先執行 Cell 4 和 Cell 5")
else:
    fieldnames = ['_id', 'weibo_url', 'user_id', 'screen_name',
                  'created_at', 'source', 'like_num', 'repost_num',
                  'comment_num', 'content', 'geo_info']

    # encoding='utf-8-sig' 加入 BOM,確保 Excel 正確顯示中文
    with open(OUTPUT_CSV, 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction='ignore')
        writer.writeheader()
        writer.writerows(weibo_records)

    print("✅ 已儲存 " + str(len(weibo_records)) + " 條微博到 " + OUTPUT_CSV)

    # ── 可靠下載函數(JavaScript 觸發 + 備用連結)────────────
    def colab_download(filename):
        """
        在 Google Colab 中可靠地下載文件
        方法 1:JavaScript 直接觸發瀏覽器下載
        方法 2:顯示備用下載連結(若瀏覽器攔截,手動點擊)
        """
        import base64
        from IPython.display import display, Javascript, HTML
        with open(filename, 'rb') as f:
            data = base64.b64encode(f.read()).decode('utf-8')
        # JavaScript 動態建立 <a> 標籤並自動點擊
        js = """
        var link = document.createElement('a');
        link.href = 'data:text/csv;base64,""" + "' + data + '" + """';
        link.download = '""" + "' + filename + '" + """';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        """
        display(Javascript(js))
        # 備用手動下載連結
        html_link = '<a href="data:text/csv;base64,' + data + '" download="' + filename + '" style="color:#4ade80;font-family:monospace;font-size:13px">⬇️ 點此手動下載 ' + filename + '</a>'
        display(HTML(html_link))
        print("📥 已觸發下載:" + filename)

    colab_download(OUTPUT_CSV)
    print("\n✅ 下載完成!")
    print("  📄 " + OUTPUT_CSV + " — 微博貼文(" + str(len(weibo_records)) + " 條)")
🚀 使用步驟
  1. 1. 登入 weibo.com,按上方說明獲取 Cookie
  2. 2. 打開 Google Colab,新建筆記本
  3. 3. 修改 Cell 3 的 COOKIE_STRUSER_IDSTART_DATEEND_DATE
  4. 4. 依序執行 Cell 1 → Cell 6,最後自動下載 CSV
  5. 5. ⚠️ 注意:Cookie 有效期約 7 天,過期後需重新獲取
💡 JSON API vs XPath 爬蟲的區別
JSON API(微博、LIHKG)
  • • 直接返回結構化數據
  • • 用 json.loads() 解析
  • • 用 dict['key'] 取值
  • • 數據更乾淨,不含 HTML 標籤
  • • 需要找到正確的 API 端點
HTML + XPath(RTHK、OpenRice)
  • • 返回 HTML 頁面
  • • 用 etree.HTML() 解析
  • • 用 tree.xpath("...") 取值
  • • 需要分析 HTML 結構
  • • class 名稱可能動態變化