pupppeteer-page-proxy每個頁面或請求獨立使用代理

1 pupppeteer-page-proxy模塊簡介

puppeteer代理設置方法中介紹了設置代理的幾種方式,其中之一是通過攔截請求,再通過http模塊轉發,給http模塊加上代理實現代理設置。pupppeteer-page-proxy[1]nodejs模塊就是基於此實現爲每個請求或page加代理。其中一些特性如下:

  • 支持每個page或每個請求使用代理。
  • 內部處理cookie。
  • 支持http、https、socks4、socks5 代理。

2 環境準備

需要三個工具:

  • puppeteer 2.1.1
  • pupppeteer-page-proxy 1.2.3
  • nodejs 10+

由於pupppeteer-page-proxy設置代理依賴http-proxy-agent、https-proxy-agent。這兩個模塊又依賴agent-base。agent-base需要5.0+。而puppeteer2.1.0纔將agent-base升級到5.1.1。因此puppeteer版本要使用5.1.1。

pupppeteer-page-proxy發送http請求依賴got[2](一個強大的nodejs http庫)。用高版本時got會使用asyn generator因此nodejs版本要升級到10+。否則啓動提示語法錯誤。

3 使用pupppeteer-page-proxy

首先我們爲每個請求指定代理。在page.on監聽請求,隨後通過page proxy發送。以訪問百度爲例,僅當url包含baidu時才使用代理。當打開頁面後,我們查詢ip會發送訪問百度的ip爲代理ip。而訪問bing時則不會對請求增加代理。

const puppeteer = require('puppeteer');
const useProxy = require('puppeteer-page-proxy');

(async () => {
    const browser = await puppeteer.launch({
        args: [
            '--disable-setuid-sandbox',
            '--no-sandbox',
            '--ignore-certificate-errors',
            '--remote-debugging-port=9222',
            '--disable-web-security'
        ],
        ignoreHTTPSErrors: true,
        headless: false,
        executablePath: "path"
    });
    const proxy = 'http://username:password@domain:port';
    const page = await browser.newPage();
    await page.setUserAgent('baiduSpider');
    await page.setRequestInterception(true);
    page.on('request', req => {
        if(req.url().indexOf('www.baidu.com/') > -1) {
            useProxy(req, proxy);
        } else {
            req.continue();
        }
    });
    await page.goto('https://www.baidu.com');
})();

接着爲page增加代理。這是將上面的例子稍作修改。不需要在手動設置攔截,監聽請求。page-proxy對於page請求攔截設置會在方法內部完成。

    useProxy(page,proxy);
    await page.goto('https://www.baidu.com');

4 注意事項

4.1 data-uri數據請求

一個頁面內部通常會有如下形式的標籤。data-src部分指定了一段base64編碼來顯示圖片。這稱作data-uri[3],即在頁面內部嵌入一段數據作爲請求結果。

    <img id="id_p" class="id_avatar sw_spd" 
    style="display:none" 
    aria-hidden="true" 
    alt="" 
    aria-label="個人資料圖片" onerror="FallBackToDefaultProfilePic(this)" 
    data-src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7" data-alt="" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7" data-bm="17">

通過chrome 調試面板查看網絡請求,url如下所示。
在這裏插入圖片描述
got遇到這種請求會產生錯誤。因此需要改造page-proxy,將這類請求交給瀏覽器處理即可。

Unsupported protocol "data:" 異常

Error: UnsupportedProtocolError: Unsupported protocol "data:"
    at request (/Users/sunfei/WebstormProjects/jsDebug/node_modules/puppeteer-page-proxy/src/lib/request.js:43:19)

4.2 代理請求超時控制

由於最終請求通過got發送,page-proxy1.2.3未提供got超時設置。因此這部分需要獨立升級,對外暴露got的設置接口。

        const response = await got(url,{
            headers: {
                'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/82.0.4085.12 Safari/537.36"
            },
            agent: {
                http:proxyAgent,
                https:proxyAgentHttps
            },
            timeout:1000    //超時設置

        });

4.3 代理ip查詢

page-proxy提供了一個使用代理後ip地址查詢,其實就是通過請求一個ip查詢接口實現。但默認是一個國外網站。我們在國內使用存在打不開的情況。因此需要進行改造。

const lookup = async (page, 
lookupService = "ip查詢服務地址", 
isJSON = true, timeout = 30000) => {

5 總結

page-proxy是一個很小巧的puppeteer page/request代理庫,基於攔截轉發思路實現,很簡介。但存在一些問題,如超時控制,代理ip查詢。實際使用過程中可在此基礎上二次開發使用即可。

6 參考

[1]pupppeteer-page-proxy,https://www.npmjs.com/package/puppeteer-page-proxy
[2]got,https://www.npmjs.com/package/got
[3]https://developer.mozilla.org/zh-CN/docs/Web/HTTP/data_URIs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章