使用Node.js异步脚本请求网页

4
我正在使用非常简单的Request模块下载网页。
我的问题是,我试图下载的页面具有一些异步脚本(具有async属性),它们没有与从http请求返回的html文档一起下载。
我的问题是如何使用/不使用(最好是使用)request模块进行HTTP请求,并在某些边缘情况下避免由于上述原因而出现的异常情况,以完整下载整个页面。

使用无界面浏览器,也许。 - mithril_knight
@mithril_knight您好,感谢回复,请查看我的评论以获取chriskelly文章的解决方案。仍在寻找解决方案。 :) - Jorayen
仍在苦苦挣扎,如果有人能帮我找到解决方案,我将不胜感激。 - Jorayen
2个回答

2
听起来你正在尝试使用Javascript进行网页抓取。
使用request是一种非常基础的方法,可能对你的需求来说过于低级和耗时。这个话题相当广泛,但你应该研究更专门的模块,比如cheerio、x-ray和nightmare。 x-ray x-ray让你可以直接从页面中选择元素,类似于jquery的方式,而不是解析整个body。 nightmare提供了一个现代化的无头浏览器,使你能够像手动使用浏览器一样输入输入内容。有了这个,你应该能够更好地处理那些导致问题的ajax类型请求。
希望对你有帮助,祝你好运!

你说得对,基本上我正在爬取网页。我使用正则表达式数组来查找返回文档中可能存在的URI,因为使用cherrio/jsdom/x-ray等工具不足以满足需求,因为有些URI并不在src/href属性值内。此外,无头浏览器也不行,因为我想要实现的是存档和镜像一个网站(类似于HTTrack)。我已经完成了大部分代码,并选择使用request来处理HTTP请求,但问题是与在浏览器中打开网站不同,request模块返回的文档不包含任何异步脚本。 - Jorayen
@Jorayen 我也遇到过这种情况,不得不转向使用phantomjs。在此之前我使用了cheerio,但和你一样,它无法加载异步脚本内容。 - mithril_knight

0

只使用请求,您可以尝试以下方法来提取异步脚本。

注意:我已经在一个非常基本的设置中进行了测试,并且还有一些工作要做,以使其更加稳健。然而,对我来说它是有效的:

测试设置

为了设置测试,我创建了一个包含如下代码的HTML文件:<script src="abc.js" async></script>

然后创建一个临时服务器来启动它(httpster)

爬虫

"use strict";

const request = require('request');

const options1 = { url: 'http://localhost:3333/' }

// hard coded script name for test purposes
const options2 = { url: 'http://localhost:3333/abc.js' }

let htmlData  // store html page here

request.get(options1)
    .on('response', resp => resp.on('data', d => htmlData += d))
    .on('end', () => {
        let scripts; // store scripts here

        // htmlData contains webpage
        // Use xml parser to find all script tags with async tags
        // and their base urls
        // NOT DONE FOR THIS EXAMPLE

        request.get(options2)
            .on('response', resp => resp.on('data', d => scripts += d))
            .on('end', () => {
                let allData = htmlData.toString() + scripts.toString();
                console.log(allData);
            })
           .on('error', err => console.log(err))
    })
    .on('error', err => console.log(err))

这个基本的例子是有效的。你需要找到页面上所有的js脚本,并提取url部分,这里我没有做。


问题在于第一个请求完成后,在“end”事件上,htmlData中不包含任何异步脚本,因此我无法找到那些异步脚本标签,这就是我的问题。 - Jorayen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接