(原创)从网页上爬取行政区代码并通过身份证号码获取出生地

证监会近日出台了更为严格的风控监管法规,因而我得到了新的需求——重做风险评测,最后一项是要统计用户的居住地。产品设计是在用户填写之前,按照用户的身份证号码将用户居住地的默认值设为出生地。
实现是比较简单的,身份证前六位依次对应我们的省、市、县的行政代码,将各个行政代码与对应的地址以key-value(Python中的字典)的形式写成常量或者写入数据库,然后拿着身份证前六位查询即可。问题在于,需要先把行政代码拿到手,然后写为字典。

1.爬取行政区代码

先查找到国家最新公布的行政区划代码网站页面

1.png

我们可以拷贝进编辑器,但想要存为字典,就需要一行一行的手动修改格式。虽然也就3000多行吧,但身为一个程序员,哪怕是最初级的,也该有一个偷懒的心,更何况人生苦短我用Python

2.png

下面开始爬取操作,这么一个简单的网页不需要复杂的爬虫,使用urllib2+BeautifulSoup4(py2的搭配,py3中应该为urllib.request+BeautifulSoup3)就可以了
先进入python.exe/ipython.exe

3.png

得到404,说明网站还是做了基本的安全措施,需要加点料。
在Chrome浏览器按F12进入调试模式,按F5刷新,在Network中查看网页中对html的Request,然后拿到Headers中的几个重要的值:Host、User-Agent、Cookie,然后添加到我们自己的request中

4.png
5.png

但这个时候拿到的req并不能直接用,如果print(req)的话,会得到满屏幕的乱码。此时req的内容,是网页的html源代码,等于在网页查看的Request对应的Response。仔细查看Response的内容,终于在第368行找到了我们的目标,拷贝到编辑器中查看

6.png

这时候该BeautifulSoup4出场了,bs4支持多种解析器:Python标准库(“html.parser”)、lxml HTML 解析器(“lxml”)、lxml XML 解析器(“xml”)、html5lib(“html5lib”),并提供了强大的遍历和搜索方法,具体查看文档。

这里使用Python标准库解析器+find_all( name , attrs)搜索标签即可
观察可知行政区编码最里层的标签是<span>, 属性为lang="EN-US"

7.png

下一步就是把110000从"bs4.element.Tag"中取出来,观察发现每条数据的格式都是一样的,倘若可以转为string,然后index('>'),再取偏移6位即可

8.png

如上图所示,一番尝试得到了所有的行政区代码,下一步就是取得对应行政区名称了。
同样是观察可知行政区名称最里层的标签为<span>,属性为style="font-family: 宋体"

此处开始换电脑了,所以截图不一样
9.png

得到的结果是Unicode字符串,但感觉似乎有点不对劲,将areas和codes打印出来对比来看一下,Unicode字符print出来就会显示中文

10.png

发现地址列表中存在空格的情况,再加以处理即可

11.png

现在剩下最后一步了,按字典的格式输出打屏幕上,然后拷贝编辑器中。
话说当时我在这里脑子抽抽了,卡了半个多小时,尝试过直接赋值为字典或者使用codes写入文件再读取出来写成字典,发现地址显示出来的全是Unicode字符,最终在旁人点醒下才跳出思维得到自己要的。

12.png
13.png

想要存入本地文件的话,需要使用codecs这个库,Unicode不能直接写入文件。
完整的代码如下:

import codecs
import urllib2
import sys

from bs4 import BeautifulSoup

url = 'http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201703/t20170310_1471429.html'
headers = {
    'Host': 'www.stats.gov.cn',
    'User-Agent': 'ozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36',
    'Cookie': 'AD_RS_COOKIE=20083363; _gscu_1771678062=957855112bjaz048; _gscs_1771678062=95785511u2vn7148|pv:5; _gscbrs_1771678062=1; _trs_uv=f3pk_6_j35k2nll; _trs_ua_s_1=i5mz_6_j35k2nll',
}

try:
    request = urllib2.Request(url, headers=headers)
    response = urllib2.urlopen(request)
    req = response.read()
except urllib2.URLError, e:
    if hasattr(e, 'code'):
        print(e.code)
    if hasattr(e, 'reason'):
        print(e.reason)
    sys.exit(1)

soup = BeautifulSoup(req, "html.parser")
code_res = soup.find_all('span', attrs={'lang': 'EN-US'})
codes = [str(c)[19:25] for c in code_res]
area_res = soup.find_all('span', attrs={'style': 'font-family: 宋体'})
areas = [a.text.strip() for a in area_res if a.text.strip()]

# 按字典的书写格式输出,避免手动加引号
# for i in range(len(codes)):                       
#    print '    "%s": u"%s",' % (codes[i], areas[i])

with codecs.open('./res.txt', 'w', 'utf-8') as f:
    for i in range(len(codes)):
        f.write(codes[i] + ':' + areas[i] + '\n')

2.通过身份证号码获取用户出生地信息

从网上可以查的18位身份证号码的编排规则,以及最后一位的校验规则

12.png
13.png

如下处理即可

# 一共3508条,不全给出
areacode = {            # 截止2016年7月31日
    "110000": u"北京市",
    "110100": u"市辖区",
    ...
}

# 校验18位身份证号码的合法性
def vertify(id):
    c = 0
    ckeck_codes = '10X98765432'         # 校验码
    for (a, p) in zip(map(int, id[:-1]), range(17, 0, -1)):
        w = (2 ** p) % 11
        c += a * w
    return id[-1] == ckeck_codes[c % 11]

# 获取出生地信息
def area(id):
    province = id[0:2]
    municipal = id[2:4]
    county = id[4:6]
    return (areacode[province + "0000"],
            areacode[province + municipal + "00"],
            areacode[province + municipal + county])

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容