首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

利用正则表达式从统计公报中爬取信息形成结构化统计数据

1 引言

现在是毕业季,相信很多同学都在忙着毕业论文,而毕业论文中最关键的问题之一就是数据来源,正所谓巧妇难为无米之炊,即使再厉害的文笔,没有一份好的数据也很难写出漂亮的论文。而在如今信息化的时代,数据来源的渠道有很多种,比如现成的统计年鉴、各种机构出的调查数据等等。但有时候,我们需要用到一些县级层面的数据时,只有去统计公报中找,当然我们大可以受到复制粘贴去抽取出我们需要的信息,在需要的数据量很少时,不妨这样做,但当我们需要的数据量比较大时,就可以考虑利用计算机程序语言来完成了。因此,本文基于收集数据的目的,讲述如何用正则表达式从连片的文字信息中抽取出我们需要的数据,并形成结构化的数据表,而正则表达式的实现则用如今炙手可热的python,python中有个re库是实现正则表达式的。

本文的内容安排如下:第2章简单概括正则表达式的基本语法(说明:包括三段代码快,待匹配文本、匹配模式和匹配结果,匹配到的字符串用粗体表示),第3章讲用python的re库实现正则表达式,第4章进行实战操作,第5章注意事项。

2 正则表达式的基本语法

2.1 匹配单个字符

待匹配文本

匹配模式

匹配结果

注意:正则表达式区分大小写,因此jicyoum不能匹配JicYoum

多个结果的情况

匹配模式

匹配结果

2.1.1 匹配任意字符

待匹配文本

匹配模式

. 可以匹配任何单个字符包括本身,不能匹配换行符。(计算机中有换行符和回车符,可自行百度了解)

2.1.2 匹配特殊字符

匹配模式

当我们要匹配“.”字符时,我们要告诉正则表达式,我们要匹配字符本身而不是其代表的“任何字符”,因此我们使用元字符 \ (转义字符,表示“这个字符有特殊的含义,而不是字符本身的含义”),因此 . 代表一个普通的点字符。

2.2 匹配一组字符

2.2.1 匹配一组字符中的一个

匹配模式

[和]不匹配任何字符,用来定义一个字符集合,此处匹配任意以n或s开题的字符串

思考:如何去除一个字符变量a的空白字符和换行符,a.replace('\s','').replace('\n', '') 在学正则表达式前我一般这样做,利用正则表达式re.sub(patter,relacement,sting)有更好的处理方式。

2.2.2 利用字符集合区间

匹配模式

只有在[]里才是具有特殊意愿的连字符,否则只是普通字符,尾字符不能比首字符小,否则就没意义,常用字符集合还有[A-Z], [a-z]

2.2.3 取非匹配

待匹配文本

匹配模式

^ 只有在字符集合里才表示取非,否则表示一个匹配模式的开头

2.3 使用元字符

空白元字符

空白字符元字符

数字字母元字符

2.4 重复匹配

贪婪匹配与非贪婪匹配?

2.5 位置匹配

2.6 子表达式

定义:子表达式是一个更大的表达式的一部分,把一个表达式划分为一系列子表达式的目的是为了把那些子表达式当做独立元素来使用。

待匹配文本

匹配模式

匹配结果

子表达式

正则表达式还有引用、前后查找、嵌套条件等内容,推荐看《正则表达式必知必会》

3 正则表达式的python实现:re模块

python正则表达式基本语法与第二章所述基本一致,有补充之处可以参考官方文档python regular expression operation

re模块中处理字符串的方法主要有:re.match(),re.search(),re.findall(),re.sub(),re.split()

前3个方法是用来搜寻匹配字符串。

re.match()和re.search()主要区别是re.match()需要从字符串的开头匹配,而re.search()可以从整个文本中搜寻匹配,两个方法返回的都是一个match对象

可以进一步对这个match对象采用group方法

match.group(0),返回的是匹配结果本身,match.group(1-),返回的匹配结果中的子匹配,也可以用match.groups(),以元组的形式返回所有子匹配结果

re.findall()和前连个方法的区别是,它返回的是一个match对象的列表。

re.sub()和re.split()分别用正则表达式对字符串进行替换和切割操作。

4 用正则表达式爬取统计公报数据

4.1 确定爬取目标

我们以中国最有名的县之一——凤凰县为例,来说说明正则表达式的应用,首先我们需要去凤凰县的政府网站确定其统计公报的发布网址如下:

urls = {

2017: 'http://www.fhzf.gov.cn/zwgk/xzfxxgkml/tjxx/201803/t20180316_871446.html',

2016: 'http://www.fhzf.gov.cn/zwgk/xzfxxgkml/tjxx/201706/t20170614_706524.html',

2015: 'http://www.fhzf.gov.cn/zwgk/xzfxxgkml/tjxx/201609/t20160924_311672.html',

}

作为研究案例,就选取凤凰县2015-2017年三年的统计年鉴作为爬虫目标,而需要爬取的指标如下表所示,都是一些常规的经济指标。

4.2 爬取实战

直接先上代码

最终爬取的结果如下:

凤凰县指标.png

代码解读:代码的主体是定义了一个获取指标数据的函数,然后利用循环爬取三年的数据,用到的模块是实现正则表达式的re模块、模拟浏览器获取网站信息的requests模块、解析网页的BeautifulSoup模块,以及用于数据处理的numpy和pandas模块。

头部信息:由于政府网站可能会有些限制,因此加入浏览器头伪装成浏览器访问,浏览器头部信息存在USER_AGENT_LIST中,每次访问随机从中取一个。

获取网页内容并解析:用requests获取网页内容,并用BeautifulSoup解析取得统计公报的完整内容。

用正则表达获取指标数据:正则表达式中有7个用括号括起来的子表达式,代表需要爬取的7个指标数据。([\d.\w]+?),其中\d.代表一个数字,由于可能是小数所以家里''.'',用\w把单位也爬下来+?表示非贪婪匹配。

把结果返回到一个字典中。

利用循环把爬取的各年的字典结构的数据加入列表中,然后用pandas把其转化成数据框。

5 注意事项

本文的例子是相对比较简单和理想的情况,在实际应用中,特别是要爬取的年份比较多的时候,可能每年统计公报的差异会表较大,这时候需要获取数据就要编写逻辑更复杂的正则表达式。但有时候如果,正则表达式编写的难度太大,需要花费太多精力,还不如放弃那一两个指标,把很难解决的问题直接用复制粘贴替代,有时候反而能节约时间精力。因为,正则表达式本身的目的就是使复杂问题简单、高效,有的时候为了写出一个“高大上”的正则表达式而浪费大量时间是得不偿失的。

下期预告:

暂定:R语言中正则表达式的应用,感兴趣的同学可以随便关注下微信公众号:Python__R

微信公众号二维码.jpg

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180414G1DE3A00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券