iT邦幫忙

2023 iThome 鐵人賽

0
Software Development

跟著 OXXO 一起學 Python系列 第 65

( Day 31.2 ) Python 爬取 LINE TODAY 留言

  • 分享至 

  • xImage
  •  

這篇文章會解析 LINE TODAY 的留言頁面,搭配 Python 的 Requests 函式庫,實作一個可以爬取 LINE Today 某篇文章所有留言的網路爬蟲。

原文參考:爬取 LINE TODAY 留言

本篇使用的 Python 版本為 3.7.12,所有範例可使用 Google Colab 實作,不用安裝任何軟體 ( 參考:使用 Google Colab )

LINE Today 留言結構

使用 Chrome 瀏覽器,開啟 LINE TODAY 的頁面,點選任意一篇文章,開啟文章頁面。

LINE TODAY:https://today.line.me/tw/v2/tab

本篇範例開啟了一篇「英特爾基辛格已抵台 錄影片讚聲台積電」的文章。

文章連結:https://today.line.me/tw/v2/article/oqay0ro

將文章往下捲動,找到留言的位置,點擊「顯示全部」,會開啟留言的頁面。

文章對應的留言頁面:https://today.line.me/tw/v2/comment/article/oqay0ro

開啟留言頁面後,在網頁的任意位置,按下滑鼠右鍵,點擊「檢視」,開啟 Chrome 開發者工具,切換到「Network」頁籤,在 Network 頁籤裡,可以看到網頁開啟時,所有透過網路下載或上傳的內容 ( 如果沒有看到內容,重新整理網頁就會看到 )。

Python 教學 - 爬取 LINE TODAY 留言 - LINE Today 留言結構

點擊前方的清除按鈕,清空內容 ( 方便待會觀察出現哪些項目 ),再將子頁籤切換到「Fetch/XHR」,該頁籤表示有哪些 XMLHttpRequest 物件在交換溝通。

Python 教學 - 爬取 LINE TODAY 留言 - 物件在交換溝通

重新整理網頁,開發者工具中就會陸續出現一些物件,在畫面裡找到名為「list?articleId=.....」的項目,點選這個項目,就能看到該文章的有多少留言以及所有留言的內容。

Python 教學 - 爬取 LINE TODAY 留言 - 該文章的有多少留言以及所有留言的內容

觀察一下這個物件的網址 ( 可以在該項目上按下滑鼠右鍵,開啟到新的 tab 裡 ),可先注意這篇文章的 articleId、每次顯示留言的數量 limit 和第二頁開始的次序 pivot

https://today.line.me/webapi/comment/list?articleId=179673305&sort=POPULAR&direction=DESC&country=TW&limit=30&pivot=0&postType=Article

因為留言物件的網址數量 limit 設定為 30,所以如果該網頁的留言很多 ( 範例網頁有超過兩百則留言 ),會產生「不止一筆」留言物件,這時從開發者工具裡就會看到 pivot=0、pivot=30、pivot=60...等的留言物件網址。

Python 教學 - 爬取 LINE TODAY 留言 - 「不止一筆」留言物件

由於文章的網址並沒有 articleId,表示網頁一定是透過某些機制將網址對應到 articleId,檢視網頁原始碼後 ( 在網頁上點擊滑鼠右鍵,點選檢視網頁原始碼 ),搜尋 179673305 ( 這篇文章的 articleId ),會發現網頁原始碼有撰寫了相對應的轉換程式,如何轉換並不重要,重要的是記住下圖標註紅色的位置,待會會透過程式擷取對應的 articleId。

Python 教學 - 爬取 LINE TODAY 留言 - 擷取對應的 articleId

轉換網址,印出留言總數}

由於 Fetch/XHR 的網址使用的是 articleId,所以必須先從原本的網址裡提取 articleId ( 目的在於如果有多個頁面,就不用一一開啟開發者工具找 articleId ),下方的程式碼執行後,會印出該篇文章的 articleId。

參考:Requests 函式庫拆分字串 str.split(x)

import requests

webUrl = requests.get('https://today.line.me/tw/v2/article/oqay0ro')   # get 文章網址
# 取得文章的原始碼後,使用 split 字串拆分的方式,拆解出 articleId
article_id = webUrl.text.split('<script>')[1].split('id:"article:')[1].split(':')[0]
print(article_id)

取得 articleId 後,將使用變數與字串格式化的方式,將留言物件的 articleId 更換成該篇文章的 articleId,再度使用 requests,取得 json 格式的內容,並印出文章的總數。

參考:字串格式化 f-string

import requests

webUrl = requests.get('https://today.line.me/tw/v2/article/oqay0ro')   # get 文章網址
# 取得文章的原始碼後,使用 split 字串拆分的方式,拆解出 articleId
article_id = webUrl.text.split('<script>')[1].split('id:"article:')[1].split(':')[0]
print(article_id)

# 使用 requests get 留言物件
comment = requests.get(f'https://today.line.me/webapi/comment/list?articleId={article_id}&sort=POPULAR&direction=DESC&country=TW&limit=30&pivot=0&postType=Article')
json = comment.json()   # 取得內容後,轉換成 json 格式
num = int(json['result']['comments']['count'])   # 取得文章的總數
print(num)   # 印出文章總數

Python 教學 - 爬取 LINE TODAY 留言 - 轉換網址,印出留言總數

印出每一筆留言的內容

由於留言筆數過多時 ( 每頁留言一次顯示最多 100 篇 ),留言的物件會拆分成不同的項目,所以下方的程式定義了一個 getComment 函式,在函式執行時賦予「pivot」( 下一頁從第幾筆留言開始 ) 的參數,並透過 range 和 for 迴圈的搭配,就能印出所有的留言。

參考:rangefor 迴圈

import requests

webUrl = requests.get('https://today.line.me/tw/v2/article/oqay0ro')
article_id = webUrl.text.split('<script>')[1].split('id:"article:')[1].split(':')[0]
print(article_id)

commentUrl = requests.get(f'https://today.line.me/webapi/comment/list?articleId={article_id}&sort=POPULAR&direction=DESC&country=TW&limit=30&pivot=0&postType=Article')
json = commentUrl.json()
num = int(json['result']['comments']['count'])
print(num)

# 定義函式,給予一個參數
def getComment(n):
    # 使用字串格式化的方式,讓網址會根據不同的參數而有所不同
    commentUrl = requests.get(f'https://today.line.me/webapi/comment/list?articleId={article_id}&sort=POPULAR&direction=DESC&country=TW&limit=30&pivot={n}&postType=Article')
    json = commentUrl.json()     # 取得對應網址的 json 內容
    comments = json['result']['comments']['comments']   # 取得該網址下所有留言
    for i in comments :
        # 印出留言者名稱以及留言內容
        print('<' + i['displayName'] + '>\n' + i['contents'][0]['extData']['content'])
        print('----------------')

for i in range(0, num, 30):
    getComment(i)    # 從 0 開始,每隔 30 筆取一次

Python 教學 - 爬取 LINE TODAY 留言 - 印出每一筆留言的內容

小結

一個網頁在顯示的過程中,背後可能不斷的在與後端交換資料,只要善用 Chrome 的開發者工具,可以從中獲得很多在網頁上看不到的內容,搭配 Python 的函式庫,就能輕鬆抓取各種網頁內容了。

更多教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我有個超過一千篇教學的 STEAM 教育學習網,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 31.1 ) Python 爬取 Yahoo 股市即時股價
下一篇
( Day 32.1 ) Python 發送 LINE Notify 通知
系列文
跟著 OXXO 一起學 Python101
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言