Skip to content

rayc2045/ghibli-crawler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ghibli Crawler

Photo

Usage

Install Git and Node, then type in terminal:

$ git clone https://github.com/rayc2045/ghibli-crawler
$ cd ghibli-crawler
$ sh download.sh

If you don't use Brave browser, remember to change the executablePath in index.js to your Chromium browser file path, or directly replace the npm package "puppeteer-core" with "puppeteer" and remove the executablePath in index.js:

$ npm i puppeteer
// index.js
const puppeteer = require('puppeteer-core'); // Replace "puppeteer-core" with "puppeteer"

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser', // Remove this line

Awhile after running $ node index.js, all photos will be saved in the "img" folder. (321.9 MB)

Photo

Dev Log

最近對爬蟲感到興趣,幾天的研究發現 Puppeteer 這套由 Google 開源、使用無介面操作 Chrome 做自動化測試的 Node.js 函式庫也能用來爬取資料,因此決定使用 Node.js 搭配 Puppeteer 和 Axios (基於 promise 的 HTTP 庫),自動化將先前作品「吉卜力相簿」 上的一千多張作品劇照下載下來。

Puppeteer 可由 npm 進行安裝,如果電腦中有基於 Chromium 的瀏覽器,可下載容量較小的核心版本,之後再將啟動路徑設置為應用程式路徑即可 (範例使用 Brave 瀏覽器):

$ npm i puppeteer-core
const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser'
  });
})();

Puppeteer 的語法並不難,在官方文件中可找到許多範例;而其中因為大多自動化操作屬於非同步行為,需要另外使用 async/await 語法確保程式依序執行,算是比較需要注意的部分,較常用到的指令有:

const page = await browser.newPage();

const cookies = await page.cookies([...urls]); // 獲取此頁 cookies
await page.setCookie(cookieObject1, cookieObject2); // 設定 cookie
await page.setUserAgent(userAgent); // 設定 userAgent

const navbar = await page.$('.nav'); // 抓取單一元素
const links = await page.$$('a'); // 抓取複數元素

const title = await page.evaluate(() => 
  document.querySelector('#title').textContent.trim()); // 取得 title

const imageLinks = await page.evaluate(() =>
  [...document.querySelectorAll('img')].map(img => img.src)); // 取得圖片網址

await page.type('#email', 'example@gmail.com'); // 輸入
await page.click('.loginBtn'); // 點擊

// 單一元素截圖
const target = await page.$('img');
await target.screenshot({ path: `./img/example.png` });

// 整頁截圖
await page.screenshot({
  path: './img/screenshot.png',
  type: 'png',
  fullPage: true
  // clip: { x: 0, y: 0, width: 1920, height: 800 }
});

const url = await page.url(); // 當前網址
await page.reload(); // 重整頁面
await page.goBack(); // 上一頁
await page.goForward(); // 下一頁

await page.waitForNavigation(); // 等待頁面跳轉
await page.waitForSelector('.navSubmenu'); // 等待當前頁面 AJAX 元素

await page.waitForResponse(res =>
  res.url().match(encodeURIComponent(name)) && response.ok()); // 等待資料回應完成

await page.waitForFunction(() =>
  [...document.querySelectorAll('div[class="asset"]')].some(el =>
    el.textContent.includes('Assets Folder'))); // 等待功能完成

這次實作中遇到最大的問題是在大量下載圖片時,Node 端遇到的錯誤,原因由短時間內發出過多請求導致圖片下載失敗,透過加上 slowMo 參數,將自動化操作的速度減慢得以解決:

(node:15319) UnhandledPromiseRejectionWarning: Error: getaddrinfo ENOTFOUND www.ghibli.jp
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:67:26)
(Use `node --trace-warnings ...` to show where the warning was created)
const browser = await puppeteer.launch({
  executablePath: '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser',
  slowMo: 1200
});

完成初次爬蟲和自動化程序的過程中小有成就感,如果未來有需求,也許還會使用類似的方式做網頁轉 PDF、自動化登入操作,又或是定時爬完資料後結合寄信功能做 Email 通知吧!

文章同步刊載於 Medium