在我們開始之前,你需要遵守當地的法紀法規,不可隨意抓取未經允許公開的資料。
以下是本教學所需的一些東西:
Cheerio 是一個在Node.js 中解析HTML 和XML 的工具,在GitHub 上非常受歡迎,擁有超過23k 的star 。
它快速、靈活且易於使用。由於它實現了JQuery 的子集,如果你已經熟悉JQuery,那麼很容易開始使用Cheerio。
Cheerio 和Web 瀏覽器之間的主要區別在於,cheerio 不產生視覺渲染、載入CSS、載入外部資源或執行JavaScript。它只是解析標記並提供用於操作產生的資料結構的API。這就解釋了為什麼它也非常快——cheerio 文件。
如果你想使用cheerio 來抓取網頁,您需要先使用axios或node-fetch等套件來取得標記。
在此範例中,我們將抓取此Wikipedia 頁面上列出的所有國家和其他司法管轄區的ISO 3166-1 alpha-3 程式碼。它位於ISO 3166-1 alpha-3頁面的當前代碼部分下。
這是國家/司法管轄區清單及其相應代碼的樣子:
在此步驟中,您將透過在終端機上執行以下命令為您的專案建立目錄。該命令將創建一個名為learn-cheerio
. 如果你願意,你可以給它一個不同的名字。
mkdir learn-cheerio
learn-cheerio
成功執行上述指令後,您應該可以看到一個名為created 的資料夾。
在下一步中,您將在您喜歡的文字編輯器中開啟剛剛建立的目錄並初始化項目。
在此步驟中,您將導航至專案目錄並初始化專案。在您喜歡的文字編輯器中開啟您在上一個步驟中建立的目錄,並透過執行以下命令來初始化專案。
npm init -y
成功執行上述指令將package.json
在專案目錄的根目錄下建立一個檔案。
在下一個步驟中,您將安裝專案依賴項。
在此步驟中,您將透過執行以下命令來安裝專案依賴項。這將需要幾分鐘,所以請耐心等待。
npm i axios cheerio pretty
成功執行上述命令將在欄位package.json
下的檔案中註冊三個依賴項。 dependencies
第一個依賴是axios
,第二個是cheerio
,第三個是pretty
。
axios是一個非常流行的http 用戶端,可以在node 和瀏覽器中運作。我們需要它,因為cheerio 是一個標記解析器。
為了讓Cheerio 解析標記並抓取您需要的數據,我們需要axios
用於從網站取得標記。如果您願意,可以使用另一個HTTP 用戶端來取得標記。它不一定是axios
.
pretty是用於美化標記的npm 包,以便在終端上列印時可讀。
在下一部分中,您將檢查將從中抓取資料的標記。
在從網頁中抓取資料之前,了解頁面的HTML 結構非常重要。
在此步驟中,您將檢查要從中抓取資料的網頁的HTML 結構。
導覽至Wikipedia 上的ISO 3166-1 alpha-3 代碼頁面。在“當前代碼”部分下,有一個國家列表及其相應的代碼。 CTRL + SHIFT + I
您可以按chrome 上的組合鍵或右鍵單擊然後選擇「檢查」選項來開啟DevTools 。
這是我在chrome DevTools 中的清單:
在下一節中,您將編寫用於抓取網頁的程式碼。
在本節中,你將編寫用於抓取我們感興趣的資料的程式碼。首先執行以下將建立app.js
檔案的命令。
touch app.js
成功執行上述指令將app.js
在專案目錄的根目錄下建立一個檔案。
像其他Node 套件一樣,在開始使用它們之前,你必須先require axios
、 cheerio
和。你可以透過在剛剛創建pretty
的文件頂部添加下面的程式碼來做到這一點。 app.js
const axios = require("axios"); const cheerio = require("cheerio"); const pretty = require("pretty");
在我們編寫用於抓取資料的程式碼之前,我們需要學習cheerio
. 我們將解析下面的標記並嘗試操作生成的資料結構。這將幫助我們學習Cheerio 語法及其最常用的方法。
下面的標記是ul
包含我們元素的li
元素。
const markup = ` <ul class="fruits"> <li class="fruits__mango"> Mango </li> <li class="fruits__apple"> Apple </li> </ul> `;
將上述變數宣告加入app.js
檔案
cheerio
你可以使用該cheerio.load
方法載入標記。此方法將標記作為參數。它還需要另外兩個可選參數。如果你有興趣,可以在文件中閱讀有關它們的更多資訊。
下面,我們傳遞第一個也是唯一需要的參數,並將回傳值儲存在$
變數中。我們使用該變數是因為cheerio 與Jquery $
的相似性。如果你願意,可以使用不同的變數名。
將以下程式碼加入你的app.js
檔案:
const $ = cheerio.load(markup); console.log(pretty($.html()));
如果你現在透過在終端機上app.js
執行指令來執行檔案中的程式碼node app.js
,你應該可以在終端機上看到標記。這是我在終端機上看到的:
Cheerio 支援大多數常見的CSS 選擇器,例如class
、 id
和element
選擇器等。在下面的程式碼中,我們選擇帶有類別的元素fruits__mango
,然後將所選元素記錄到控制台。將以下程式碼加入你的app.js
檔案。
const mango = $(".fruits__mango"); console.log(mango.html()); // Mango
如果你使用指令執行,上述程式碼行將Mango
在終端機上記錄文字。 app.js``node app.js
您也可以選擇一個元素並取得特定屬性,例如class
、 id
或所有屬性及其對應值。
將以下程式碼加入你的app.js
檔案:
const apple = $(".fruits__apple"); console.log(apple.attr("class")); //fruits__apple
上面的程式碼將會登入fruits__apple
終端機。 fruits__apple
是所選元素的類別。
Cheerio 提供了.each
循環遍歷多個選定元素的方法。
下面,我們選擇所有元素並使用該方法li
循環遍歷它們。 .each
我們在終端機上記錄每個清單項目的文字內容。
將以下程式碼加入你的app.js
檔案。
const listItems = $("li"); console.log(listItems.length); // 2 listItems.each(function (idx, el) { console.log($(el).text()); }); // Mango // Apple
上面的程式碼會記錄2
,也就是清單項目的長度,執行完程式碼後會在終端機上顯示文字Mango
和。 Apple``app.js
Cheerio 提供了一種將元素附加或附加到標記的方法。
此append
方法會將作為參數傳遞的元素加入到所選元素的最後一個子元素之後。另一方面, prepend
將在選定元素的第一個子元素之前加入傳遞的元素。
將以下程式碼加入你的app.js
檔案:
const ul = $("ul"); ul.append("<li>Banana</li>"); ul.prepend("<li>Pineapple</li>"); console.log(pretty($.html()));
在新增和新增元素到標記之後,這是我登入$.html()
終端機時看到的內容:
這些是Cheerio 的基礎知識,可以幫助你開始網頁抓取。 要從Wikipedia 抓取我們在本文開頭描述的數據,請將以下程式碼複製並貼上到app.js
檔案中:
// Loading the dependencies. We don't need pretty // because we shall not log html to the terminal const axios = require("axios"); const cheerio = require("cheerio"); const fs = require("fs"); // URL of the page we want to scrape const url = "https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3"; // Async function which scrapes the data async function scrapeData() { try { // Fetch HTML of the page we want to scrape const { data } = await axios.get(url); // Load HTML we fetched in the previous line const $ = cheerio.load(data); // Select all the list items in plainlist class const listItems = $(".plainlist ul li"); // Stores data for all countries const countries = []; // Use .each method to loop through the li we selected listItems.each((idx, el) => { // Object holding data for each country/jurisdiction const country = { name: "", iso3: "" }; // Select the text content of a and span elements // Store the textcontent in the above object country.name = $(el).children("a").text(); country.iso3 = $(el).children("span").text(); // Populate countries array with country data countries.push(country); }); // Logs countries array to the console console.dir(countries); // Write countries array in countries.json file fs.writeFile("coutries.json", JSON.stringify(countries, null, 2), (err) => { if (err) { console.error(err); return; } console.log("Successfully written data to file"); }); } catch (err) { console.error(err); } } // Invoke the above function scrapeData();
透過閱讀程式碼,你了解正在發生的事情嗎?如果沒有,我現在將詳細介紹。我還對每一行程式碼進行了註釋,以幫助你理解。
在上面的程式碼中,我們需要檔案頂部的所有依賴項, app.js
然後我們宣告了scrapeData
函數。在函數內部,使用axios
. 然後將我們需要抓取的頁面的獲取HTML 加載到cheerio
.
國家/地區列表及其對應iso3
代碼嵌套在一個div
具有. 類的元素中plainlist
。 li
元素被選中,然後我們使用該方法循環遍歷它們.each
。每個國家的資料都被抓取並儲存在一個陣列中。
使用指令執行上述程式碼後node app.js
,將抓取的資料寫入countries.json
檔案並列印在終端機上。這是我在終端機上看到的部分內容:
感謝你閱讀這篇文章!我們已經介紹了使用cheerio
. 如果你想更深入地了解並完全了解其工作原理,可以前往Cheerio 文件。