使用 Node.js 开发资讯爬虫流程


Posted in Javascript onJanuary 07, 2018

最近项目需要一些资讯,因为项目是用 Node.js 来写的,所以就自然地用 Node.js 来写爬虫了

项目地址:github.com/mrtanweijie… ,项目里面爬取了 Readhub 、 开源中国 、 开发者头条 、 36Kr 这几个网站的资讯内容,暂时没有对多页面进行处理,因为每天爬虫都会跑一次,现在每次获取到最新的就可以满足需求了,后期再进行完善

爬虫流程概括下来就是把目标网站的HTML下载到本地再进行数据提取。

一、下载页面

Node.js 有很多http请求库,这里使用 request ,主要代码如下:

requestDownloadHTML () {
 const options = {
  url: this.url,
  headers: {
  'User-Agent': this.randomUserAgent()
  }
 }
 return new Promise((resolve, reject) => {
  request(options, (err, response, body) => {
  if (!err && response.statusCode === 200) {
   return resolve(body)
  } else {
   return reject(err)
  }
  })
 })
 }

使用 Promise 来进行包装,便于后面使用的时候用上 async/await 。因为有很多网站是在客户端渲染的,所以下载到的页面不一定包含想要的HTML内容,我们可以使用 Google 的 puppeteer 来下载客户端渲染的网站页面。众所周知的原因,在 npm i 的时候 puppeteer 可能因为需要下载Chrome内核导致安装会失败,多试几次就好了:)

puppeteerDownloadHTML () {
 return new Promise(async (resolve, reject) => {
  try {
  const browser = await puppeteer.launch({ headless: true })
  const page = await browser.newPage()
  await page.goto(this.url)
  const bodyHandle = await page.$('body')
  const bodyHTML = await page.evaluate(body => body.innerHTML, bodyHandle)
  return resolve(bodyHTML)
  } catch (err) {
  console.log(err)
  return reject(err)
  }
 })
 }

当然客户端渲染的页面最好是直接使用接口请求的方式,这样后面的HTML解析都不需要了,进行一下简单的封装,然后就可以像这样使用了: #滑稽 :)

await new Downloader('http://36kr.com/newsflashes', DOWNLOADER.puppeteer).downloadHTML()

二、HTML内容提取

HTML内容提取当然是使用神器 cheerio 了, cheerio 暴露了和 jQuery 一样的接口,用起来非常简单。浏览器打开页面 F12 查看提取的页面元素节点,然后根据需求来提取内容即可

readHubExtract () {
 let nodeList = this.$('#itemList').find('.enableVisited')
 nodeList.each((i, e) => {
  let a = this.$(e).find('a')
  this.extractData.push(
  this.extractDataFactory(
   a.attr('href'),
   a.text(),
   '',
   SOURCECODE.Readhub
  )
  )
 })
 return this.extractData
 }

三、定时任务

cron 每天跑一跑 
function job () {
 let cronJob = new cron.CronJob({
 cronTime: cronConfig.cronTime,
 onTick: () => {
  spider()
 },
 start: false
 })
 cronJob.start()
}

四、数据持久化

数据持久化理论上应该不属于爬虫关心的范围,用 mongoose ,创建Model

import mongoose from 'mongoose'
const Schema = mongoose.Schema
const NewsSchema = new Schema(
 {
 title: { type: 'String', required: true },
 url: { type: 'String', required: true },
 summary: String,
 recommend: { type: Boolean, default: false },
 source: { type: Number, required: true, default: 0 },
 status: { type: Number, required: true, default: 0 },
 createdTime: { type: Date, default: Date.now }
 },
 {
 collection: 'news'
 }
)
export default mongoose.model('news', NewsSchema)

基本操作

import { OBJ_STATUS } from '../../Constants'
class BaseService {
 constructor (ObjModel) {
 this.ObjModel = ObjModel
 }

 saveObject (objData) {
 return new Promise((resolve, reject) => {
  this.ObjModel(objData).save((err, result) => {
  if (err) {
   return reject(err)
  }
  return resolve(result)
  })
 })
 }
}
export default BaseService

资讯

import BaseService from './BaseService'
import News from '../models/News'
class NewsService extends BaseService {}
export default new NewsService(News)

愉快地保存数据

await newsService.batchSave(newsListTem)

更多内容到Github把项目clone下来看就好了。

总结

Javascript 相关文章推荐
jQuery创建插件的代码分析
Apr 14 Javascript
javascript获取隐藏元素(display:none)的高度和宽度的方法
Jun 06 Javascript
JavaScript用JQuery呼叫Server端方法示例代码
Sep 03 Javascript
让人蛋疼的JavaScript语法特性
Sep 30 Javascript
浅谈JavaScript中setInterval和setTimeout的使用问题
Aug 01 Javascript
js文件中直接alert()中文出来的是乱码的解决方法
Nov 01 Javascript
JS实现上传图片的三种方法并实现预览图片功能
Jul 14 Javascript
jQuery中库的引用方法
Jan 06 jQuery
jQuery Dom元素操作技巧
Feb 04 jQuery
Vue解析剪切板图片并实现发送功能
Feb 04 Javascript
vue跳转页面的几种方法(推荐)
Mar 26 Javascript
vue-drag-chart 拖动/缩放图表组件的实例代码
Apr 10 Javascript
CentOS环境中MySQL修改root密码方法
Jan 07 #Javascript
12条写出高质量JS代码的方法
Jan 07 #Javascript
js数组方法reduce经典用法代码分享
Jan 07 #Javascript
javascript中的replace函数(带注释demo)
Jan 07 #Javascript
基于JavaScript实现简单的音频播放功能
Jan 07 #Javascript
js实现复制功能(多种方法集合)
Jan 06 #Javascript
tangram.js库实现js类的方式实例分析
Jan 06 #Javascript
You might like
一个域名查询的程序
2006/10/09 PHP
小偷PHP+Html+缓存
2006/12/20 PHP
PHPAnalysis中文分词类详解
2014/06/13 PHP
简单解决新浪SAE无法上传文件的问题
2015/05/13 PHP
PHP7.0版本备注
2015/07/23 PHP
php file_get_contents取文件中数组元素的方法
2017/04/01 PHP
用JavaScript实现单继承和多继承的简单方法
2009/03/29 Javascript
实现checkbox全选、反选、取消JavaScript小脚本异常
2014/04/10 Javascript
JavaScript弹出窗口方法汇总
2014/08/12 Javascript
JavaScript将XML转成JSON的方法
2015/03/12 Javascript
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
2016/05/12 Javascript
JS导出PDF插件的方法(支持中文、图片使用路径)
2016/07/12 Javascript
jqgrid实现简单的单行编辑功能
2017/09/30 Javascript
详解如何使用PM2将Node.js的集群变得更加容易
2017/11/15 Javascript
React数据传递之组件内部通信的方法
2017/12/31 Javascript
ES6与CommonJS中的模块处理的区别
2018/06/13 Javascript
Redux实现组合计数器的示例代码
2018/07/04 Javascript
JS实现的点击按钮图片上下滚动效果示例
2019/01/28 Javascript
vue 实现滚动到底部翻页效果(pc端)
2019/07/31 Javascript
javascript sort()对数组中的元素进行排序详解
2019/10/13 Javascript
分享一下Python 开发者节省时间的10个方法
2015/10/02 Python
Python如何import文件夹下的文件(实现方法)
2017/01/24 Python
git使用.gitignore设置不生效或不起作用问题的解决方法
2017/06/01 Python
图文详解Django使用Pycharm连接MySQL数据库
2019/08/09 Python
Python3自动生成MySQL数据字典的markdown文本的实现
2020/05/07 Python
python二维图制作的实例代码
2020/12/03 Python
真正了解CSS3背景下的@font face规则
2017/05/04 HTML / CSS
工业设计专业推荐信
2013/10/29 职场文书
年终考核评语
2014/01/19 职场文书
会计电算化专业自荐信
2014/03/15 职场文书
工程造价专业求职信
2014/07/17 职场文书
党支部四风整改方案
2014/10/25 职场文书
党内外群众意见范文
2015/06/02 职场文书
如何用python插入独创性声明
2021/03/31 Python
Python实现8种常用抽样方法
2021/06/27 Python
python Django框架快速入门教程(后台管理)
2021/07/21 Python