最近做了一款 高仿ReadHub小程序  微信小程序 canvas 自动适配 自动换行,保存图片分享到朋友圈  https://gitee.com/richard1015/News

具体代码已被开源,后续我会继续更新,欢迎指正

https://github.com/richard1015/egg-example

https://gitee.com/richard1015/egg-example

你可能会像我一样,平常对科技圈发生的热点新闻很感兴趣。每天利用刚打开电脑的时候,又或者是工作间隙,浏览几个更新及时的科技资讯网站。但是,科技圈每天发生的热点新闻就那么几件。看来看去,新闻的重复度高,硬广软文还看了不少。不仅浪费时间,还抓不住重点。

ReadHub 通过爬虫各种科技新闻 大数据过滤筛选 (个人猜想,大概是这一个意思),所以自己写个爬虫把数据爬到自己mysql数据库中

代码思路:

通过网上各种调用 动态网站数据 爬虫分为两种解决方案

1.模拟浏览器请求 使用 相应框架  比如:SeleniumPhantomJs

2.精准分析页面,找到对应请求接口,直接获取api数据。

  • 优点:性能高,使用方便。我们直接获取原数据接口(换句话说就是直接拿取网页这一块动态数据的API接口),肯定会使用方便,并且改变的可能性也比较小。
  • 缺点:缺点也是明显的,如何获取接口API?有些网站可能会考虑到数据的安全性,做各种限制、混淆等。这就需要看开发者个人的基本功了,进行各种分析了。
  • 我个人在爬取ReadHub时,发现《热门话题》 列表是 无混淆,所以找到请求规律,爬取成功 ,剩下 开发者资讯、科技动态、区块链快讯、招聘行情  请求index被混淆,所以暂无成功。

我在本次采用第二种解决方案 chrome浏览器分析

1.使用chrome  调试工具  Mac  按 alt + cmd+ i    Windows 按 F12   或者 右键检查  或 审查元素  找到Network 选中 xhr模块

可通过图片中看到  每次滚动加载数据时  都会有api请求数据, 我们发现 下次触发滚动加载时,的lastCursor的值 为 上次请求的  数组中最后一个对象中的order值

所以我们发现 只是的请求 url地址为 https://api.readhub.me/topic?lastCursor=53058&pageSize=20    中 的lastCursor 动态设置,即可完成抓取数据

那么接下来  我们需要  建立mysql数据库

CREATE DATABASE `news` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */;
CREATE TABLE `news` (`id` varchar(11) COLLATE utf8_bin NOT NULL,`order` double NOT NULL,`title` varchar(200) COLLATE utf8_bin NOT NULL,`jsonstr` json DEFAULT NULL,`createdAt` varchar(255) COLLATE utf8_bin DEFAULT NULL,`updatedAt` varchar(255) COLLATE utf8_bin DEFAULT NULL,`insertTime` datetime DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

然后就是编写 nodejs 中代码逻辑  我在下面的抓取冲采用  eggjs 框架中的 egg-mysql 进行连接数据库 https://eggjs.org/zh-cn/tutorials/mysql.html#egg-mysql

使用定时任务来  执行爬取数据

1.news.service 中代码实现

// app/service/news.js
const Service = require('egg').Service;class NewsService extends Service {async list(pageIndex = '', pageSize = '20') {try {// read configconst { serverUrl } = this.config.readhub;// 热门话题const topic = `${serverUrl}topic?lastCursor=${pageIndex}&pageSize=${pageSize}`;// use build-in http client to GET hacker-news apiconst result = await this.ctx.curl(topic,{dataType: 'json',});if (result.status === 200) {return result.data;}return [];} catch (error) {this.logger.error(error);return [];}}async saveDB(list) {try {const newsClient = this.app.mysql.get("news");list.data.forEach(item => {// 插入newsClient.insert('news', {id: item.id,order: item.order,title: item.title,jsonstr: JSON.stringify(item),createdAt: new Date(item.createdAt).getTime(),updatedAt: new Date(item.updatedAt).getTime(),}).then(result => {// 判断更新成功const updateSuccess = result.affectedRows === 1;this.logger.info(item.id + " > " + updateSuccess);}).catch(error => {//入库失败错误机制触发this.app.cache.errorNum += 1;})});} catch (error) {this.logger.error(error);}}
}module.exports = NewsService;

2.定时任务代码实现

update_cache.js

const Subscription = require('egg').Subscription;class UpdateCache extends Subscription {// 通过 schedule 属性来设置定时任务的执行间隔等配置
  static get schedule() {return {interval: '5s', // 隔单位 m 分 、  s 秒、  ms  毫秒 type: 'all', // 指定所有的 worker 都需要执行immediate: true, //配置了该参数为 true 时,这个定时任务会在应用启动并 ready 后立刻执行一次这个定时任务。disable: false//配置该参数为 true 时,这个定时任务不会被启动。
    };}// subscribe 是真正定时任务执行时被运行的函数
  async subscribe() {let ctx = this.ctx;ctx.logger.info('update cache errorNum  = ' + ctx.app.cache.errorNum);// errorNum 当错误数量 > 50时 停止抓取数据if (ctx.app.cache.errorNum > 50) {ctx.logger.info('errorNum > 50 stop ');return;}ctx.logger.info('update cache begin ! currentLastCursor = ' + ctx.app.cache.lastCursor);const pageIndex = ctx.app.cache.lastCursor || '';const pageSize = '20';const newsList = await ctx.service.news.list(pageIndex == 1 ? '' : pageIndex, pageSize);if (newsList.data.length == 0) {//没有数据时错误机制触发this.app.cache.errorNum += 1;ctx.logger.info('no data stop ! currentLastCursor = ' + ctx.app.cache.lastCursor);} else {ctx.service.news.saveDB(newsList)ctx.app.cache.lastCursor = newsList.data[newsList.data.length - 1].order;ctx.logger.info('update cache end ! currentLastCursor set  = ' + ctx.app.cache.lastCursor);}}
}module.exports = UpdateCache;

update_cache_init.js

const Subscription = require('egg').Subscription;class UpdateCacheInit extends Subscription {// 通过 schedule 属性来设置定时任务的执行间隔等配置
  static get schedule() {return {interval: 60 * 24 + 'm', // 隔单位 m 分 、  s 秒、  ms  毫秒 type: 'all', // 指定所有的 worker 都需要执行immediate: true, //配置了该参数为 true 时,这个定时任务会在应用启动并 ready 后立刻执行一次这个定时任务。disable: false//配置该参数为 true 时,这个定时任务不会被启动。
    };}// subscribe 是真正定时任务执行时被运行的函数
  async subscribe() {let ctx = this.ctx;ctx.logger.info('update cache init');if (ctx.app.cache.errorNum > 50) {//初始化内置缓存ctx.app.cache = {lastCursor: '',errorNum: 0 //错误数量
      };}}
}module.exports = UpdateCacheInit;

项目运行图

具体代码已被开源,后续我会继续更新,欢迎指正

https://github.com/richard1015/egg-example

https://gitee.com/richard1015/egg-example

转载于:https://www.cnblogs.com/richard1015/p/9203597.html

nodejs eggjs框架 爬虫 readhub.me相关推荐

  1. nodejs和python爬虫 哪个好_nodejs有哪些爬虫框架?

    nodejs有哪些爬虫框架?下面本篇文章给大家介绍几款nodejs爬虫框架.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. node-spider 基于nodejs的通用爬虫框架,得 ...

  2. Crawler之Scrapy:Python实现scrapy框架爬虫两个网址下载网页内容信息

    Crawler之Scrapy:Python实现scrapy框架爬虫两个网址下载网页内容信息 目录 输出结果 实现代码 输出结果 后期更新-- 实现代码 import scrapy class Dmoz ...

  3. python多线程爬虫框架_普通爬虫vs多线程爬虫vs框架爬虫,Python爬对比

    前言 本文的文字及图片过滤网络,可以学习,交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 基本开发环境 Python 3.6 皮查姆 目标网页分析 网站就选择发表情这个网站吧 网站是静 ...

  4. Nodejs ORM框架Sequelize

    Nodejs ORM框架Sequelize (模型,关联表,事务,循环,及常见问题) 建立连接 const Sequelize = require('sequelize'); const sequel ...

  5. Python基础知识回顾及scrapy框架爬虫基础

    1.函数 函数参数:必须 默认 关键 可变 函数种类:外部 内部 匿名 lambda 装饰函数:@语法糖 函数总是要返回的 ,若没有return,None总是被返回   2.面向对象: 对象:已存在, ...

  6. nodeJS实现简易爬虫

    nodeJS实现简易爬虫 需求:使用nodeJS爬取昵图网某个分类下的图片并存入本地 运用nodeJS自带系统模块http.fs 示例代码: var http =require('http'); va ...

  7. eggjs框架学习心得

    前言: eggjs作为阿里开源的企业级 Node.js 框架,其官网教程https://eggjs.org/zh-cn/tutorials/index.html介绍的很详细,可以帮助初学开发者快速搭建 ...

  8. 一次使用NodeJS实现网页爬虫记 - huanping - 博客园

    一次使用NodeJS实现网页爬虫记 - huan&ping - 博客园

  9. nodejs MVC框架:Adonisjs框架入门-001概述

    Adonisjs是一个MVC结构的Nodejs后端框架,可以用来创建WEB应用.API服务,包含处理 HTTP adonisjs是一个后端mvc框架,基于nodejs,使用typescript语言编写 ...

  10. nodejs实现新闻爬虫

    nodejs实现新闻爬虫 作为费德勒的铁杆粉丝,每天早上都会在新浪体育里面的网球频道浏览费德勒新闻.由于只关注费德勒的新闻,所以每次都要在网页中大量的新闻中筛选相关信息,感觉效率好低,所以用node写 ...

最新文章

  1. Logback 配置文件这样优化,TPS提高 10 倍
  2. 千亿级携程酒店AWS实践
  3. SQL点滴5—产生时间demention,主要是时间转换
  4. python2.7爬虫实例-Python2.7爬虫-爬取简书文章-入门
  5. 合肥市电力大数据应用工程技术研究中心成立
  6. aws搭建java项目_AWS下S3之java开发
  7. 六、乘胜追击,将剩下的Git知识点搞定
  8. Django学习笔记之——Forms
  9. JQuery中样式标签的处理
  10. 计组之中央处理器:7、指令流水线基本概念性能指标、影响因素
  11. oracle 自定义函数 返回一个表类型
  12. javascript 的预解释机制
  13. 光纤中传导模式matlab仿真,光纤通信实验指导书
  14. vue 浏览器页面刷新
  15. MySQL什么情况会导致索引失效?
  16. Python网络爬虫(二):小说下载器
  17. 三十六计第三计 借刀杀人
  18. HBase批量写入数据
  19. H3C服务器带外默认账号和密码,H3C产品的默认密码是多少?
  20. 知识付费直播间即时通讯

热门文章

  1. Android工具类篇 清理APP应用缓存
  2. 系统上电后 bootloader的执行流程
  3. 8255芯片控制发光二极管模拟步进电机汇编实验
  4. 记一次golang memory leak的解决过程
  5. 通过 ANE(Adobe Native Extension) 启动Andriod服务 推送消息(三)
  6. 帝国 php 7.0 默认 后台用户名及认证码,帝国CMS忘记后台登陆用户名 密码 认证码 安全提问答案 数据库用户名及密码的解决方法 | 坐倚北风...
  7. 静态路由原理及配置(8)
  8. 行转列 和 链接查询 
  9. 802.1Q封装的VLAN数据帧格式
  10. sogou/workflow入门(windows版)