js 逆向爬取报销发票(二)

接上文,没看过的可以点击这里,juejin.cn/post/733240...。继续把上文没完成的内容补充完成。

puppeteer 介绍

Puppeteer 是一个由 Google Chrome 团队开发的 Node 库,它提供了一套高级 API 来通过 DevTools 协议控制无头 Chrome 或 Chromium。无头浏览器是没有图形界面的浏览器,它允许开发者在服务器上运行网页,进行自动化测试、抓取网页内容、生成页面截图或 PDF 等操作。

puppeteer 安装

bash 复制代码
npm i puppeteer

编写 downloadTicket 函数

遍历上文中生成的 data.json,解析出 receiptUrl 并使用 puppeteer 打开,等待页面加载完成后,可以使用 cheeroi 库来获取到发票对应的 dom 元素,然后拿到其 url,示例代码如下:

javascript 复制代码
async function downloadTicket(url) {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto(url, {
    waitUntil: 'networkidle0',
  });

  const content = await page.content();
  const $ = cheerio.load(content);
  const imgUrl = $('.my-gallery a').attr('href');

  console.log(imgUrl);

  await browser.close();
}

执行后我们就可以拿到这张发票对应的地址了

接下来,我们使用 request 结合 stream 来下载该发票

javascript 复制代码
const filePath = './test.png';

var stream = fs.createWriteStream(filePath);

request(imgUrl)
	.pipe(stream)
	.on('close', function () {
	    console.log('done');
	});

把这段代码放入 downloadTicket 函数中执行后,就可以看到当前目录下多了一个 test.png 的发票文件了

结构化发票文件

按照科室对发票进行分类下载,首先第一步遍历 data.json 获取到所有的科室信息,然后根据科室名称创建对应的目录,将发票下载到相应的目录

javascript 复制代码
async function main() {
  for (let record of recordList) {
    const {payTime, deptName, typeName, money, receiptUrl, receiNo} = record;    
    const dirName = category.includes(deptName) ? deptName : other;
    const filePath = `./${dirName}/${receiNo}.png`;

    if (!fs.existsSync(filePath)) {
      await downloadTicket(receiptUrl, filePath);
    } else {
      console.log('exist');
    }
  }
}

这样就大功告成了~等等,要是再有一个用于统计 excel 就更好了,也很简单

安装 node-xlsx

bash 复制代码
npm i node-xlsx -D

改造一下上面的 main 函数,把数据保存起来,最后一起写入到 excel 中,如下

javascript 复制代码
async function run() {
  const data = [['时间', '科室', '类型', '费用']];

  for (let record of recordList) {
    const {payTime, deptName, typeName, money, receiptUrl, receiNo} = record;
    data.push([payTime, deptName, typeName, money, receiptUrl]);
    const dirName = category.includes(deptName) ? deptName : other;
    const filePath = `./${dirName}/${receiNo}.png`;

    if (!fs.existsSync(filePath)) {
      await downloadTicket(receiptUrl, filePath);
    } else {
      console.log('exist');
    }
  }

  var buffer = xlsx.build([{name: 'sheet', data: data}]);
  fs.writeFileSync('result.xlsx', buffer, {flag: 'w'});
}

执行后就生成了一个 result.xlsx 文件,打开后内容如下
搞定~

相关推荐
岳哥i17 分钟前
vue鼠标单机复制文本
javascript
幻云20101 小时前
Python深度学习:从筑基到登仙
前端·javascript·vue.js·人工智能·python
我即将远走丶或许也能高飞3 小时前
vuex 和 pinia 的学习使用
开发语言·前端·javascript
爱吃泡芙的小白白3 小时前
Vue 3 核心原理与实战:从响应式到企业级应用
前端·javascript·vue.js
码上成长4 小时前
JavaScript 数组合并性能优化:扩展运算符 vs concat vs 循环 push
开发语言·javascript·ecmascript
油丶酸萝卜别吃4 小时前
Mapbox GL JS 表达式 (expression) 条件样式设置 完全指南
开发语言·javascript·ecmascript
摘星编程5 小时前
用React Native开发OpenHarmony应用:timing定时动画参数
javascript·react native·react.js
JosieBook5 小时前
【Vue】12 Vue技术—— Vue 事件修饰符详解:掌握事件处理的高级技巧
前端·javascript·vue.js
摘星编程5 小时前
在OpenHarmony上用React Native实现AnimatedValue补间动画
javascript·react native·react.js
摘星编程6 小时前
React Native鸿蒙版:AnimatedXY双轴动画完整代码
javascript·react native·react.js