使用 Puppeteer,如何在不必实际单击 link 并加载页面的情况下获取最终的重定向 URI?
Using Puppeteer, how to get the final redirect URI without having to actually click the link and load the page?
TLDR;是否可以在使用 JS 函数和 location.href() 或 window.open() 的可点击 link 上获取重定向 URI,以在 JS and/or Puppeteer 中打开新页面无需实际单击 link?
[编辑]
在发布此问题时发现此 ,但它要求我首先 "click" link 并检查响应 header,我试图在不单击的情况下获取值,我认为应该是可能的...
我正在使用 Puppeteer 构建一个站点爬虫,我通过在页面上实际 "clicking"(模拟)每个 link 而不是仅仅扫描页面以查找 a.href标记并获取指示的 URI。
我当然在使用递归 async/await 并且对这种编程范例还很陌生,但我似乎取得了不错的进步。这是我在 "click"...
期间返回的每个页面上调用的主要函数
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;
};
我通过构建其他基于 non-Puppeteer 的重定向 link 爬虫的经验了解到这是一个问题,因为您必须使用初始 href URI 跟踪每个可点击的 link值和最终 URI,并且由于您不想重复任何爬网,因此在将它们提交给 qued_clickable_links Map().
之前,您应该知道这些值
因此,使用此代码块会给我重定向的 URI ,但仅限于基于 non-Javascript 的 href 值,而不是页面上每个可点击的 link ...
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
上的 link 之一,link 和 text=TERMS & CONDITIONS
的给定值是 href=javascript:void(0)
将这些值作为 href_value
放入上述函数只会给我一个错误!这使得该功能对于我想要实现的目标来说相对毫无价值。
这一切的重点是通过单击 link 来抓取网站,而不仅仅是扫描页面,所以我需要一个重定向功能来理解这一点并给我值 as如果我点击 link
恐怕这是您需要以特殊方式处理以构建真正的站点爬虫的情况之一。我认为会有更多这样的案例,所以我认为您的实施应该更加复杂。一般来说,这是一个很大的话题,但我希望你能提供一些见解。
网站上可能有几种不同类型的 link 和重定向。其中一些是:
- links 到另一个网站
- links 到您网站的另一个页面
- link秒下载一个文件
- links 发送电子邮件
- links 到位于同一页面上的锚点
- links 到另一个页面上的锚点
可能我错过了一些,当然我没有提到通过执行 JS 函数进行的重定向,因为这是您遇到的困难 (href="javascript:void(0);"
)
因此,我建议将所有 link 保留为结构化 class 的对象,而不仅仅是 link 的集合。实际上我认为你这样做了,至少这个方法 qued_clickable_links.store_link()
是这样建议的。但是,查看该方法接受的参数,我认为这可能还不够。 class 应包含如下信息:
- 是否重定向URL是否
- 如果它包含完整路径或仅包含相对路径
- 是否在新版本中打开window/tab
只有这样,您才能管理您在旅途中遇到的所有类型和问题。
但是回到在这种特殊情况下不点击它就获得 link 的问题——我很确定唯一合理的解决方案是解析 onclick
函数以提取第一个参数它的意思是要加载的资源的URL。我在解析字符串方面已经足够好了,所以我不会为您提供任何好的实现。你可以这样得到onclick
函数的字符串:
var selector = 'body > div:nth-child(3) > div.footer__block.footer-menu > div:nth-child(3) > a';
$(selector)[0].onclick.toString();
希望对您有所帮助。
TLDR;是否可以在使用 JS 函数和 location.href() 或 window.open() 的可点击 link 上获取重定向 URI,以在 JS and/or Puppeteer 中打开新页面无需实际单击 link?
[编辑]
在发布此问题时发现此
我正在使用 Puppeteer 构建一个站点爬虫,我通过在页面上实际 "clicking"(模拟)每个 link 而不是仅仅扫描页面以查找 a.href标记并获取指示的 URI。
我当然在使用递归 async/await 并且对这种编程范例还很陌生,但我似乎取得了不错的进步。这是我在 "click"...
期间返回的每个页面上调用的主要函数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;
};
我通过构建其他基于 non-Puppeteer 的重定向 link 爬虫的经验了解到这是一个问题,因为您必须使用初始 href URI 跟踪每个可点击的 link值和最终 URI,并且由于您不想重复任何爬网,因此在将它们提交给 qued_clickable_links Map().
之前,您应该知道这些值因此,使用此代码块会给我重定向的 URI ,但仅限于基于 non-Javascript 的 href 值,而不是页面上每个可点击的 link ...
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
上的 link 之一,link 和 text=TERMS & CONDITIONS
的给定值是 href=javascript:void(0)
将这些值作为 href_value
放入上述函数只会给我一个错误!这使得该功能对于我想要实现的目标来说相对毫无价值。
这一切的重点是通过单击 link 来抓取网站,而不仅仅是扫描页面,所以我需要一个重定向功能来理解这一点并给我值 as如果我点击 link
恐怕这是您需要以特殊方式处理以构建真正的站点爬虫的情况之一。我认为会有更多这样的案例,所以我认为您的实施应该更加复杂。一般来说,这是一个很大的话题,但我希望你能提供一些见解。
网站上可能有几种不同类型的 link 和重定向。其中一些是:
- links 到另一个网站
- links 到您网站的另一个页面
- link秒下载一个文件
- links 发送电子邮件
- links 到位于同一页面上的锚点
- links 到另一个页面上的锚点
可能我错过了一些,当然我没有提到通过执行 JS 函数进行的重定向,因为这是您遇到的困难 (href="javascript:void(0);"
)
因此,我建议将所有 link 保留为结构化 class 的对象,而不仅仅是 link 的集合。实际上我认为你这样做了,至少这个方法 qued_clickable_links.store_link()
是这样建议的。但是,查看该方法接受的参数,我认为这可能还不够。 class 应包含如下信息:
- 是否重定向URL是否
- 如果它包含完整路径或仅包含相对路径
- 是否在新版本中打开window/tab
只有这样,您才能管理您在旅途中遇到的所有类型和问题。
但是回到在这种特殊情况下不点击它就获得 link 的问题——我很确定唯一合理的解决方案是解析 onclick
函数以提取第一个参数它的意思是要加载的资源的URL。我在解析字符串方面已经足够好了,所以我不会为您提供任何好的实现。你可以这样得到onclick
函数的字符串:
var selector = 'body > div:nth-child(3) > div.footer__block.footer-menu > div:nth-child(3) > a';
$(selector)[0].onclick.toString();
希望对您有所帮助。