第一次个人编程作业

第一次个人编程作业

博客作业求高分 嘻嘻!!

1.GITHUB链接

2.PSP表格估计时间

PSP2.1 Personal Software Process Stages 预估耗时(分钟)
Planning 计划 60
· Estimate · 估计这个任务需要多少时间 60
Development 开发 1170
· Analysis · 需求分析 (包括学习新技术) 60
· Design Spec · 生成设计文档 30
· Design Review · 设计复审 40
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 60
· Design · 具体设计 100
· Coding · 具体编码 420
· Code Review · 代码复审 120
· Test · 测试(自我测试,修改代码,提交修改) 120
Reporting 报告 60
· Test Repor · 测试报告 60
· Size Measurement · 计算工作量 60
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 40
1375 · 合计 1230

3.计算模块接口的设计与实现过程

3.1接口思路描述

(1)首先主程序分析字符串分离出level和字符串数据,然后调用我自己写的parseAddr尝试分离出五级地址

(2)在parseAddr库中,根据之前的level等级,从而判断是否要在分离五级地址的时候,补全缺失的地址

(3)分离出五级地址后,根据level等级,判断是否需要继续将详细地址分离成 路名+门牌号+详细地址

(4)如果需要补全七级地址则需要调用高德地图的API,先通过模糊地址解析处经纬度,然后利用经纬度逆地址解析.根据逆地址解析得到的详细地址,从而分离出门牌号和路名

ParseAddr 接口代码:

def parse(self,addr):
        provinces,cities,countries,towns=self.provinces,self.cities,self.countries,self.towns
        #找出省
        #print(provinces,cities,countries,towns)
        dic={
            'province':'',
            'city':'',
            'country':'',
            'town':'',
            'detail':'',
        }
        for i in abbrProvinces:
            if i in addr and ( addr.find(i)==0):#保证第一个省正确
                dic['province']=allProvinces[abbrProvinces.index(i)]
                if dic['province'] in ['北京','天津','上海','重庆']:
                    dic['city']=dic['province']+'市'
                break
        if dic['province']=='':
            for i in cities:
                if (cities[i]['city'] or cities[i]['city'][:-1]) in addr:
                    dic['provnice']=provinces[cities[i]['city_id'][:2]+10*'0']
                    break
        if dic['province']=='':
            for i in countries:
                if countries[i]['country'] in addr:
                    dic['province']=provinces[countries[i]['country_id'][:2]+10*'0']
                    break
        if dic['province'] == '':
            for i in towns:
                if towns[i]['town'] in addr:
                    dic['province']=provinces[towns[i]['town_id'][:2]+10*'0']
        #print(dic['province'])
        province_id = provinces[dic['province']]
        if dic['province']:
            if (dic['province'][-1] == '省') or (dic['province'] in ['北京', '天津', '重庆', '上海']):
                if dic['province'] in ['北京', '天津', '重庆', '上海']:
                    # match=re.match(dic['province'],addr)
                    dic['city']=dic['province']+'市'
                    span = addr.find(dic['province']) + len(dic['province'])
                    if addr[span] == '市':
                        addr = addr.replace(dic['city'], '', 1)
                    else:
                        addr = addr.replace(dic['province'], '', 1)
                else:
                    span = addr.find(abbrProvinces[allProvinces.index(dic['province'])]) + len(
                        abbrProvinces[allProvinces.index(dic['province'])])
                    # print(match.span())
                    if addr[span] == '省':
                        addr = addr.replace(dic['province'], '', 1)
                    else:  # 后面没有省
                        addr = addr.replace(dic['province'][:-1], '', 1)
            else:
                addr = addr.replace(dic['province'], '', 1)


        if dic['city'] == '':
            for i in cities:
                if i[:2]==province_id[:2]:#保证分词正确
                    if (cities[i]['city'] in  addr) and addr.find(cities[i]['city']) ==0:
                        dic['city']=cities[i]['city']
                    if  ((cities[i]['city'][:-1]) in addr ) and ( addr.find(cities[i]['city'][:-1])==0):
                        dic['city']=cities[i]['city']

        #找到县
        if dic['city']:
            if (not (dic['province'] in ['北京', '天津', '重庆', '上海'])) and (dic['city'][-1] == '市'):
                span = addr.find(dic['city'][:-1]) + len(dic['city'][:-1])
                if addr[span] == '市':
                    addr = addr.replace(dic['city'], '', 1)
                else:
                    addr = addr.replace(dic['city'][:-1], '', 1)
            else:
                addr = addr.replace(dic['city'], '', 1)

        for i in countries:
            #print(countries[i])
            if (countries[i]['country']  in addr) and (province_id[:2]==countries[i]['country_id'][:2]) :
                if addr.find(countries[i]['country'])==0:
                    dic['country'] = countries[i]['country']
                    addr=addr.replace(dic['country'],'',1)
                    if dic['city']=='' :
                        if i[:4]+8*'0' in cities:
                            dic['city']=cities[i[:4]+8*'0']['city']
                    break
        if dic['city']:
            if (not (dic['province'] in ['北京', '天津', '重庆', '上海'])) and (dic['city'][-1] == '市'):
                span = addr.find(dic['city'][:-1]) + len(dic['city'][:-1])
                if addr[span] == '市':
                    addr = addr.replace(dic['city'], '', 1)
                else:
                    addr = addr.replace(dic['city'][:-1], '', 1)
            else:
                addr = addr.replace(dic['city'], '', 1)
        for i in towns:
            #print(towns[i])
            if (re.findall(towns[i]['town'],addr) ) and (province_id[:2]==towns[i]['town_id'][:2]):
                if addr.find(towns[i]['town'])==0:
                    #print(towns[i]['town'])
                    dic['town']=towns[i]['town']
                    addr=addr.replace(dic['town'],'',1)
                    if dic['city']=='':
                        if i[:4]+8*'0' in cities:
                            dic['city']=cities[i[:4]+8*'0']['city']
                    if dic['country']=='':
                        if i[:7]+5*'0' in countries:
                            dic['country'] = countries[i[:7] + 5 * '0']['country']
                    break

        if dic['city']:
            if (not (dic['province'] in ['北京', '天津', '重庆', '上海'])) and (dic['city'][-1] == '市'):
                span = addr.find(dic['city'][:-1]) + len(dic['city'][:-1])
                if addr[span] == '市':
                    addr = addr.replace(dic['city'], '', 1)
                else:
                    addr = addr.replace(dic['city'][:-1], '', 1)
            else:
                addr = addr.replace(dic['city'], '', 1)

        # addr = addr.replace(dic['town'], '', 1)
        # addr = addr.replace(dic['country'], '', 1)
        dic['detail'] = addr
        #print(dic)
        return dic

3.2接口流程图

3.3 实现过程和算法说明

(1)parseAddr库中有一个Load()类,初始化类后,将会加载4个xlsx文件,分别存入四个字典:省,市,县,乡.

Load()库下有两个函数,一个是补全函数,一个是剔除函数.补全函数用来补全五级地址,剔除函数用来剔除原本不存在的地址.

性能优点1:空间换时间 ;在构造省市县乡四级数据结构的时候,为了减少循环,提升查找效率。我是用了双向字典。将键-值存在字典后,并将二者调换位置,再次存下。

性能优点2:快速查询;在爬取城乡区域信息时,发现城乡区域代码的一种继承关系。只需要取前两位数字得到省级,前四位得到市级...等等

(2)GDAPI,利用在高德地图平台上申请的key,调用API,使用地址/逆地址解析接口,从而拿到七级地址.

(3)在主文件中对返回的五级地址或七级地址进行处理,得到正确的答案.

4.计算模块接口部分的性能改进

4.1接口结构调整

将部分功能相似的函数进行了整合,形成一个函数,通过对参数的控制,从而产生不同结果.

将GDAPI和parseAddr模块整合,打造出分析地址出神入化的一个python库,最近准备开源它.

4.2接口性能改进

将一些暴力for循环的模块,重写成一些数据结构,如双向字典,快速hash出我想要的结果.

引用一些其他的库,替换自己字符串模拟,提高自己的数据处理速度.

在性能分析工具Profile下,有这样的显示,的对我自己写函数api_code调用非常频繁.(因为我平凡的调用了高德API)

(1)在数据加载上的时间非常少.

(2)大量时间花费在了调用系统函数上

(3)对Split()函数压力太大,没有合理的分配函数的功能

5.计算模块部分单元测试展示

5.1 数据构造思路

根据数据制作者的思路,首先在国家统计局上爬取31个省市县乡村的行政信息,然后调用菜鸟物流的API,进行模糊搜索,得到一组数据大约1000条.这样构造的数据将会非常近似原生数据

5.2 单元测试覆盖率截图

(1) parseAddr

(2)GDAPI

(3)整体测评

6.计算模块部分异常处理说明

样例测试

1!晏孔,重庆巫山13097181946县大昌镇洋溪村便民超市.
1!荆麻,13282875332天津市北淮淀镇乐善庄村乐善庄小学.
1!诸葛宁盛,河南省15613629652焦作市山阳区定和街道塔南路287号新兴日化.
1!冯昔唉,安徽省合肥市庐江县郭河镇G3京台高18835354291速合肥市庐江县广寒桥街道.
1!百里屏闷,广西壮族自治区桂林市灵川县潭13315249688下镇004乡道灵川县潭下镇大义村民委员会.
1!徐扼负,天津市河北区月牙河街道大江里58号楼13289199578.
1!娄缠壮,山东省烟台莱山14732355817区莱山街道南陈家疃小区10栋.
1!曹持,江苏泰州13066409994市海陵区迎宾路88号春兰商务酒店.
1!赫连谴,北京市桥梓镇214县道中共沙峪口村支13827008064部委员会.
1!督坠,浙江淳安县中洲镇杨畈线畈头村18682392149村邮站.
1!桓猿攀,13898044414辽宁省营口市盖州市西海街道305国道盖州市西海农场.
1!通描哗,山西省临汾市安泽县冀氏镇北孔滩村13228042359村委会.
1!卓斧,贵州省贵阳清镇市红枫街164号青龙街道办事处13949510110.

(1)异常处理1:

在程序运行中很显然会出现数据结构错误如:字典键值缺失——KeyError。

解决方法:try ... except ... 处理异常并构造强力数据,保证代码全被覆盖到。

(2)异常处理2:

当数据可能是极端数据(边界数据)时,会导致程序无法承受的错误,甚至无法继续运行下去。

例如:index out of range。

解决方案:构造边界数据,并使用try ... except ...处理异常

(3)异常处理3:

当网络出现波动时,API调用出现问题。

解决方法:这时应该考虑sleep主线程,并及时保护现场,将数据写入指定文本。

7.PSP表格实际时间

PSP2.1 Personal Software Process Stages 实际耗时(分钟)
Planning 计划 40
· Estimate · 估计这个任务需要多少时间 40
Development 开发 1335
· Analysis · 需求分析 (包括学习新技术) 120
· Design Spec · 生成设计文档 20
· Design Review · 设计复审 60
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 70
· Design · 具体设计 80
· Coding · 具体编码 400
· Code Review · 代码复审 90
· Test · 测试(自我测试,修改代码,提交修改) 240
Reporting 报告 80
· Test Repor · 测试报告 75
· Size Measurement · 计算工作量 40
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 60
· 合计 1375
原文地址:https://www.cnblogs.com/JustNo/p/11609855.html