目的是實現用puppeteer實現登陸流程自動化,把登陸後獲取到的合法cookies傳輸給node端,實際大量抓取數據則使用request,提升抓取性能和可靠性。javascript
首先,給request默認參數中添加jar屬性:java
const cookieJar = request.jar() const rp = request.defaults({ jar: cookieJar, ... // 其它request默認參數 })
這樣,使用這個rp對象就會使用這個cookieJar對象來儲存從響應中解析出的cookies,也能夠經過操做cookieJar對象來增刪改查單個cookienode
經過puppeteer從瀏覽器獲取cookiesgit
const cookies = await page.cookies()
這裏的cookies是個普通javascript對象的數組,每一個元素中包含name, value, domain, path, expires, httpOnly, secure等屬性github
將瀏覽器獲取的cookies填充到cookieJar中
這個步驟值得重點說道說道:npm
npm install tough-cookie@x.x.x
安裝特定版本cookies.forEach(json => { const { name, domain } = json json.key = name json.expires = json.expires > 0 ? new Date(json.expires * 1000) : 'Infinity' const cookie = Cookie.fromJSON(json) cookieJar.setCookie(cookie, 'https://' + domain) })
這裏的麻煩是request包裝後的cookie操做方法並不全面,好比我發現沒法用cookieJar.getCookies()這個方法獲取到'.xxxx.com'這樣的domain下的cookies,所以只好本身經過分析源碼,寫了下面這個方法來一次性獲取cookieJar中的全部cookie對象json
async function allCookies (jar) { const store = jar._jar.store return (await Promise.all(Object.keys(store.idx).map(d => util.promisify(store.findCookies).call(store, d, null)))).flat() }
注意:api
而後就能夠簡單的把Cookie對象轉換爲puppeteer接受的普通js對象了數組
const cookies = await allCookies(cookieJar) cookies = cookies.map(c => ({ ...c, expires: c.expires instanceof Date ? c.expires.getTime() / 1000 : -1, name: c.key })) await page.setCookie.apply(page, cookies)
由於Page.setCookie接受的是變長參數而不是數組,所以用apply來調用瀏覽器