如何使用 axios 和 cheerio 实现多页抓取
How can i achieve multiple page scraping with axios and cheerio
你好,我正在使用带有 cheerio 的 axios 来抓取一些 data.I 想要抓取多个页面,
url 结构就像 example.com/?page=1.How 我可以用计数器抓取每一页吗?
axios({
method: "get",
url:
"https://example.com/?page=",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
}
}).then(res => {
我相信有多种方法可以实现该解决方案,但基本上您需要执行所有 axios
并以编程方式使用 Cheerio 解析所有这些。
如果您知道要抓取多少页
您可以创建一个简单的 for
循环,并使用生成的 url 将所有 axios
函数一个一个地推送到一个数组中。然后你可以用 Promise.all
调用它们
const promises = [];
for(let page = 0; page <= 5; page ++){
promises.push(
axios({method: "get",url:`https://example.com?page=${page}`})
.then(res => {
// Parse your result with Cheerio or whatever you like
})
);
}
// You can pass the responses on this resolve if you want.
Promise.all(promises).then(...)
如果您正在抓取列表页面并且总页数未知
然后您可以创建一个 async/recursive 函数来分派 axios
请求并有条件地迭代。通过这种方式,与下面的解决方案相比,您还可以减少内存的最大使用量。而且它会更慢,因为请求不会并行。
// The function below is kind-of pseudo code so don't try to copy/paste it :)
const dispatchRequest = (page) => {
const response = axios({url: `https://example.com?page=${page}`});
// Ex: You can parse the response here with Cheerio and check if pagination is not disable
if(something){
return dispatchRequest(page+1);
}
else{
return response;
}
}
上述解决方案当然有缺点。如果您被目标网站阻止或您的请求以某种方式失败,您将没有机会重试相同的请求或轮换您的代理来绕过目标网站的安全性。
我建议您实现一个 queue
并将所有请求调度函数放在那里。通过这种方式,您可以检测到 fails/problems 并再次将失败的请求排入队列。您还可以在 queue
支持下实施上述两种解决方案。您可以 运行 并行处理并更好地管理您的 memory/CPU 消费方式。
您也可以使用 SDK。我看到有几个抓取 SDK 为您提供了整个工具集,因此您不会重新发明轮子。
你好,我正在使用带有 cheerio 的 axios 来抓取一些 data.I 想要抓取多个页面, url 结构就像 example.com/?page=1.How 我可以用计数器抓取每一页吗?
axios({
method: "get",
url:
"https://example.com/?page=",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
}
}).then(res => {
我相信有多种方法可以实现该解决方案,但基本上您需要执行所有 axios
并以编程方式使用 Cheerio 解析所有这些。
如果您知道要抓取多少页
您可以创建一个简单的 for
循环,并使用生成的 url 将所有 axios
函数一个一个地推送到一个数组中。然后你可以用 Promise.all
const promises = [];
for(let page = 0; page <= 5; page ++){
promises.push(
axios({method: "get",url:`https://example.com?page=${page}`})
.then(res => {
// Parse your result with Cheerio or whatever you like
})
);
}
// You can pass the responses on this resolve if you want.
Promise.all(promises).then(...)
如果您正在抓取列表页面并且总页数未知
然后您可以创建一个 async/recursive 函数来分派 axios
请求并有条件地迭代。通过这种方式,与下面的解决方案相比,您还可以减少内存的最大使用量。而且它会更慢,因为请求不会并行。
// The function below is kind-of pseudo code so don't try to copy/paste it :)
const dispatchRequest = (page) => {
const response = axios({url: `https://example.com?page=${page}`});
// Ex: You can parse the response here with Cheerio and check if pagination is not disable
if(something){
return dispatchRequest(page+1);
}
else{
return response;
}
}
上述解决方案当然有缺点。如果您被目标网站阻止或您的请求以某种方式失败,您将没有机会重试相同的请求或轮换您的代理来绕过目标网站的安全性。
我建议您实现一个 queue
并将所有请求调度函数放在那里。通过这种方式,您可以检测到 fails/problems 并再次将失败的请求排入队列。您还可以在 queue
支持下实施上述两种解决方案。您可以 运行 并行处理并更好地管理您的 memory/CPU 消费方式。
您也可以使用 SDK。我看到有几个抓取 SDK 为您提供了整个工具集,因此您不会重新发明轮子。