1. 程式人生 > >使用Puppeteer進行數據抓取(四)——圖片下載

使用Puppeteer進行數據抓取(四)——圖片下載

path con encode 內容 and Go size 分享圖片 IT

大多數情況下,圖片獲取並不是很困難的事情,獲取圖片的url,然後模擬瀏覽器請求即可。但是,有的時候這種方法往往無法生效,常見的情形有:

  1. 動態圖片,每次獲取都是一個新的,例如圖片驗證碼,重新獲取時是一個新的驗證碼圖片,已經失去了效果了。
  2. 動態上下文,有的網站為了反爬蟲,獲取圖片時要加上其動態生成的cookie才行。

這些情況下,使用puppeteer驅動chrome瀏覽器能看到圖片,但獲取url後單獨請求時,要麽獲取到的圖片無效,要麽獲取不到圖片。本文這裏就簡單的介紹下一些十分通用且有效的下載這些圖片的方法。

截圖:

截圖是一種非常簡單除暴的方法,大多數的時候也是最方便有效的。特別是對於驗證碼之類的動態生成的圖片,這些驗證碼獲取原始圖片往往需要一定時間的分析,但chrome能直接截取渲染後生成的圖片,直接跳過了分析過程,十分方便。

這裏以專利檢索及分析網為例,截取它登陸的驗證碼。

  技術分享圖片

首先用devtool分析其selector path。

發現其為"#codePic",接下來的操作就非常簡單了

await page.goto(‘http://www.pss-system.gov.cn/sipopublicsearch/portal/uiIndex.shtml‘);

const image = await page.waitForSelector(‘#codePic‘);
await image.screenshot({
path:
驗證碼.png‘,
omitBackground: false

});

這裏用的並不是page.screenshot,因為那樣對整個頁面截圖了,而是首先獲取驗證碼圖片的ElementHandle,然後調用ElementHandle.screenshot只對該元素截圖。

這種方式非常簡單有效,但由於是通過渲染的方式獲取的數據,還是丟失了原始信息的,例如,svg圖片就丟失了矢量信息了。

從緩存中讀取

另外一種思路是直接從chrome緩存中的數據讀取圖片數據,就像chrome dev tool的source tab中的那樣

  技術分享圖片

這個功能在puppeteer中並沒有封裝,在dev protocol中是有的,它主要涉及到如下兩個api:

Page.getResourceTree

它可以用來獲取資源樹,就像上圖左邊所示:

Page.getResourceContent

它可以用來獲取資源內容,它需要兩個參數,frameid和url。frameid可以從page中獲取,url必須是前面getResourceTree中獲取的url。

雖然puppeteer沒有封裝這兩個函數的功能,但還是有一個私有接口page._client.send可以發送原始dev protocol指令。這裏我們可以簡單的封裝一下:

async function getResourceTree(page) {
var resource = await page._client.send(‘Page.getResourceTree‘);
return resource.frameTree;
}

const assert = require(‘assert‘);
async function getResourceContent(page, url) {
const { content, base64Encoded } = await page._client.send(
‘Page.getResourceContent‘,
{ frameId: String(page.mainFrame()._id), url },
);
assert.equal(base64Encoded, true);
return content;
};

此時就說明我們可以利用前面的api獲取該圖片了。

const fs = require(‘fs‘);

await page.waitForSelector(‘#codePic‘);
const url = await page.$eval(‘#codePic‘, i => i.src);
const content = await getResourceContent(page, url);
const contentBuffer = Buffer.from(content, ‘base64‘);
fs.writeFileSync(
驗證碼.png‘, contentBuffer, ‘base64‘);

這種方式並不限於只獲取圖片,也可以獲取原始的js,svg之類的資源。

使用Puppeteer進行數據抓取(四)——圖片下載