Nodejs 网络抓取在 3 个循环内有 3 个请求
Nodejs web scraping with 3 requests inside 3 loops
我的任务是通过网络抓取网站类别内容并将其制作成 json 文件。我只能对主页进行硬编码 URL。每个类别使用 ajax 并且每个类别都有一个以上的页面。
- 我应该请求主页 url(例如:http://www.example.com/category.php,获取多少类别并保存类别标题
- 当我得到总类别时,我将使用 for 循环 请求来自(例如:http://www.example.com/category.php?category=i)
- 当我访问每个类别时,我应该请求计算每个类别中有多少页并使用 for 循环(例如:http://www.example.com/category.php?category=i&page=x)
- 当我访问每个页面时,我应该统计其中有多少内容并使用for循环获取数据并将其保存在变量
中
- 我应该生成一个 JSON 文件来保存结果。
在 3 个循环内生成 3 个请求的 node.js 代码结构是什么?
尝试使用 Async waterfall。
示例片段:
async.waterfall([
firstFunction,
secondFunction,
lastFunction,
], (err, result) => {
if(err){}
});
function firstFunction(callback) {
callback(null);
}
function secondFunction(callback) {
callback(null);
}
function lastFunction(callback) {
callback(null);
}
在循环内执行请求的代码与在循环外执行请求的代码没有任何不同,唯一的大区别在于如何处理它。当然,对于一个请求,您通常可以编写一个简单的函数来完成所有操作,但是对于这样的事情,您最好这样做:
为每个单独的部分创建一个异步函数,以后在其他地方(比如另一个项目)可能会有用,例如:抓取类别列表,抓取每个类别中的页面列表,并从每个类别的列表中抓取实际页面。
在使用循环的地方,为请求创建一个数组,为响应创建另一个数组,或者使用 map
或另一个循环对单个变量执行此操作,但是 不要等待每个请求,而是不要 await
任何请求,而只是映射请求 -> Promise(response)
。在 map/whatever 循环之后使用 await Promise.all(arrayOfResponses)
等待所有请求完成(当然你可以只限制一部分请求以防止它让你暂时被 IP 禁止,或者降低如果它的服务器很弱)。
当你像这样完成一个功能时,其他功能就会容易得多。您甚至可以编写一个可用于所有请求的通用函数,然后根据需要调用它并在函数外任何您喜欢的地方等待它(因此它对单个请求和数组都很有用)。
尽管如此,制作机器人的一个重要部分是也要尽量对它友善,以免惹上麻烦。部分原因是考虑网站及其带宽,因此您不会像上面提到的那样将其关闭,但您可能还希望避免您在网站上的个人帐户(如果有的话)因为您的机器人而受到惩罚。
设置适当的用户代理可以对此有所帮助,http://www.user-agents.org 可以从中得到很好的启发。请注意有多少包括产品名称、版本和网站,有些还包括用于联系机器人处理程序的电子邮件地址。这些有助于识别机器人,如果它失控了,给他们联系的人,而不是立即禁止用户代理或 IP 地址。
我的任务是通过网络抓取网站类别内容并将其制作成 json 文件。我只能对主页进行硬编码 URL。每个类别使用 ajax 并且每个类别都有一个以上的页面。
- 我应该请求主页 url(例如:http://www.example.com/category.php,获取多少类别并保存类别标题
- 当我得到总类别时,我将使用 for 循环 请求来自(例如:http://www.example.com/category.php?category=i)
- 当我访问每个类别时,我应该请求计算每个类别中有多少页并使用 for 循环(例如:http://www.example.com/category.php?category=i&page=x)
- 当我访问每个页面时,我应该统计其中有多少内容并使用for循环获取数据并将其保存在变量 中
- 我应该生成一个 JSON 文件来保存结果。
在 3 个循环内生成 3 个请求的 node.js 代码结构是什么?
尝试使用 Async waterfall。
示例片段:
async.waterfall([
firstFunction,
secondFunction,
lastFunction,
], (err, result) => {
if(err){}
});
function firstFunction(callback) {
callback(null);
}
function secondFunction(callback) {
callback(null);
}
function lastFunction(callback) {
callback(null);
}
在循环内执行请求的代码与在循环外执行请求的代码没有任何不同,唯一的大区别在于如何处理它。当然,对于一个请求,您通常可以编写一个简单的函数来完成所有操作,但是对于这样的事情,您最好这样做:
为每个单独的部分创建一个异步函数,以后在其他地方(比如另一个项目)可能会有用,例如:抓取类别列表,抓取每个类别中的页面列表,并从每个类别的列表中抓取实际页面。
在使用循环的地方,为请求创建一个数组,为响应创建另一个数组,或者使用
map
或另一个循环对单个变量执行此操作,但是 不要等待每个请求,而是不要await
任何请求,而只是映射请求 ->Promise(response)
。在 map/whatever 循环之后使用await Promise.all(arrayOfResponses)
等待所有请求完成(当然你可以只限制一部分请求以防止它让你暂时被 IP 禁止,或者降低如果它的服务器很弱)。
当你像这样完成一个功能时,其他功能就会容易得多。您甚至可以编写一个可用于所有请求的通用函数,然后根据需要调用它并在函数外任何您喜欢的地方等待它(因此它对单个请求和数组都很有用)。
尽管如此,制作机器人的一个重要部分是也要尽量对它友善,以免惹上麻烦。部分原因是考虑网站及其带宽,因此您不会像上面提到的那样将其关闭,但您可能还希望避免您在网站上的个人帐户(如果有的话)因为您的机器人而受到惩罚。
设置适当的用户代理可以对此有所帮助,http://www.user-agents.org 可以从中得到很好的启发。请注意有多少包括产品名称、版本和网站,有些还包括用于联系机器人处理程序的电子邮件地址。这些有助于识别机器人,如果它失控了,给他们联系的人,而不是立即禁止用户代理或 IP 地址。