【发布时间】:2020-03-18 02:24:51
【问题描述】:
TLDR;是否可以在使用 JS 函数和 location.href() 或 window.open() 在 JS 和/或 Puppeteer 中打开新页面的可点击链接上获取重定向 URI,而无需实际点击链接?强>
[编辑] 在发布此问题时发现此Puppeteer get request redirects,但它要求我首先“单击”链接并检查响应标头,并且我试图在没有单击的情况下获取值,我认为这应该是可能的......
我正在使用 Puppeteer 构建一个站点爬虫,我通过实际“单击”(模拟)页面上的每个链接来实现它,而不是仅仅扫描页面以查找 a.href 标记并获取指示的 URI。
我当然使用递归和 async/await 并且对这种编程范式相当陌生,但我似乎取得了不错的进展。这是我在“点击”期间返回的每个页面上调用的主要函数...
async function crawl(page) {
const url = await page.url();
// kick out already processed pages
if (crawled_pages.has(url)) {
CURRENT_DEPTH--;
return false;
}
// scrape all rendered <a> links off page
let page_alinks = await page.$$("a");
// kick out of recursion if we dont find any links on the page...
if (page_alinks.length === 0) return false;
console.log("[ " + url + " ] links found: " + page_alinks.length);
// var data = await page.$eval('a[href|="data:text"]', el => el.href);
crawled_pages.set(url, page);
// now add each of the links to a mapped collection using the concatted text and link
// values as the key and the link node as the value
for (let click_node of page_alinks) {
let href_value = await (await click_node.getProperty('href')).jsonValue();
let text_value = await (await click_node.getProperty('text')).jsonValue();
let redir_value = "";
request({url: href_value, followRedirect: false}, function (err, res, body) {
redir_value = res.headers.location;
});
if (debug) {
console.log("text = " + text_value);
console.log("href = " + href_value);
console.log("redir= " + redir_value);
}
// track how deep into the recurse are we
click_node.depth = CURRENT_DEPTH + 1;
click_node.redir = redir_value;
if (qued_clickable_links.store_link(text_value, href_value, click_node)) {
if (debug) console.log("storg link [ " + text_value + "`" + href_value + " ]");
} else {
if (debug) console.log("rejecting link [ " + text_value + "`" + href_value + " ]");
}
}
// loop the clickable links
let clicknode = null, next_page = null;
while ((clicknode = qued_clickable_links.pop()) === true) {
(async () => {
const newPagePromise = getNewPageWhenLoaded();
await clicknode.click({delay: 1000});
next_page = await newPagePromise;
})();
next_page.depth = CURRENT_DEPTH + 1;
CURRENT_DEPTH++;
let rv = await crawl(next_page);
}
CURRENT_DEPTH--;
return true;
};
我通过构建其他基于非 Puppeteer 的爬虫的经验了解到重定向链接是一个问题,因为您必须使用初始 href URI 值和最终 URI 来跟踪每个可点击链接,因为您不希望要重复任何抓取,您应该在将这些值提交到 qued_clickable_links Map() 之前知道这些值。
因此,使用此代码块将为我提供重定向的 URI但仅限于基于非 JavaScript 的 href 值,而不是页面上的每个可点击链接...
const request = require('request');
let redir_value = "";
request({url: href_value, followRedirect: false}, function (err, res, body) {
redir_value = res.headers.location;
});
例如,对于底部https://krksol-miraclebust.com 上的链接之一,与text=TERMS & CONDITIONS 的链接的给定值是href=javascript:void(0) 将这些值作为href_value 放入上述函数中只会给我一个错误!这使得该功能对于我想要实现的功能相对毫无价值。
这样做的重点是通过点击链接来抓取网站,而不仅仅是扫描页面,所以我需要一个重定向功能来理解这一点并为我提供价值就像我点击了链接
【问题讨论】:
-
我的两个想法是 1. 捕获 URL 并在 Puppeteer 的上下文之外对其进行 ping 操作,并检查那里的标题。您可以使用 axios 在 Node 环境中执行此操作。 2.复制初始href值,传回Node运行时,然后在新的pptr浏览器实例中打开url,记录去哪里。
-
hmmm 那么 axios 方法的资源密集程度如何?它真的会启动浏览器并呈现页面并抓取标题吗?至于第二个,这当然是蛮力的方式来做到这一点,但我真的在寻找(如果它存在的话)一种无需在初始 uri 上进行全面渲染即可获得该值的方法。也,就像你还在想我实际上有一个href!这就是重点……这些“链接”具有 void() href 值,并且仅由单击事件呈现:)
-
“这些“链接”具有 void() href 值,并且仅由单击事件呈现”-因此您需要单击它们,或者抓取该页面上的 JS……听起来很困难。
标签: javascript node.js redirect web-crawler puppeteer