Puppeteer 不重啓如何更換代理 IP

攝影:產品經理

豉油雞

我們知道,在寫爬蟲的過程中,如果總是使用同一個 IP,很容易就會被網站識別並封禁,所以需要使用代理 IP 並經常更換。

但如果你在網上搜索 Puppeteer 如何更換代理 IP,你會發現,網上的解決方案一般是這樣寫的:

const puppeteer = require('puppeteer');

(async() ={
  const browser = await puppeteer.launch({
    args: [ '--proxy-server=123.45.67.89:8888' ]
  });
  const page = await browser.newPage();
  await page.goto('http://httpbin.org/ip');
  await browser.close();
})();

這種寫法有一個問題,如果你要更換 IP,必須重啓爬蟲。那麼有沒有辦法不重啓爬蟲也能更換代理 IP 呢?

方法有,並且有兩個。

隧道代理

對一些網站來說,只要每次訪問的 IP 不一樣就可以避免被封禁,那麼我們可以使用隧道代理。隧道代理供應商會給我們提供一個唯一的域名和端口。我們把它設置爲爬蟲的代理就可以了。代理供應商會在後端自動給每一次請求更換 IP,不用我們來操心。

我們使用青果雲 [1] 的隧道代理來做演示。它可以免費試用 2 小時。我獲取到的代理 IP 地址爲:http://D5A913AF:B1DE2C46D321@tunnel.qg.net:11151。於是,我可以修改上面的 Puppeteer 代碼中的 IP 地址:

const puppeteer = require('puppeteer-core');

(async() ={
  const browser = await puppeteer.launch({
    args: [ '--proxy-server=tunnel.qg.net:11151' ], headless: false, executablePath: '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'});
  const page = await browser.newPage();
  await page.authenticate({username: '賬號', password: '密碼'});  // 如果代理沒有權限驗證,可以移除這一行
  response = await page.goto('http://httpbin.org/ip');
  console.log('第一次訪問: ', await response.text());
  response = await page.goto('http://httpbin.org/ip');
  console.log('第二次訪問: ', await response.text());
})()

運行效果如下圖所示:

動態按需修改代理 IP

IP 並不是換得越頻繁越好。如果網站需要登錄,那麼你登錄以後每一次請求都更換 IP,這反而會弄巧成拙,讓網站更加懷疑你是不是爬蟲。還有一些網站,例如淘寶,當你訪問一個頁面的時候,它會自動 301 跳轉多次。在這幾次跳轉的時候,你必須保持 IP 一致,否則它就會屏蔽你。

我們有時候需要實現按需更換代理 IP——讓開發者在需要更換 IP 的時候,再來更換。

爲了讓 Puppeteer 實現這個目標,我們可以安裝一個第三方模塊:puppeteer-page-proxy

npm i puppeteer-page-proxy

安裝完成以後,我們來使用看看:

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


puppeteer.launch({headless: false, executablePath: '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'}).then(
    async browser ={
        console.log('start...')
        const page = await browser.newPage()

        await useProxy(page, 'http://賬號:密碼@119.5.228.105:21477')
        console.log('change proxy success, start to visit url')
        resp = await page.goto('http://httpbin.org/ip')
        console.log(await resp.text())

        await useProxy(page, 'http://賬號:密碼@119.41.199.19:56214')
        console.log('change proxy success, start to visit url')
        resp = await page.goto('http://httpbin.org/ip')
        console.log(await resp.text())
        }
)

運行效果如下圖所示:

當我們需要更換 IP 的時候,只需要在代碼裏面執行await useProxy(page, 'http://賬號:密碼@IP:端口'),就可以更換新的 IP 了。如果你的代理 IP 沒有賬號密碼,那麼可以把代碼改成:await useProxy(page, 'http://IP:端口')

可能有人會問,你上面的示例代碼中,你是直接把代理填寫到代碼裏面的。如果我需要訪問某個 URL 來獲取新的代理怎麼辦呢?其實這也很簡單,你可以再安裝一個第三方模塊:axios用來發起網絡請求獲取新的代理 IP,然後再替換:

npm i axios

還是以青果雲的短效代理 IP 爲例,它可以提供一個接口,訪問接口後,你能得到一個有效期 5-15 分鐘的短效 IP,如下圖所示:

開通試用賬號以後,你可以獲得一個提取代理的 URL,類似於下面這樣:

https://proxy.qg.net/extract?Key=ABCDEFGH&Num=1&AreaId=&Isp=&DataFormat=txt&DataSeparator=%5Cn&Detail=0

訪問以後就能拿到代理 IP,如下圖所示:

現在,我們要在 Puppeteer 裏面,先訪問這個 URL 獲取代理,再把代理 IP 設置到 Puppeteer 中,然後再訪問目標網頁。對應的代碼如下:

const puppeteer = require('puppeteer-extra')
const useProxy = require('puppeteer-page-proxy')
const axios = require('axios')

async function set_proxy(page){
    resp = await axios.get('https://proxy.qg.net/extract?Key=ABCDEFG&Num=1&AreaId=&Isp=&DataFormat=txt&DataSeparator=%5Cn&Detail=0')
    proxy = 'http://賬號:密碼@' + resp.data
    console.log('獲取到的代理 IP 爲:', proxy)
    await useProxy(page, proxy)
}

puppeteer.launch({headless: false, executablePath: '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'}).then(
    async browser ={
        console.log('start...')
        const [page] = await browser.pages()
        await set_proxy(page)

        console.log('change proxy success, start to visit url')
        resp = await page.goto('http://httpbin.org/ip')
        console.log(await resp.text())
}
)

運行效果如下圖所示:

參考文獻

[1] 青果雲: https://www.qg.net/business/proxyip/42.html

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/6PtJtG0FVJV1mBG8eR0WJg