數據採集實戰(二)-- 京粉商品(by puppeteer)

1. 概述

京粉(https://union.jd.com/)是京東聯盟下的網站,通過分享其中的商品鏈接可以賺取佣金,類似淘客聯盟。

採集京粉的商品,既可以練習 puppeteer的使用,平時想在京東購物時,也能用得上(採集看看有類似商品的價格和評價)。

2. 主要流程

採集的流程很簡單:
image.png

2.1 登錄

登錄本來是很簡單的步驟,只是京粉的登錄有點特殊,它的登錄框是在 iframe 中,所以,加載完網頁後可能登錄框並沒有出現。
需要加載完 iframe 之後才能錄入用戶名/密碼。
image.png

登錄模塊的代碼如下:

const username = "YOUR NAME";
const passwd = "YOUR PASSWORD";

// 登錄
const login = async (page) => {
  await page.goto("https://union.jd.com/index");

  // 等待加載 login 的 iframe
  await page.waitForSelector("#indexIframe");
  const frame = (await page.frames())[1];

  await frame.waitForSelector("#loginname");
  // 輸入用戶名和密碼 登錄
  await frame.type("#loginname", username, { delay: 100 });
  await frame.type("#nloginpwd", passwd, { delay: 100 });
  await frame.click("#paipaiLoginSubmit");
};

export default login;

2.2 進入“商品檢索”菜單

登錄成功後,進入首頁,點擊左側的菜單進入“商品檢索”頁面。
image.png

注意這裏直接使用 page 的 click 方法是無效的,需要使用如下方式:

// 進入商品界面
const productPage = async (page) => {
  await page.waitForSelector(".menu-wrapper");

  // 直接選擇無法點擊,只能用 page.evaluate 方法來點擊
  // 【我要推廣】 菜單
  await page.evaluate(
    (selector) => document.querySelectorAll(selector)[0].click(),
    ".el-submenu__title>span"
  );
  
  // 【商品推廣】 菜單
  await page.evaluate(
    (selector) => document.querySelectorAll(selector)[1].click(),
    "li.el-menu-item>span"
  );
};

2.3 錄入檢索條件並開始檢索

商品推廣頁面支持的檢索條件很多,這裏只輸入佣金價格的範圍來檢索:

// 檢索商品(佣金比例範圍,價格範圍)
const searchProduct = async (page, feeMin, feeMax, priceMin, priceMax) => {
  await page.waitForSelector(".imgbox");

  await page.waitForSelector("input.el-input__inner");
  const inputs = await page.$$("input.el-input__inner");

  // IMPORTANT 使用click才能輸入完整,使用 focus,無法輸入完整
  await inputs[1].click();
  // await inputs[1].focus();
  await inputs[1].type(feeMin, { delay: 200 });
  await inputs[2].click();
  await inputs[2].type(feeMax, { delay: 200 });
  await inputs[3].click();
  await inputs[3].type(priceMin, { delay: 200 });
  await inputs[4].click();
  await inputs[4].type(priceMax, { delay: 200 });

  // 佣金和價格輸入之後,鼠標必須浮在輸入框上,纔會出現確定按鈕去檢索
  const divs = await page.$$(".commission");
  // div對應的確認按鈕在隱藏的 div中
  let popover = await divs[1].evaluate((node) =>
    node.getAttribute("aria-describedby")
  );

  // 通過 hover()函數,讓確定按鈕顯示出來
  await inputs[4].hover();
  await page.waitForSelector(`#${popover}`, { visible: true });
  await page.click(`#${popover}>.el-button--primary`);
};

export default searchProduct;

佣金的範圍(feeMinfeeMax),價格範圍(priceMinpriceMax)是通過參數傳入的。

image.png

2.4 保存網頁

保存網頁很簡單,**puppeteer **提供了獲取整個HTML頁面的接口。

// 保存網頁內容到指定路徑
const savePage = async (page, dirname, filename) => {
  const html = await page.content();
  await saveContent(dirname, filename, html);
};

// 保存解析後的網頁內容到指定路徑
const saveContent = async (dirname, filename, content) => {
  if (!mkdirsSync(dirname)) {
    console.error("mkdir save page dir ERROR!");
    return;
  }

  fs.writeFileSync(path.join(dirname, filename), content);
};

2.5 進入下一頁

在頁面的最下方有翻頁的按鈕,只要找到下一頁的按鈕即可。
image.png
點擊下一頁的函數如下:

// 進入下一頁
const nextPage = async (page) => {
  await page.waitForSelector(".el-pagination");
  const pageBottons = await page.$$(".el-pagination>button");
  // pageBottons[0] -> 上一頁   pageBottons[1] -> 下一頁
  await pageBottons[1].click();
  await page.waitForNavigation();
};

export default nextPage;

3. 運行效果

jinfen.gif

4. 總結

以上通過 puppeteer 採集京粉商品數據的實戰中,技術要點主要有:

  1. 加載 iframe 並自動登錄
  2. 點擊menu 菜單遷移到商品頁面
  3. 在文本框中輸入檢索條件
  4. 自動翻頁

5. 注意事項

爬取數據只是爲了研究學習使用,本文中的代碼遵守:

  1. 如果網站有 robots.txt,遵循其中的約定
  2. 爬取速度模擬正常訪問的速率,不增加服務器的負擔
  3. 只獲取完全公開的數據,有可能涉及隱私的數據絕對不碰
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章