项目代码在这里
参考了如下内容
爬虫主体
爬虫主要结构如下
- config # 配置文件
- index.js # 全局配置
- region.json # 地区json
- sublist.json # 包含项json
- typelist.json # 类型json
- index.js # 启动项
仔细分析,爬虫主要有以下几部分构成
- 构造url字符串
- 请求url对应的html
- 对html进行分析,获取对应信息
- 将所需信息保存并下载
构造URL
这里分析了微博搜索时的url结构,主要有以下几个字段
# 搜索文字
# 搜索类型
# 搜索包含项
# 搜索时间区间
# 搜索地区
考虑到参数内容过多,我在这里将url完全拆分出来,使用单独的
config
进行配置,具体内容如下
var isTopic = true // 如果是 #话题# 类型 则true
var searchWords = ''
var keywords = encodeURI(searchWords)
var typeList = require('./typelist.json')
// 可选类型:全部 热门 原创 关注人 认证用户 媒体 观点
var type = ''
var subList = require('./sublist.json')
// 可选参数:全部 含图片 含视频 含音乐 含短链
var sub = ''
// timescope=custom:2020-05-01-0:2020-05-03-9
var startTime = '' // yyyy-mm-dd-h
var endTime = '' // yyyy-mm-dd-h
var area = require('./region.json') // 陕西西安
var province = '' // 省份
var city = '' // 城市
var provinceAll = true // 如果province == 全部, 则provinceAll = true
// 下载时间间隔 单位:秒(s)
var timeDelay = 10 // default
var pageConfig = {
'q': isTopic ? `%23${keywords}%23` : `${keywords}`,
'type': `${typeList[type]}`,
'include': `${subList[sub]}`,
'timescope':`${startTime}:${endTime}`,
'region': provinceAll ? ``: `${area[province].code}:${area[province].city[city]}`,
'delay': timeDelay * 1000
}
module.exports = pageConfig
请求HTML
因为我习惯了
superagent
,这里就用的这个
return superagent
.get(url)
.set({
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7',
'Cookie': cookie,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
})
分析HTML,获取对应信息
思考了很久,最终放弃了
cheerio
,选择使用jquery
+JSDOM
,不得不说真香
const { window } = new JSDOM(res.text)
const $ = require('jquery')(window)
var userName = $('.name') // 用户名 数组对象
var userNameArr = Array.from(userName).map(val => val.text.trim()) // 用户名 数组值
var userText = $('.txt') // 用户发言文本 数组对象
var userTextArr = Array.from(userText).map(val => val.innerHTML) // 用户发言文本
var regText = /展开全文/g
var trueTextInfo = userTextArr.filter(val => !regText.test(val))
var regTag = /<\/?.+?\/?>/g
var userTextInfo = trueTextInfo.map(val => val.replace(regTag, '')).map(val => val.trim()) // 用户发言文本 数组
var infoFrom = $('.from') // 用户from 信息数组对象
var regcreateTime = /(\d{2}月\d{2}日.*?\d{2}:\d{2})|(\d{1}.*?前)/
var regFrom = /rel="nofollow">(.*?)<\/a>/
var infoFromArr = Array.from(infoFrom).map(val => val.innerHTML) // 数组值
var createTime = infoFromArr.map(val => val.match(regcreateTime)).map(val => val ? val[1]: '') // 创建时间
var deviceInfo = infoFromArr.map(val => val.match(regFrom)).map(val => val ? val[1] : '') // 设备信息
var controlPanel = $('.card-act ul li a')
var repeat = controlPanel.filter(val => val % 4 === 1) // 转发数 数组对象
var repeatArr = Array.from(repeat).map(val => val.text.trim().split(" ")[1]) // 转发数 数组值
var comment = controlPanel.filter(val => val % 4 === 2) // 评论数 数组对象
var commentArr = Array.from(comment).map(val => val.text.trim().split(" ")[1]) // 评论数 数组值
var star = controlPanel.filter(val => val % 4 === 3) // 点赞数 数组对象
var starArr = Array.from(star).map(val => val.text.trim()) // 点赞数 数组值
保存信息并下载
这里使用了
node-xlsx
将每次发送请求后获取的页面单独保存因为我不会合并23333
// 页面信息存放在数组中
var pageInfoArr = []
for (let i = 0; i < userNameArr.length; i++) {
pageInfoArr.push([userNameArr[i], userTextInfo[i], createTime[i], deviceInfo[i], repeatArr[i], commentArr[i], starArr[i]])
}
// xlsx 表头
var title = ['name', 'text', 'createTime', 'deviceInfo', 'repeat', 'comment', 'star']
var arr = []
arr.push(title)
arr = arr.concat(pageInfoArr)
writeXls(arr)
/**
* @description
* @param {Array} datas
*/
function writeXls(datas) {
let buffer = xlsx.build([
{
name: 'sheet1',
data: datas
}
])
fs.writeFile(`./${xlsxName}.xlsx`, buffer, err => {
if (err) {
console.log(err)
} else {
console.log('OK')
}
})
}
后续
因为没考虑好如何将每次请求的数据都写入同一个xlsx
同时考虑到爬虫不能一次发送过多请求,以免(逃~~~
这里单独用定时器设定了启动间隔,以及xlsx的名称
urlList.push(url)
for (let i = 1; i < totalPage; i++) {
urlList.push(`${url}&page=${i+1}`)
}
var xlsxCount = 1 // xlsx name +
var urlCount = 0 // url list +
function parse() {
if (xlsxCount <= totalPage) {
xlsxName = `page${xlsxCount++}`
setText(urlList[urlCount++])
console.log(xlsxName)
}
}
setInterval(parse, config['delay'])
版权属于:ajycc20
本文链接:https://ajycc20.top/archives/19.html
所有原创文章采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。 您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
测试
腊鸡+v