如何通过 puppeteer 欺骗 Instagram 认为我使用的是移动设备?

How to trick Instagram into thinking that I use a mobile device using puppeteer?

基本上我想做的是一个可以同时在多个不同社交媒体上发帖的应用程序。我没有时间尝试 reverse-engineer Instagram API 而且我认为我没有足够的能力去做这件事,所以我决定使用 puppeteer(像 phantomjs 这样的无头浏览器) .

问题是,我需要 Instagram 的移动版本才能上传照片。 我试图更改用户代理。当我在常规 chrome 中更改它时,一切正常,并且我获得了该网站的移动版本。但是当我用 puppeteer 尝试同样的事情时,我得到了 PC 版本。 这是更改用户代理的代码:

await page.setExtraHTTPHeaders({
   'User-Agent': 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
});

也许是这段代码的问题,但是当我在浏览器中查看headers时一切正常。用户代理是我需要的。 也许问题出在 Instagram 本身,我不知道。看起来 Instagram 拒绝相信这些请求来自移动设备。 我很困惑。

这里是代码的完整版本:

const puppeteer = require('puppeteer');
const jsonfile = require('jsonfile');
const fs = require('fs');

const username = 'MYUSERNAME';
const password = 'MYPASSWORD';

async function main(username, password) {
    const browser = await puppeteer.launch({  // launch browser
        headless: false,
        args: [
            `--window-size=${250},${600}`, 
            `--use-fake-ui-for-media-stream`
        ],
        defaultViewport: null
    });

    const page = await browser.newPage();
    await page.setExtraHTTPHeaders({
        'User-Agent': 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
    });

    await page.goto('https://instagram.com', { waitUntil: 'networkidle0', timeout: 0 }); // wait until page load

    console.log("Trying to log in");
    const inputs = await page.$$('.f0n8F input');    
    await inputs[0].type(username);
    await inputs[1].type(password);
    
    await Promise.all([     
        page.click('.L3NKy'),
        page.waitForNavigation({ waitUntil: 'networkidle0' }),
    ]);

    //await browser.close();
    await console.log("Done!");
}

main(username, password);

非常感谢每一位能提供一点帮助的人

最接近模拟真实移动设备的是使用 puppeteer.devices with page.emulate。这与直接从 chrome DevTools 模拟设备时获得的体验相同。用户代理不需要再设置,在DeviceDescriptors中设置。

也可以在 DeviceDescriptors 的来源中查看可用设备列表。

例如:

const puppeteer = require('puppeteer');
const iPhone = puppeteer.devices['iPhone 6'];

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.emulate(iPhone);
  await page.goto('https://instagram.com', { waitUntil: 'networkidle0', timeout: 0 }); // wait until page load

  // do stuff
  await browser.close();
})();

仅供参考: 我很确定 instagram 不鼓励网页抓取,因为它 doesn't allow reverse engineering of their api 也不鼓励。您会发现自己很容易被网站禁止。因此,请确保您完全了解自己的选择。