之前看过一篇脑洞大开的文章,介绍了各个大厂的前端反爬虫技巧,但也正如此文所说,没有100%的反爬虫方法,本文介绍一种简单的方法,来绕过所有这些前端反爬虫手段。

下面的代码以百度指数为例,代码已经封装成一个百度指数爬虫node库: https://github.com/Coffcer/baidu-index-spider

note: 请勿滥用爬虫给他人添麻烦

百度指数的反爬虫策略

观察百度指数的界面,指数数据是一个趋势图,当鼠标悬浮在某一天的时候,会触发两个请求,将结果显示在悬浮框里面:

按照常规思路,我们先看下这个请求的内容:

请求 1:

请求 2:

可以发现,百度指数实际上在前端做了一定的反爬虫策略。当鼠标移动到图表上时,会触发两个请求,一个请求返回一段html,一个请求返回一张生成的图片。html中并不包含实际数值,而是通过设置width和margin-left,来显示图片上的对应字符。并且请求参数上带有res、res1这种我们不知如何模拟的参数,所以用常规的模拟请求或者html爬取的方式,都很难爬到百度指数的数据。

爬虫思路

怎么突破百度这种反爬虫方法呢,其实也很简单,就是完全不去管他是如何反爬虫的。我们只需模拟用户操作,将需要的数值截图下来,做图像识别就行。步骤大概是:

  1. 模拟登录
  2. 打开指数页面
  3. 鼠标移动到指定日期
  4. 等待请求结束,截取数值部分的图片
  5. 图像识别得到值
  6. 循环第3~5步,就得到每一个日期对应的值

这种方法理论上能爬任何网站的内容,接下来我们来一步步实现爬虫,下面会用到的库:

  • puppeteer 模拟浏览器操作
  • node-tesseract tesseract的封装,用来做图像识别
  • jimp 图片裁剪

安装 Puppeteer, 模拟用户操作

Puppeteer是Google Chrome团队出品的Chrome自动化工具,用来控制Chrome执行命令。可以模拟用户操作,做自动化测试、爬虫等。用法非常简单,网上有不少入门教程,顺着本文看完也大概可以知道如何使用。

API文档: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md

安装:

npm install --save puppeteer
复制代码

Puppeteer在安装时会自动下载Chromium,以确保可以正常运行。但是国内网络不一定能成功下载Chromium,如果下载失败,可以使用cnpm来安装,或者将下载地址改成淘宝的镜像,然后再安装:

npm config set PUPPETEER_DOWNLOAD_HOST=https://npm.taobao.org/mirrors
npm install --save puppeteer
复制代码

你也可以在安装时跳过Chromium下载,通过代码指定本机Chrome路径来运行:

// npm
npm install --save puppeteer --ignore-scripts// node
puppeteer.launch({ executablePath: '/path/to/Chrome' });
复制代码

实现

为版面整洁,下面只列出了主要部分,代码涉及到selector的部分都用了...代替,完整代码参看文章顶部的github仓库。

打开百度指数页面,模拟登录

这里做的就是模拟用户操作,一步步点击和输入。没有处理登录验证码的情况,处理验证码又是另一个话题了,如果你在本机登录过百度,一般不需要验证码。

// 启动浏览器,
// headless参数如果设置为true,Puppeteer将在后台操作你Chromium,换言之你将看不到浏览器的操作过程
// 设为false则相反,会在你电脑上打开浏览器,显示浏览器每一操作。
const browser = await puppeteer.launch({headless:false});
const page = await browser.newPage();// 打开百度指数
await page.goto(BAIDU_INDEX_URL);// 模拟登陆
await page.click('...');
await page.waitForSelecto('...');
// 输入百度账号密码然后登录
await page.type('...','username');
await page.type('...','password');
await page.click('...');
await page.waitForNavigation();
console.log('✅ 登录成功');
复制代码

模拟移动鼠标,获取需要的数据

需要将页面滚动到趋势图的区域,然后移动鼠标到某个日期上,等待请求结束,tooltip显示数值,再截图保存图片。

// 获取chart第一天的坐标
const position = await page.evaluate(() => {const $image = document.querySelector('...');const $area = document.querySelector('...');const areaRect = $area.getBoundingClientRect();const imageRect = $image.getBoundingClientRect();// 滚动到图表可视化区域window.scrollBy(0, areaRect.top);return { x: imageRect.x, y: 200 };
});// 移动鼠标,触发tooltip
await page.mouse.move(position.x, position.y);
await page.waitForSelector('...');// 获取tooltip信息
const tooltipInfo = await page.evaluate(() => {const $tooltip = document.querySelector('...');const $title = $tooltip.querySelector('...');const $value = $tooltip.querySelector('...');const valueRect = $value.getBoundingClientRect();const padding = 5;return {title: $title.textContent.split(' ')[0],x: valueRect.x - padding,y: valueRect.y,width: valueRect.width + padding * 2,height: valueRect.height}
});
复制代码

截图

计算数值的坐标,截图并用jimp对裁剪图片。

await page.screenshot({ path: imgPath });// 对图片进行裁剪,只保留数字部分
const img = await jimp.read(imgPath);
await img.crop(tooltipInfo.x, tooltipInfo.y, tooltipInfo.width, tooltipInfo.height);
// 将图片放大一些,识别准确率会有提升
await img.scale(5);
await img.write(imgPath);
复制代码

图像识别

这里我们用Tesseract来做图像识别,Tesseracts是Google开源的一款OCR工具,用来识别图片中的文字,并且可以通过训练提高准确率。github上已经有一个简单的node封装: node-tesseract,需要你先安装Tesseract并设置到环境变量。

Tesseract.process(imgPath, (err, val) => {
if (err || val == null) {console.error('❌ 识别失败:' + imgPath);return;
}
console.log(val);
复制代码

实际上未经训练的Tesseracts识别起来会有少数几个错误,比如把9开头的数字识别成`3,这里需要通过训练去提升Tesseracts的准确率,如果识别过程出现的问题都是一样的,也可以简单通过正则去修复这些问题。

封装

实现了以上几点后,只需组合起来就可以封装成一个百度指数爬虫node库。当然还有许多优化的方法,比如批量爬取,指定天数爬取等,只要在这个基础上实现都不难了。

const recognition = require('./src/recognition');
const Spider = require('./src/spider');module.exports = {async run (word, options, puppeteerOptions = { headless: true }) {const spider = new Spider({ imgDir, ...options }, puppeteerOptions);// 抓取数据await spider.run(word);// 读取抓取到的截图,做图像识别const wordDir = path.resolve(imgDir, word);const imgNames = fs.readdirSync(wordDir);const result = [];imgNames = imgNames.filter(item => path.extname(item) === '.png');for (let i = 0; i < imgNames.length; i++) {const imgPath = path.resolve(wordDir, imgNames[i]);const val = await recognition.run(imgPath);result.push(val);}return result;}
}
复制代码

反爬虫

最后,如何抵挡这种爬虫呢,个人认为通过判断鼠标移动轨迹可能是一种方法。当然前端没有100%的反爬虫手段,我们能做的只是给爬虫增加一点难度。

Node: Puppeteer + 图像识别 实现百度指数爬虫相关推荐

  1. 爬虫之js加密参数破解练习-百度指数爬虫(附完整源码)

    百度指数爬虫 前言 分析 查看响应体 找到加密的代码块 python实现解密过程 完整代码 前言 完整源码如因环境问题无法运行(没有安装node环境),将解密部分换成python(已在博客中附上)即可 ...

  2. 爬取百度知道分类_百度指数爬虫|介绍篇

    简单介绍 前段时间帮别人写了几个爬虫,其中有一个是爬取百度指数.绝大多数人应该都知道这个东西,我在这里再说明一下哈! 百度指数是百度提供的可以查看人们每天搜索关键词的次数的功能,具体长下面这个样子: ...

  3. 爬虫天坑系列-百度指数爬虫

    原文地址:http://blog.shenjianshou.cn/?p=170 giithub:https://github.com/TTyb/Baiduindex 最近有很多朋友跟我说," ...

  4. 百度指数爬虫城市对应代码

    DROP TABLE IF EXISTS baidu_provice_tmp;CREATE TABLE IF NOT EXISTS baidu_provice_tmp (num STRING ,pro ...

  5. 百度指数、360指数爬虫python版:基于selenium+chrome和图像识别技术

    如果需要帮忙爬取数据,请加QQ:2422035338 一.前言: 1.本博客主要介绍百度指数爬取,360指数获取类似: 2.想要获取数据必须先登录百度指数,频繁登陆会导致要求输入验证码和手机验证码: ...

  6. 【Python爬虫】百度指数爬取+导入数据库+QuickBI展示

    百度指数爬取原文在这里:如何用Python下载百度指数的数据_小小明-代码实体的专栏-CSDN博客 00.序言 一直想把百度指数每天定时爬下来,然后放到Dashboard里展示,终于,我看到了大神给出 ...

  7. python 时间序列突变检测_Python 百度指数突变点检测

    百度指数是一款非常好用的工具,通过它我们能知道某些关键词在过去的一些日子里的热度变化趋势并能够对这些数据进行分析.如果能用得好百度指数,我们将能产出巨大的价值.你可以通过关注文章下方的Python实用 ...

  8. 探索百度指数与股价的关系

    探索百度指数与股价的关系 前言 百度指数代表着某个词在互联网的热度,心血来潮,想探索一下百度指数与相关企业股价之间是否有关系.本文选取四家车企,分别为CC汽车,BYD,SQ,CA汽车.(股价数据来源t ...

  9. py获取前端的参数_获取百度指数

    百度指数简介 百度指数有一个详细的帮助文档,下面列出来的几个点是我的个人总结: 百度指数是度量网民搜索量多寡的指数,可以用来描述社会对某某某的关注度. 百度指数大众版不要钱,百度指数专业版要钱,但不对 ...

最新文章

  1. 她们,在字节跳动写代码
  2. Android 隐藏软键盘
  3. smartClient 2--可视化组件
  4. QT Creator应用程序开发——01简单按钮显示
  5. 人工智能与大数据的完美结合 1
  6. 用uGUI开发自定义Toggle Slider控件
  7. 推荐几个好评率超高的公众号,有远见的程序员都关注了!
  8. oracle sql语句中有关null使用的一点理解
  9. lol游戏挂机软件_“本不想挂机,但系统不让重连!”LOL成“挂机联盟”,5局3挂机...
  10. 判断四边形凹凸性及凹点
  11. 拼插机器人课和围棋课_乐高机器人玩具与机器人教育有什么区别?
  12. java读取libs下文件_Android开发中libs和jinLibs文件夹的作用详解
  13. 【生活感想】期末考试
  14. Sniffing_Spoofing Report
  15. Android 内部存储和外部存储
  16. Android程序员必备,offer拿到手软
  17. 清代国画大师孙温绘全本《红楼梦》系列数字藏品即将上线!
  18. android 黑色透明背景,解决Android png透明图片转jpg时背景变黑的问题
  19. MYSQL 基本练习
  20. pandas的loc[ ]和iloc[ ]方法解析

热门文章

  1. 我想去远方,我想出去走走,我想到处看看!!
  2. Android编程--常用代码
  3. 服务端解决故障的处理思路
  4. 验证码破解:极验3.0滑动验证码破解最新俩种方法
  5. pip 升级到最近21.0.1 后报错 sys.stderr.write(f“ERROR: {exc}“)
  6. 为什么公有云在中国落地难
  7. maskrcnn_benchmark代码分析(2)
  8. 移动web开发要点总结
  9. 生产者消费者模式解决强耦合问题
  10. win2003 启用了Internet Explorer增强的安全配置