iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 24
0
AI & Data

Puppeteer 簡單快速建立自己的 Nodejs 爬蟲系列 第 24

Day 24 爬蟲範例-中央社-每個子項(類lazy load)

今天就繼續每個分類的子項目吧


我們先檢查子項目有甚麼?

乍看之下只是普通標題
但是在更下面有"看更多內容"
點下去後就可以擷取更多標題
在這邊就可以用到puppteer的功能 page.tap()
今天就先來解決這問題

我們先新增一個class類別,儲存上次的分類物件

class Category {
  name: string;
  href: string;
  constructor(name: string, href: string) {
    this.name = name;
    if (name === "" && href === undefined) return;
    this.href = href;
  }
}

接著我們修改上次的 getCategory 方法,把 Object 都改為 Category

async function getCategory(body: string): Promise<Array<Category>> {
  let $ = await cheerio.load(body);
  let data: Array<Category> = [];
  await $(
    "div header div div div #pnProductNav #pnProductNavContents ul.main-menu li"
  ).each((i: number, el: any) => {
    let name: string = $(el).find("a.first-level").text();
    let href: string = $(el).find("a.first-level").attr("href");
    if (name === "" && href === undefined) return;
    //新增物件
    let tmp = new Category(name, href);
    data.push(tmp);
  });
  return data;
}

我們再新增一個方法,負責處理子項目的資料 getCategorySubPost

async function getCategorySubPost(data: Array<Category>, page: any) {
}

這裡我們就在Main方法上加入這方法,並把data和page傳入(記得把data的object也改為Category

let data: Array<Category> = await getCategory(body);
await getCategorySubPost(data, page);

接著我們循環每個data物件
把用page轉跳到每個page

for (let index = 0; index < data.length; index++) {
    const element = data[index];
    await page.goto(element.href);
    //等待頁面載入到頁尾的footerlet end = true;
    while (end){
      try {
        await page.waitFor(2000);
        await page.tap(
          "body div.list div#scrollable.scrollable div.container div.listContent div.wrapper div.centralContent div.statement a#SiteContent_uiViewMoreBtn"
        );
      } catch (error) {
        end = false;
      }
    }
    await page.waitForSelector("footer");
}

接著我們得針對"看更多內容"做點選

await page.tap(
"body div.list div#scrollable.scrollable div.container div.listContent div.wrapper div.centralContent div.statement a#SiteContent_uiViewMoreBtn"
);
//我們先測試一個
break;

先跑跑看

npm run start

結果看的出他的確點選到我們要的元素
但我們不知道他的最後一次出現是甚麼時候
我們可以用try catch去包他
因為page.tap()這個方法,只能在元素可看見時才能處理
所以看不到就會報錯

所以我們把他改成 while回圈,再抓到不到元素時跳出

let end = true;
    while (end){
      try {
      //等待幾秒不要一次抓太快,雖然這裡是已經預先載入了,不會增加server負擔
      //但能增加每頁切換的速度
        await page.waitFor(2000);
        await page.tap(
          "body div.list div#scrollable.scrollable div.container div.listContent div.wrapper div.centralContent div.statement a#SiteContent_uiViewMoreBtn"
        );
      } catch (error) {
        end = false;
      }
    }

那我們再來

npm run start

就可以看到他完美的跑完我們的要求了


那下一篇再來抓資料吧
我們結果預計會用vue-cli做出一個可以顯示的畫面


上一篇
Day 23 爬蟲範例-中央社(練習使用typescript)
下一篇
Day 25 爬蟲範例-中央社-繼續
系列文
Puppeteer 簡單快速建立自己的 Nodejs 爬蟲25

尚未有邦友留言

立即登入留言