前几天,公司的一些网编和网推们需要扒某个页面内关于全国药店的店铺名、地址和电话,我一看,好家伙,四川省就足足有93页的数据量,一页60条数据,靠人工 Ctrl+C + Ctrl+V
身为一名懒比,能偷懒当然不能出力了啊!
要数据,当然要【爬】【虫】!
不过身为一名苦逼的菜鸟 html狗
,你和我说什么 python
,我选择狗带
所幸啊,我们有一个好玩儿的东西,叫做 Node.js
!
那么就开始动手吧!
(文件已上传,源码请移步 同性交友平台)。
爬虫主要是去获取HTML里的data,然后正则输出你所需要的信息,不过因为有一个神奇的依赖包 cheerio.js
的存在,咱们可以在node里直接像 jQuery
一样用 美金 的力量操作DOM元素。
关于 cheerio.js
的操作方法,同学们可以移步 这儿,可以发现,它的操作方法以及相应的API简直就是和 jQuery
一毛一样,那妥了,接下来就是分析页面结构,就可以开始扒了!
所以,我们需要先 npm
一下这个依赖包
npm i cheerio -s
安装好以后,就可以开始编写 js
啦。
贴上源码,并做解释:
const http = require('http'); // 引入http模块
const fs = require('fs'); // 引入fs模块
const cheerio = require('cheerio'); // 引入cheerio模块
let i = 0; // id
let str = ''; // 下一页后的新地址
let addressInfo = []; // 地址信息
let end = ''; // 结束页,通过正则replace a标签的href
let page = 0; // 当前页
const url = 'http://www.fuyaotang.com/a110000'; // 要扒的页面的第一页
function fetchPage(x) {
startRequest(x);
};
function startRequest(x) {
http.get(x, (res) => { // 获取数据而不是上传数据,所以用GET请求即可
let html = '';
res.setEncoding('utf-8'); // 防止中文乱码
res.on('data', (chunk) => {
html += chunk; // 获取到的html标签,拼接到html变量上
});
res.on('end', () => {
let $ = cheerio.load(html); // 声明cheerio
let infoArray = $('div.related a'); // 获取所有的内容
infoArray.each((index, item) => {
addressInfo.push({ // 添加到数组中
storeName: infoArray.eq(index).children('h3').text().trim(),
address: infoArray.eq(index).children('p').eq(0).text().trim(),
telNum: infoArray.eq(index).children('p').eq(-1).text().trim(),
id: i += 1
});
});
// console.log(addressInfo);
end = $('div.list a').eq(-2).attr('href'); // 下一页地址
end = end.substr(end.length - 2).replace(/[_]/g, ""); // 下一页href的正则输出-->获取数值
let newxtLink = `http://www.fuyaotang.com/${$('div.list a').eq(-2).attr('href')}`;
str = encodeURI(newxtLink); // encodeURI编码
if(page < end) {
page += 1;
fetchPage(str); // 递归
} else {
saveContent($, addressInfo); // 全部结束后,保存数据
}
});
}).on('error', (err) => {
console.log(err); // 报错信息打印到DOC
})
}
function saveContent($, data) {
let storeName = '',
address = '',
telNum = '';
data.forEach((item, index) => {
storeName += data[index].storeName + '\r\n'; // windows需要\r\n换行
address += data[index].address + '\r\n';
telNum += data[index].telNum + '\r\n';
});
// 因为他们的EXCEL需求是要一列一列的输出数据,因此将每一列数据保存到一个文件中,可以直接Ctrl+a复制粘贴,其他的数据操作留待他们在EXCEL自己操作了
fs.appendFile('./data/' + $('.filtertag').find('.cur').text().trim() + '_店铺.txt', storeName, 'utf-8', (err) => {
if (err) {
console.log(err)
}
})
fs.appendFile('./data/' + $('.filtertag').find('.cur').text().trim() + '_地址.txt', address, 'utf-8', (err) => {
if (err) {
console.log(err)
}
})
fs.appendFile('./data/' + $('.filtertag').find('.cur').text().trim() + '_电话.txt', telNum, 'utf-8', (err) => {
if (err) {
console.log(err)
}
})
};
fetchPage(url); // 执行函数
这里必须要说一句,不要通过 Babel
直接用 ES6
简直不要再美唧唧,手动滑稽。
因为只是简单的数据需求,因此仅仅写到这儿,更多的功能,包括下一页涉及的是点击事件发送 ajax
直接更新 DOM树
而不是 href
超链接跳转到新页面,这些处理日后再议啦~~