网站上经常会使用省市区数据,正好最近正在学习Egg.js,于是就尝试Egg.js采集统计局上面的数据。
搭建环境
$ mkdir egg-example
$ cd egg-example
$ npm init
$ npm i egg --save
$ npm i egg-bin --save-dev
添加 npm scripts 到 package.json:
{
"name": "egg-example",
"scripts": {
"dev": "egg-bin dev"
}
}
编写 Controller
我们第一步需要编写的是 Controller 和 Router。
// app/controller/home.js
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
this.ctx.body = 'Hello world';
}
}
module.exports = HomeController;
配置路由映射:
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
};
加一个配置文件:
// config/config.default.js
exports.keys = <此处改为你自己的 Cookie 安全字符串>;
此时目录结构如下:
egg-example
├── app
│ ├── controller
│ │ └── home.js
│ └── router.js
├── config
│ └── config.default.js
└── package.json
现在可以启动应用来体验下
$ npm run dev
$ open localhost:7001
html结构
分析页面结构,页面2018年统计用区划代码和城乡划分代码
其中关于城市的的截图:
代码结构如下:
假如用Jquery ,可以这样获取数据:
$('.provincetr').each(function(i,tr){
$(tr).children().each(function(j,td){
console.log($(td).text()); //省份名称
console.log($(td).find('a').attr('href')) //市区内容链接
})
});
获取到的省份以及包含市区内容链接:
然后在抓取市区页面去得到市区的列表,
比如:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2018/13.html 是河北省的所有城市的内容。
以此类推,直至获取到所有需要的数据。
工具
cheerio是一个以jquery语法为核心的服务器爬虫库,大部分的用法和Jquery很相似。
npm i cheerio --save
iconv-lite 防止乱码,目标页面的编码gb2312。
npm i iconv-lite --save
开发
首先在app/controller/ 下新建一个area.js,该控制器用来获取数据,代码如下:
const Controller = require('egg').Controller;
var cheerio = require('cheerio');
var iconv = require('iconv-lite');
//基础链接
const baseUrl="http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2018/";
class AreaController extends Controller {
async getArea() {
const province =await this.getProvince();
await this.getCity(province);
this.ctx.body=province;
}
async getProvince(){
var me=this;
let url=baseUrl+'index.html'; //页面地址
let provice=[]; //存储数据
const {data}=await this.ctx.curl(url); //抓取页面
let $ = cheerio.load(iconv.decode(data,'gb2312'));
$('.provincetr').each(function(i,tr){
$(tr).children().each(function(j,td){ //解析数据
var name=$(td).text();
var link=$(td).find('a').attr('href');
let obj={
name:name,
code:link.substr(0,2),
children:[]
};
provice.push(obj);
});
});
return provice;
}
async getCity(province){
for(let i=0;i<province.length;i++){
let cityLink=baseUrl+province[i].code+'.html';
const {data}=await this.ctx.curl(cityLink);
let $ = cheerio.load(iconv.decode(data,'gb2312'));
$('.citytr').each(function(i,tr){
var code=$(tr).find('td').first().text();
var name=$(tr).find('td').last().text();
var link=$(tr).find('a').attr('href');
let obj={
name:name,
code:code,
};
province[i].children.push(obj);
});
}
}
}
module.exports = AreaController;
修改router.js 的代码:
router.get('/', controller.area.getArea);
访问:http://localhost:7001
最终获取的数据格式:
这里只介绍了获取省市的代码,其他获取更多的数据可以自行添加。
热门评论
基于egg.js的后台开发框架、权限管理、前后端分离 vue.js https://www.cool-admin.com