Node.js数据抓取技术实战示例

Node.js常用的库有哪些呢?比如axios或者node-fetch用来发送HTTP请求,cheerio用来解析HTML,如果是动态网页的话可能需要puppeteer这样的无头浏览器。这些工具的组合应该能满足大部分需求。

然后,可能遇到的难点在哪里?比如反爬虫机制,比如验证码、IP封锁,或者需要处理JavaScript渲染的内容。这时候可能需要使用puppeteer来模拟浏览器行为,或者使用代理池来避免IP被封。

接下来考虑步骤。首先发送请求获取页面内容,然后解析HTML提取所需数据,最后存储数据到文件或数据库。如果是分页的数据,可能需要循环处理多个页面。还需要处理异常情况,比如请求失败、页面结构变化等,这时候需要错误处理和日志记录。

另外,爬虫可能对性能有要求吗?比如并发请求,可以使用Promise.all或者限制并发数的库,比如p-limit,避免同时发送太多请求导致服务器压力过大或被封IP。

数据存储方面,可能需要存到JSON文件、CSV,或者数据库如MongoDB、MySQL,根据用户需求选择。如果是简单需求,保存到文件可能更方便。

还有合法性的问题,提醒用户遵守网站的robots.txt,尊重版权和隐私,避免法律问题。这也是需要注意的地方。

最后,代码示例部分需要简单明了,展示一个完整的流程。比如用axios获取页面,用cheerio解析,提取数据,然后保存到文件。如果是动态内容,用puppeteer的例子。同时给出注意事项,比如处理延迟、错误处理等。

多数用户是初学者,所以代码示例要注释清楚,步骤明确。同时需要提到可能的扩展点,比如处理分页、并发请求、存储到数据库等,让用户知道如何根据需求进一步开发。

总结一下,回答需要涵盖工具选择、步骤分解、代码示例、注意事项以及可能的扩展方向,帮助用户全面了解Node.js抓取数据的流程和要点。

在 Node.js 中实现数据抓取通常涉及 HTTP 请求、HTML 解析和数据处理。以下是详细实现步骤和示例代码:

一、常用工具

HTTP 请求库

axios:Promise-based HTTP 客户端

node-fetch:类似浏览器 fetch 的实现

puppeteer:无头浏览器(用于动态渲染页面)

HTML 解析

cheerio:类似 jQuery 的 DOM 操作库

jsdom:完整的 DOM 实现

其他工具

p-limit:控制并发请求

csv-writer:生成 CSV 文件

二、静态页面抓取示例

constaxios=require('axios');

constcheerio=require('cheerio');

constfs=require('fs');

asyncfunctionfetchData(url) {

try{

const{data}=awaitaxios.get(url);

const$=cheerio.load(data);


constresults=[];

$('.product-item').each((i,element)=>{

results.push({

name:$(element).find('.name').text().trim(),

price:$(element).find('.price').text().trim(),

link:$(element).find('a').attr('href')

     });

   });

fs.writeFileSync('products.json',JSON.stringify(results,null,2));

console.log('数据抓取完成');

}catch(error) {

console.error('抓取失败:',error.message);

  }

}

// 使用示例

fetchData('https://example.com/products');

三、动态页面抓取(使用 Puppeteer)

constpuppeteer=require('puppeteer');

asyncfunctiondynamicScraping(url) {

constbrowser=awaitpuppeteer.launch();

constpage=awaitbrowser.newPage();


awaitpage.goto(url, {waitUntil:'networkidle2'});


// 执行页面内 JavaScript

constdata=awaitpage.evaluate(()=>{

returnArray.from(document.querySelectorAll('.user-card'))

.map(card=>({

username:card.querySelector('.username').innerText,

bio:card.querySelector('.bio').innerText

     }));

  });

awaitbrowser.close();

returndata;

}

// 使用示例

dynamicScraping('https://example.com/users')

.then(data=>console.log(data))

.catch(console.error);

四、高级技巧

处理分页

asyncfunctionpaginatedScraping(baseUrl,totalPages) {

constresults=[];


for(letpage=1;page<=totalPages;page++) {

consturl=`${baseUrl}?page=${page}`;

constdata=awaitfetchData(url);

results.push(...data);

awaitnewPromise(resolve=>setTimeout(resolve,2000));// 延迟防止封禁

  }


returnresults;

}

并发控制

constpLimit=require('p-limit');

constlimit=pLimit(3);// 最大并发数

asyncfunctionconcurrentScraping(urls) {

constpromises=urls.map(url=>

limit(()=>fetchData(url))

  );

returnPromise.all(promises);

}

代理配置

constaxiosInstance=axios.create({

proxy: {

host:'proxy-server',

port:8080,

auth: {

username:'your_user',

password:'your_pass'

   }

  }

});

五、数据存储选项

JSON 文件

fs.writeFileSync('data.json',JSON.stringify(data));

CSV 文件

constcreateCsvWriter=require('csv-writer').createObjectCsvWriter;

constcsvWriter=createCsvWriter({

path:'data.csv',

header: [

{id:'name',title:'NAME'},

{id:'price',title:'PRICE'}

  ]

});

csvWriter.writeRecords(data);

数据库存储(MongoDB 示例)

constmongoose=require('mongoose');

constproductSchema=newmongoose.Schema({

name:String,

price:Number,

link:String

});

constProduct=mongoose.model('Product',productSchema);

asyncfunctionsaveToDB(data) {

awaitmongoose.connect('mongodb://localhost:27017/scraping');

awaitProduct.insertMany(data);

awaitmongoose.disconnect();

}

六、反爬虫对策

设置合理的请求头

headers: {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',

'Accept-Language': 'en-US,en;q=0.9'

}

使用随机延迟

function randomDelay(min, max) {

return new Promise(resolve =>

setTimeout(resolve, Math.random() * (max - min) + min)

);

}

处理 Cookie

const jar = new tough.CookieJar();

axios.get(url, {

jar: jar,

withCredentials: true

});

七、错误处理最佳实践

async function robustScraping(url, retries = 3) {

for (let i = 0; i < retries; i++) {

try {

return await fetchData(url);

} catch (error) {

if (i === retries - 1) throw error;

await new Promise(resolve => setTimeout(resolve, 5000 * (i + 1)));

}

}

}

注意事项

遵守 robots.txt 规则

尊重网站的服务条款

控制请求频率(建议 2-5 秒/请求)

处理敏感数据需符合 GDPR 等法规

使用 try/catch 处理网络错误

定期检查选择器是否有效

根据具体需求可以组合这些技术,简单的静态页面使用 cheerio + axios 即可,复杂场景(SPA、需要登录)则需要 puppeteer。对于大规模抓取建议使用分布式架构(Redis 队列 + 多 Worker)。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容