1

我正在尝试使用 PuppeteerCrawler 抓取我们本地的 Confluence 安装。我的策略是先登录,然后提取会话 cookie 并在起始 url 的标题中使用它们。代码如下:

首先,我“步行”登录以提取相关凭据:

const Apify = require("apify");

const browser = await Apify.launchPuppeteer({sloMo: 500});
const page = await browser.newPage();
await page.goto('https://mycompany/confluence/login.action');

await page.focus('input#os_username');
await page.keyboard.type('myusername');
await page.focus('input#os_password');
await page.keyboard.type('mypasswd');
await page.keyboard.press('Enter');
await page.waitForNavigation();

// Get cookies and close the login session
const cookies = await page.cookies();
browser.close();
const cookie_jsession = cookies.filter( cookie => {
    return cookie.name === "JSESSIONID"
})[0];
const cookie_crowdtoken = cookies.filter( cookie => {
    return cookie.name === "crowd.token_key"
})[0];

然后我使用准备好的请求标头构建爬虫结构:

const startURL = {
    url: 'https://mycompany/confluence/index.action',
    method: 'GET',
    headers:
    {
        Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7',
        Cookie: `${cookie_jsession.name}=${cookie_jsession.value}; ${cookie_crowdtoken.name}=${cookie_crowdtoken.value}`,
    }
}

const requestQueue = await Apify.openRequestQueue();
await requestQueue.addRequest(new Apify.Request(startURL));
const pseudoUrls = [ new Apify.PseudoUrl('https://mycompany/confluence/[.*]')];

const crawler = new Apify.PuppeteerCrawler({
    launchPuppeteerOptions: {headless: false, sloMo: 500 },
    requestQueue,
    handlePageFunction: async ({ request, page }) => {

        const title = await page.title();

        console.log(`Title of ${request.url}: ${title}`);
        console.log(page.content());

        await Apify.utils.enqueueLinks({
            page,
            selector: 'a:not(.like-button)',
            pseudoUrls,
            requestQueue
        });

    },
    maxRequestsPerCrawl: 3,
    maxConcurrency: 10,
});

await crawler.run();

足部登录和 cookie 提取似乎没问题(“卷曲”请求完美运行),但 Confluence 不接受通过 puppeteer / headless chromium 登录。似乎标题以某种方式丢失了..

我究竟做错了什么?

4

1 回答 1

2

在不首先详细说明为什么标题不起作用的情况下,我建议gotoFunctionPuppeteerCrawler选项中定义一个自定义,例如:

{
    // ...
    gotoFunction: async ({ request, page }) => {
        await page.setCookie(...cookies); // From page.cookies() earlier.
        return page.goto(request.url, { timeout: 60000 })
    }
}

这样,您无需进行解析,cookie 将在每个页面加载之前自动注入浏览器。

需要注意的是,在使用无头浏览器时修改默认请求标头不是一个好习惯,因为它可能会导致某些站点将接收到的标头与已知浏览器指纹列表相匹配。

更新:

以下部分不再相关,因为您现在可以使用Request该类按预期覆盖标题。

标头问题是一个复杂的问题,涉及Puppeteer 中的请求拦截这是 Apify SDK 中相关的 GitHub 问题。不幸的是,通过Request对象覆盖标头的方法目前在 中不起作用PuppeteerCrawler,所以这就是您不成功的原因。

于 2019-02-26T12:32:27.263 回答