跳到主要內容跳到頁尾

IMPORTXML 基礎:用 XPath 抓網頁上指定的內容

7 分鐘閱讀Lv.3 中級摘要與日期

IMPORTHTML 只能抓整張表格或清單,想抓標題、連結網址或某個 class 的內容就要用 IMPORTXML。從 //h2、//a/@href、[@class]、text()、contains() 學 XPath 基本寫法,並說明 JavaScript 動態內容抓不到、網站可能封鎖的情況。

發布 更新

文章目錄

IMPORTHTML 只能整張表格、整份清單一起抓。如果我只想要網頁上的所有標題,或是每個連結實際指向的網址,就要請出 IMPORTXML,用 XPath 告訴它要哪一塊。

XPath 看起來很像密碼,不過常用的寫法就那幾種,這篇逐一示範,最後講哪些網頁抓不到。

IMPORTXML

IMPORTXML 會讀取網址的內容,把符合 XPath 的部分放進試算表。

語法

  • 網址:完整網址,要加 https://,用雙引號包起來,也可以放在別的儲存格再參照。
  • XPath查詢:要選哪些元素的描述,同樣用雙引號包起來。
  • 地區:選填,用來解析數字、日期的地區代碼;沒填就用檔案的地區設定。本文的範例都用不到。

公式本身已經用雙引號包字串,XPath 裡面要放引號的話,用單引號:"//a[@class='nav']"。

網址我通常放在別的儲存格,公式比較短,要換頁面也只改一格。下面的範例都在 A1 放同一個網址,維基百科的 Mohs scale(莫氏硬度)條目,網址是:

https://en.wikipedia.org/wiki/Mohs_scale_of_mineral_hardness

公式放在 C1,結果會從 C1 往下展開。文中的數字是 2026 年 10 月的頁面。維基百科會被編輯,哪天你看到的數字不一樣是正常的。

XPath 基本寫法

選標籤://h1、//h2

// 的意思是「不管在文件的哪個位置」,後面接標籤名稱。先抓頁面的大標題:

Google 試算表公式
fx

抓頁面中所有 h1 標籤的文字

=IMPORTXML(A1, "//h1")

這個頁面只有一個 h1,C1 會得到 Mohs scale。

第一次在檔案裡用 IMPORTXML(或 IMPORTHTML、IMPORTDATA、IMPORTFEED),儲存格會先是 #REF!,畫面上方出現黃色橫幅:「警告:某些公式正試圖傳送資料到外部或接收外部的資料。」右邊有「瞭解詳情」和「允許存取」,按「允許存取」之後,這份檔案裡的這幾個函式才會真的去抓資料。IMPORTRANGE 另有一套「連結試算表」的授權卡片,不走這個橫幅,做法見 IMPORTRANGE 跨試算表同步。

再來抓所有的 h2,也就是各段落的標題:

Google 試算表公式
fx

抓頁面中所有 h2 標籤的文字

=IMPORTXML(A1, "//h2")

來看看結果,共 9 列:

列C
1Contents
2Reference minerals
3Examples
4Use
5Comparison with Vickers scale
6Footnotes
7See also
8References
9Further reading

第 1 列的 Contents 是維基百科目錄區塊的標題,不是條目的段落。想把它排除,可以加條件,後面的練習會做。

選屬性://a/@href

標籤上的屬性用 @ 開頭。連結的目標網址放在 a 標籤的 href 屬性裡,所以:

Google 試算表公式
fx

抓頁面中所有連結的網址

=IMPORTXML(A1, "//a/@href")

這一天的頁面有 429 個連結,前三個是:

列C
1#bodyContent
2/wiki/Main_Page
3/wiki/Wikipedia:Contents

第一個 #bodyContent 是跳到頁面內某處的連結,第 2、3 個只有路徑沒有網域,拿去用之前要自己補上 https://en.wikipedia.org。同一個頁面的寫法也不統一,後面還有直接寫完整網址的,真的要整批使用,我會先掃一遍再決定怎麼處理。

標籤換成別的也一樣,//img/@src 就是頁面上所有圖片的來源路徑。

加條件:[@class='...']

方括號裡放條件,@class='wikitable' 的意思是「class 屬性正好等於 wikitable」。想知道頁面上有幾個這種表格,用 COUNTA 數一下:

Google 試算表公式
fx

數 class 正好是 wikitable 的表格有幾個

=COUNTA(IMPORTXML(A1, "//table[@class='wikitable']"))

結果是 2。但莫氏硬度那張主表格的 class 是 wikitable sortable,兩個詞,所以沒被選到。「等於」就是整個字串完全一樣,多一個字都不行。

來比較三種寫法,各用一格公式,放在 E1 到 E3:

儲存格XPath結果
E1//table[@class='wikitable']2
E2//table[contains(@class,'wikitable')]3
E3//table[@class='wikitable sortable']1

HTML 的 class 常常有好幾個詞,用「等於」很容易漏掉。E2 的 contains 比較保險。

包含就好:contains()

contains(@屬性, '文字') 的意思是「屬性裡有這段文字就算」。上面的 E2 就是這個寫法,連 wikitable sortable 也選到了,所以是 3 個。

它也可以用在 href 上。我想找所有網址裡有 Vickers 的連結:

Google 試算表公式
fx

抓網址裡含有 Vickers 的連結

=IMPORTXML(A1, "//a[contains(@href,'Vickers')]/@href")

來看看結果:

列C
1#Comparison_with_Vickers_scale
2https://en.wikipedia.org/wiki/Vickers_hardness_test

一個是頁面內跳到「Comparison with Vickers scale」那一段的連結,另一個是 Vickers 硬度試驗的條目。

取文字:text()

text() 取的是標籤「直接包著」的文字。莫氏硬度表格的第 2 欄是礦物名稱,每個名稱都包在 a 連結裡面。先不加 text(),直接選第 2 欄的儲存格:

Google 試算表公式
fx

抓硬度表第 2 欄的儲存格,名稱在連結裡面,會一併取到

=IMPORTXML(A1, "//table[contains(@class,'sortable')]//td[2]")

這樣會得到 10 列礦物名稱:

列C
1Talc
2Gypsum
3Calcite
4Fluorite
5Apatite

第 6 到 10 列依序是 Orthoclase feldspar、Quartz、Topaz、Corundum、Diamond。其中 Orthoclase 和 feldspar 在原始碼裡中間隔著換行標籤,IMPORTXML 把兩段直接接起來,第 6 列的值是 Orthoclasefeldspar,中間沒有空格。要用這欄去比對或查詢的話,先留意這一列。

改成 td[2]/text() 的話,名字不是 td 直接包著的,而是在 a 裡面,所以什麼都選不到:

Google 試算表公式
fx

td 底下沒有直接的文字,什麼都選不到

=IMPORTXML(A1, "//table[contains(@class,'sortable')]//td[2]/text()")

會得到 #N/A,點儲存格的提示是「匯入的內容空白。」。

要取文字就得往下寫到 a:td[2]/a/text()。這樣會得到 11 列而不是 10 列,因為 Orthoclase 和 feldspar 被換行標籤切成兩段文字,各占一列。所以沒有特別需求的話,我會直接選元素本身,不加 text()。

不管用哪一種,查詢寫完我都會用 COUNTA 或 ROWS 數一下結果筆數,看是不是自己預期的數字。

不會寫 XPath 的話

我自己寫 XPath 的流程是這樣的:在 Chrome 上對想抓的字按右鍵,選「檢查」,開發者工具會停在那個元素。再對它按右鍵,選「Copy」>「Copy XPath」,路徑就複製下來了。開發者工具也可以用 F12 或 Ctrl+Shift+I(Mac 為 Cmd+Option+I)打開。

貼進去之前要注意三件事:

  • Chrome 複製出來的 XPath 引號是雙引號,像 //*[@id="total"],放進公式要改成單引號。
  • 它常常給一長串從頭走到尾的絕對路徑,網頁一改版就斷。如果元素本身有 class 或 id,我會改成上面的 [@class=...] 或 contains 寫法,比較耐用。
  • 開發者工具顯示的是瀏覽器整理過的結構,路徑裡的 /tbody/ 常常是瀏覽器自己補的,伺服器送出的原始碼裡未必有。貼上後選不到東西時,先試著把 /tbody/ 拿掉。

抓不到的時候

IMPORTXML 讀的是伺服器回傳的 HTML,不會像瀏覽器那樣執行頁面上的 JavaScript。所以有幾種情況會抓不到:

  • 內容是 JavaScript 之後才填進去的。很多購物網站、股價頁面是這樣,瀏覽器看得到,原始碼裡卻沒有那個數字。
  • 要登入才看得到的頁面。公式沒有地方輸入帳號密碼。
  • 網站不讓 Google 的抓取程式進去。

判斷是哪一種,我會在 Chrome 開網頁後按 Ctrl+U(Mac 為 Cmd+Option+U)看原始碼,再用 Ctrl+F(Mac 為 Cmd+F)搜尋想抓的字。搜得到,表示伺服器有送,XPath 寫對就抓得到。搜不到,就是 JavaScript 填的,換 XPath 也沒用,要看看網站有沒有公開的資料下載或 API,需要自動化的話再考慮 Apps Script。

抓不到時的錯誤碼,常見是 #N/A,提示會告訴你是哪一種:XPath 選不到東西是「匯入的內容空白。」;網址不存在(404)是「在指定網址找不到資源。」。

抓公開網頁前,先看一下網站的使用條款,也可以在網址後面加 /robots.txt,看對方有沒有不讓機器人抓取的設定,有的話就不要抓。多久更新一次、同一份試算表放太多匯入函式會怎樣、為什麼不能用 NOW() 強迫更新(網址串上 NOW() 會得到 #ERROR!),這些寫在 網頁資料匯入函式 那篇,這裡不重講。

抓回來的文字常常夾著空格、符號或奇怪的格式,整理的方法接著看 整理文字資料 和 髒資料清理分工。

練習

1

排除目錄的標題

同一個 Mohs scale 頁面,//h2 會多抓到一個「Contents」。觀察原始碼,其他 8 個 h2 都有 id 屬性,Contents 那個沒有。請寫出只抓有 id 的 h2 的公式,網址放在 A1。

2

數表格的個數

請寫出公式,算出 class 裡有 wikitable 這個詞的表格共有幾個,網址放在 A1。

換一個你常看的公開網頁,試著抓抓看它的標題和連結吧!

我是喜特先生,Mr. Sheet,我們下個教學見!

分享:
#IMPORTXML#IMPORTHTML#XPath#網頁抓取
喜特先生 Mr. Sheet

喜特先生 Mr. Sheet

數據分析師/商業分析師

八年工作經驗,跨不同業界解決數據需求。做過的案例都整理在作品集。

接下來可以

這篇在技能樹的 Lv.3「資料整合與自動化」,模組「處理網頁資料」(第 1/1 篇)。讀完這篇,路線上的下一個模組是「AI 幫你清理資料」。

回到技能樹

相關文章

查看所有文章

留言討論

共 0 則留言

訂閱電子報,新文章上線就通知你

免費,隨時可取消。

送出即表示同意服務條款與隱私權政策。