简单网络爬虫实现
背景 有个朋友需要将湖北碳排放权交易中心的成交概况数据总揽表.有将近2000页的数据, 如果考人工一个一个去复制粘贴, 估计她会砸电脑吧. 就是这个网页的表格内容: http://www.hbets.cn/index.php/index-show-tid-11.html
目标 把这个页面的所有页数据塞到一个excel里面
爬取原理 使用headless浏览器模拟人工将所有页面打开, 然后去抓取对应dom节点文本数据.支持这个操作的框架有很多, nightmare, phantomjs, puppeteer等, pyhon 环境下有 robot Framework. 这几个都有尝试过, 最后选用pupeteer. robot framework 简直就是反人类.前面三个都是nodejs环境运行的. 然, puppeteer 是google开源的, 同时, await async 加持, JS 开发者都知道这意味着什么.
核心代码 const puppeteer = require('puppeteer'), fs = require('fs'), $ = require('jquery'), path = require('path'); const XLSX = require("xlsx"); const WorkBook = require("./workbook"); let bigSheet = [ ['试点地区', '成交价', '当日成交量( 吨)', '当日成交额( 元)', '日期'] ]; (async () => { const browser = await puppeteer.launch({ executablePath: 'D:/Users/steven.zhu/AppData/Local/Chromium/Application/chrome.exe', headless: true, }); let getOnePage = async (url, maxPage) => { const page = await browser.newPage(); await page.goto(url, { waitUntil: 'networkidle2' }); await page.setJavaScriptEnabled(true); // await page.screenshot({ // path: 'hn.png', // format: 'A4' // }); await page.waitFor(1200); let oneSheet = await page.evaluate(() => { let sheet = []; let uls = $(".future_table ul.cont"); uls.each((i, obj) => { console.log(i, obj) let one = []; one.push($(".future_table ul.cont").eq(i).find('.li1').html()); one.push($(".future_table ul.cont").eq(i).find('.li2').html()); one.push($(".future_table ul.cont").eq(i).find('.li3').html()); one.push($(".future_table ul.cont").eq(i).find('.li4').html()); one.push($(".future_table ul.cont").eq(i).find('.li5').html()); sheet.push(one); }); return sheet;; }); bigSheet = [].concat(bigSheet, oneSheet) page.once('load', () => console.log('Page loaded!')); await page.close() url.match(/&p=(\w*)$/) if (RegExp.$1 == maxPage){ await setTimeout(()=>{ browser.close(); },5000) } }; (async () => { let getAllPage = (i, maxPage) => { console.log('抓取进度:', i + '/' + maxPage) getOnePage( "http://www.hbets.cn/index.php/index-show-tid-11.html?&p=" + i, maxPage ); if (i <= maxPage) { setTimeout(() => { getAllPage(++i, maxPage) }, 1000) } else { console.log('>>>>', bigSheet) workbook = new WorkBook({ Sheet1: bigSheet }) workbook.writeFile('xxx.xlsx') } } getAllPage(1, 1000) console.log('hehe') })() })() 结语 随手写的, 代码比较简单, 凑合看吧. 并不是多了几个文件夹名称就是架构好吗>_<