第一次个人编程作业

1.GitHub

< https://github.com/hsthy/031702426>

2.PSP表格

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

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

​ 写在最前面的是我的设计思路。
​ 切分难度等级和姓名、手机号太简单了这里就不说了。下面只讲地址如何处理。
​ 在我们发布作业之前,柯逍老师班级发布这道题的时候,我就去看了下他们题目,顺便还写了点,不过由于上周在爆肝花朵识别就没继续写。
​ 看到题目的第一反应是调API解决。(这就是我在PSP表格里预期过于自信的原因)在上篇博客提到过利用百度智能云TTS的API,那会儿顺便看了下百度智能云的位置DuMap服务。
​ DuMap给了几个接口。初步想法是调用地理编码API将题目所给的文字位置信息转化为经纬度,然后调用逆向地理编码API将经纬度转回JSON格式的地理信息。所以预估题目用不了三小时就好了。。。。。。然后发现我天真了。。。。。。精度真的很差(辣鸡百度)。这个方法行不通后,我发现他还有个行政区划区域检索的接口,不过同样辣鸡。。。。。。举个栗子,写博客这晚我去的铜盘智园羽毛球馆,这是一个相对精确的地址,但是在这个API请求结果会跳出2个POI。。。像福州大学旗山校区玫瑰园食堂,他能返回好几个POI。。。。。。所以这个方法也不行。

​ 遂转战高德地图API,同样辣鸡。地理(正向/逆向)编码的API精度不够,行政区划的API仅仅允许一个关键词。。。而且是向下查询毫无卵用(其实还是有点用的,后面会提到高德的这个行政区划API)
​ 接下来就是最后实现的方法。这里的主要思路是查询这个表全国省市区县街道json\pcas-code.json,下载地址https://www.dssz.org/3385070.html 这个json其实可以通过上文提到的高德行政区划的API爬到或许更新的(鬼知道高德的数据新不新啊)数据。

​ 这里放一下请求地址:

https://restapi.amap.com/v3/config/district?keywords=地址关键字&subdistrict=2&key=<用户的key>

\ \ 区(县) \ 街道 这前四级都可以通过查表实现。每次通过字符串切片得到字符串前两个字符与四级行政区划json表格内容进行比对,过程就是一些for循环(缺失的情况下需要嵌套的for),最后得到第五级详细地址,在难度一中就完成了,在难度二中,需要对难度一的第五级详细地址用正则表达式进行匹配。具体可以看后面的代码。
​ 而难度三,由于没有API帮助,这里无法实现第四级,即街道这一级缺失的处理。(这里包括了同时缺失第四级和其他级别的情况)。难度三这里处理方法是多层for循环嵌套(数据量还是可以接受的查询速度不会很慢)尽管这个解法很水很水很水,但是最终还是得到了115/125(天枢星)||1094.8000000000588/1151(最终版测试工具)分数。

得分

下面是程序主要实现的函数
流程图

#定义标准答案的格式,名字+手机+七级地址

class Result:
    name = ""
    phone = ""
    province = ""#直辖市/省(省级)
    city = ""#直辖市/市(地级)
    area = ""#区/县/县级市(县级)
    town = ""#街道/镇/乡(乡镇级)
    street = ""#路名
    number = ""#门牌号
    building = ""#详细地址

#获取电话
def getphone(s):
    pattern = re.compile(r'1\d{10}')
    match = pattern.search(s)
    try:
        phone = match.group(0)
    except AttributeError:
        print("输入的手机号格式不正确")
    return phone
#去除混杂在中间的电话,获取混合的地址
def getaddress(s,phone):
    addressList=s.split(phone)
    address=""
    address=address.join(addressList)
    address=address[:-1]#切片去除句点
    return address
#去除字符串头部指定的子串
def cutdown(origin,child):
    limit=len(child)
    i = 0
    while i < limit:
        if origin[i] != child[i]:
            break
        i = i + 1
    return origin[i:]
    
def segementFive(add,res,jd):

    #直辖市/省(省级)
    match=add[:2]
    #print("匹配",match)
    for itemProvince in jd:
        if re.search(match,itemProvince["name"]):
            res.province = itemProvince["name"]
            cityList = itemProvince
            #print(res.province)
            add=cutdown(add,res.province)#混合地址去除省份

            #判断第一级是否为直辖市,若是,添加回字符串(第二级用
            for direct in ["北京","上海","天津","重庆"]:
                if direct == res.province:
                    add = res.province + add
            
            break
    if res.province == "":#目前台湾暂时没有数据
        return 
    #-------------------------------------------------------------------------        
    #直辖市/市(地级)
    flagCity=0#默认没有查找到
    match=add[:2]
    for itemCity in cityList["children"]:  
        if re.search(match,itemCity["name"]):
            flagCity=1
            res.city = itemCity["name"]
            #print(res.city)
            
            add = cutdown(add,res.city)
            areaList = itemCity
            break

    #-------------------------------------------------------------------------
    #区/县/县级市(县级)
    match=add[:2]
    flagArea=0
    if(flagCity==1):
        for itemArea in areaList["children"]:
            if re.search(match,itemArea["name"]):
                flagArea=1
                res.area=itemArea["name"]
                #print(res.area)
            
                add=cutdown(add,res.area)
                townList=itemArea
                break
    else:#处理市级缺失情况下的县级查找
        for itemCity in cityList["children"]:
            for itemArea in itemCity["children"]:
                if re.search(match,itemArea["name"]):
                    res.area=itemArea["name"]
                    #print(res.area)
                    add = cutdown(add,res.area)
                    townList=itemArea
                    flagArea=1
                    break
            else:
                continue
            break

    #---------------------------------------------------------------------
    #街道/镇/乡(乡镇级)
    match=add[:2]
    if (flagArea==1):
        for itemTown in townList["children"]:
            if re.search(match,itemTown["name"]):
                res.town = itemTown["name"]
                #print(res.town)
                add=cutdown(add,res.town)
                break
    else:#处理县级缺失情况下的乡镇级查找
        for itemArea in areaList["children"]:
            for itemTown in itemArea["children"]:
                if re.search(match,itemTown['name']):
                    res.town=itemTown["name"]
                    #print(res.town)
                    add=cutdown(add,res.town)
                    break
            else:
                continue
            break
    #---------------------------------------------------------------------
    res.street=add#在五级地址中使用street作为详细地址
    
def segementSeven(detail,res):    
    add=detail
    pattern=re.compile(r'(.*?[街])|(.*?[道])|(.*?[路])|(.*?[巷])|(.*?[大街])|(.*?[街道])')
    #pattern= re.compile(r'.+(路|街|巷|桥|道){1}')
    match = pattern.search(add)
    if(match):
        res.street = match.group(0)
    else:#可能存在缺失街道
        res.street = ""
    #print(res.street)
    add = cutdown(add,res.street)
    
    pattern=re.compile(r'(.*?[号])')
    #pattern = re.compile(r'.+(号){1}')
    match = pattern.search(add)
    if(match):
        res.number = match.group(0)
    else:#可能存在缺失门牌号
        res.number = ""
    #print(res.number)
    add = cutdown(add,res.number)
    res.building = add
    #print(res.building)

def enhancement(add,res,jd):
    
    #直辖市/省(省级)
    match=add[:2]
    #print("匹配",match)
    flagProvince=0#默认省级没有找到
    for itemProvince in jd:
        if re.search(match,itemProvince["name"]):
            flagProvince=1
            res.province = itemProvince["name"]
            cityList = itemProvince
            add=cutdown(add,res.province)#混合地址去除省份

            #判断第一级是否为直辖市,若是,添加回字符串(第二级用
            for direct in ["北京","上海","天津","重庆"]:
                if direct == res.province:
                    add = res.province + add
            break
    
    #-------------------------------------------------------------------------        
    #直辖市/市(地级)
    flagCity=0#默认没有查找到
    match=add[:2]
    if(flagProvince==1):
        for itemCity in cityList["children"]:  
            if re.search(match,itemCity["name"]):
                flagCity=1
                res.city = itemCity["name"]
                add = cutdown(add,res.city)
                areaList = itemCity
                break
    else:#处理省级缺失情况下的市级查找
        for itemProvince in jd:
            for itemCity in itemProvince["children"]:
                if re.search(match,itemCity["name"]):
                    flagCity=1
                    flagProvince=1
                    res.province=itemProvince["name"]
                    res.city=itemCity["name"]
                    add=cutdown(add,res.city)
                    areaList=itemCity
    #-------------------------------------------------------------------------
    #区/县/县级市(县级)
    match=add[:2]
    flagArea=0
    if(flagCity==1):
        for itemArea in areaList["children"]:
            if re.search(match,itemArea["name"]):
                flagArea=1
                res.area=itemArea["name"]
                add=cutdown(add,res.area)
                townList=itemArea
                break
    elif(flagCity==0 and flagProvince==1):#处理省级不缺失但是市级缺失情况下的县级查找
        for itemCity in cityList["children"]:
            for itemArea in itemCity["children"]:
                if re.search(match,itemArea["name"]):
                    flagCity=1
                    flagArea=1
                    res.city=itemCity["name"]
                    res.area=itemArea["name"]
                    add = cutdown(add,res.area)
                    townList=itemArea
                    break
            else:
                continue
            break
    else:#(flagCity==0 and flagProvince==0):#处理省级缺失并且市级缺失情况下的县级查找
        for itemProvince in jd:
            for itemCity in itemProvince["children"]:
                for itemArea in itemCity["children"]:
                    if re.search(match,itemArea["name"]):
                        flagProvince=1
                        flagCity=1
                        flagArea=1
                        res.province=itemProvince["name"]
                        res.city=itemCity["name"]
                        res.area=itemArea["name"]
                        add=cutdown(add,res.area)
                        townList=itemArea
                        break
                else:
                    continue
                break
            if(flagProvince==1):
                break
    #---------------------------------------------------------------------
    #街道/镇/乡(乡镇级)
    match=add[:2]
    flagTown=0#默认没有查找到
    if (flagArea==1):
        for itemTown in townList["children"]:
            if re.search(match,itemTown["name"]):
                res.town = itemTown["name"]
                #print(res.town)
                add=cutdown(add,res.town)
                break
    elif(flagArea==0 and flagCity==1):#处理市级不缺失但县级缺失情况下的乡镇级查找
        for itemArea in areaList["children"]:
            for itemTown in itemArea["children"]:
                if re.search(match,itemTown['name']):
                    res.area=itemArea["name"]
                    res.town=itemTown["name"]
                    #print(res.town)
                    add=cutdown(add,res.town)
                    break
            else:
                continue
            break
    else:#(flagArea==0 and flagCity==0)处理市级缺失并且县级缺失情况下的乡镇级查找
        for itemCity in cityList["children"]:
            for itemArea in itemCity["children"]:
                for itemTown in itemArea["children"]:
                    if re.search(match,itemTown["name"]):
                        flagCity=1
                        flagArea=1
                        flagTown=1
                        res.city=itemCity["name"]
                        res.area=itemArea["name"]
                        res.town=itemTown["name"]
                        add=cutdown(add,res.town)
                        break
                else:
                    continue
                break
            if(flagCity==1):
                break
    #---------------------------------------------------------------------
    pattern=re.compile(r'(.*?[街])|(.*?[道])|(.*?[路])|(.*?[巷])|(.*?[大街])|(.*?[街道])')
    #pattern= re.compile(r'.+(路|街|巷|桥|道){1}')
    match = pattern.search(add)
    if(match):
        res.street = match.group(0)
    else:#可能存在缺失街道
        res.street = ""
    #print(res.street)
    add = cutdown(add,res.street)
    
    pattern=re.compile(r'(.*?[号])')
    #pattern = re.compile(r'.+(号){1}')
    match = pattern.search(add)
    if(match):
        res.number = match.group(0)
    else:#可能存在缺失门牌号
        res.number = ""
    add = cutdown(add,res.number)
    res.building = add

def formatFive(res,dat):
    dat["姓名"]=res.name
    dat["手机"]=res.phone
    dat["地址"].append(res.province)
    dat["地址"].append(res.city)
    dat["地址"].append(res.area)
    dat["地址"].append(res.town)
    dat["地址"].append(res.street)

def formatSeven(res,dat):
    dat["姓名"]=res.name
    dat["手机"]=res.phone
    dat["地址"].append(res.province)
    dat["地址"].append(res.city)
    dat["地址"].append(res.area)
    dat["地址"].append(res.town)
    dat["地址"].append(res.street)
    dat["地址"].append(res.number)
    dat["地址"].append(res.building)
def solution(sourceStr,JD):#参数是原始字符串和js数据表
    #用于输出的json
    data={
        "姓名":"",
        "手机":"",
        "地址":[]
    }
    result = Result()#实例化结论格式
    s = ""
    s=sourceStr
    level = s.split("!")[0]#获取本条输入的难度
    level=eval(level)

    s=s.split("!")[1]#原始输入去掉"难度!"
    result.name = s.split(",")[0]#获取姓名

    s=s.split(",")[1]#原始输入剩余电话与地址
    phonenumber = getphone(s)#获取电话

    result.phone = phonenumber
    address=getaddress(s,phonenumber)#address为初步的混合地址
    
    if level==1:
        segementFive(address,result,JD)
        formatFive(result,data)
    elif level==2:
        segementFive(address,result,JD)
        segementSeven(result.street,result)
        formatSeven(result,data)
    else:
        enhancement(address,result,JD)
        formatSeven(result,data)
    jsonresult=json.dumps(data,ensure_ascii=False)
    print(jsonresult)

事实上,运行pylint分析代码后有一个warning不是很明白。eval干嘛不能用啊?

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

因为是循环输入的,1151条数据,所以输入部分肯定是消耗最大的。。。改不动改不动

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

展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。并将单元测试得到的测试覆盖率截图,发表在博客中。**(6')

部分测试数据

1!皇甫享,安徽宣城郎13734164891溪县飞鲤镇011乡道*三立村村委会.
1!家按犯,*藏自治区昌都卡若区城关镇214国道城关镇嘎东街社区居民委员15347650776会.
1!席赠,湖南省长沙市雨花区黎托街道黎托15224968346乡川河村雨花区托溪小学.
1!淳于象,辽宁丹东凤城市刘家河镇304国道徐家台村委13986910893会.
1!成偶,山*省吕梁岚18918500295县王狮乡209国道阳湾明德小学.
1!何东,北京东城13297814858区朝阳门街道南小街59号竹杆胡同小区.
1!满哪俊,福建福州仓山区临江街道工农路36号下池小区11号15384414182楼.
1!钱僻苍,安徽省合肥市瑶海区合肥龙岗综合经济开发区海洲景秀世家2期13001981786.
1!阳吟,上海市绿华18970386517镇华*村村委会.
1!施裕槐,上海普陀区大13743250056渡河路1927弄真北新村三街坊2号楼.
1!农咧,江苏省扬州市江都区15058550687大桥镇昌勋村村委会.
1!咸陡隐,江苏省苏州吴江区*望镇新业织造有限公司吴江区*望镇双浜村村民委员13184142847会.
1!池桑炉,天津市河*区友谊路街道黑牛城道*江南里30号丽13739936363枫酒店.
1!卜畸,天津东丽区丰年村街道丰年村街道办事处常熟里社18974264425区居民委员会.
1!左悯渣,浙江省湖州南浔区湖盐公路花城村13938948912村委会.
1!曹租,13286764387北京市丰台区张郭庄南路11号张郭庄小区.
1!谈艇,上海市黄浦区豫园街道方浜*路10号方*居委18839721688会.
1!白粥屠,山*省*中市*遥县兴民街18号新南堡小学新15363389322南堡供销综合门市部.
1!敖堡,山东烟台蓬莱市南王街道15759233074芝山路中共大宁家村支部委员会.
1!邴拆,重庆北碚区龙凤桥街道15242716859龙凤桥街龙凤2村.
1!胥怕摩,天津市河东区成林道63号天津工业15567749658大学.
1!胥卫忍,福建省南*市邵武市卫13017035415闽镇谢坊村耕山队.
1!詹持,山*省*中市*遥县古陶镇永安南路闫壁村委13346009866会.
1!卜寸潜,河北保定竞秀区东风街道*大园*街24号13328693915.
1!第五昌因,黑龙江省鸡*市密山市裴德镇兴利村15109633363农机服务站.
1!满虏,河南省焦作市山阳区中星街道焦辉路中马村巧莲大型15165434173弹花.
2!郦暗祸,北京市门头沟区东辛房街道滑15964374932石道78号.
2!罗挚,上海市长宁13866840508区虹桥街道虹桥路虹桥小区.
2!居***员,四川省成都邛崃市火井镇状元路185号高场社区居委15182872302会.
2!蒲诚,广东省汕头市濠13798786108江区达濠街道海旁路10号达濠派出所.
2!蒯哎葫,山*太原市尖草坪区15247416699迎新街道新顺南大街南固碾村委会.
2!微生句,广*壮族自治区桂林市七星15605131954区七星区街道金星路2号矿地院.
2!茅参,上海市嘉定区马13347914736陆镇嘉新公路1157号樊家村1256号楼.
2!周厘倾,北京13274312770市石景山区鲁谷街道鲁谷大街七星园北区24号楼.
2!寿佳,湖13221817716南益阳赫山区春嘉路6号.
2!柳吻,辽宁省大连市中山区青泥13013864707洼桥街道上海路45号宏孚大厦苏宁易购.
2!宋俗管,广东省珠海市15925966933三灶镇求知路23号鱼林小学.
2!沃顽敷,上海市徐汇区华泾镇华发15005036921路99号明丰新纪苑.
2!田社耘,黑龙江齐齐哈尔市龙沙区湖滨街道园18623684309建街51号园艺小区.
2!路输,江苏省沭阳县周集13031622960乡人民路1号沭阳县周集乡人民政府.
2!钟离越,浙江舟山岱山县高亭镇沿港*路209号闸口社区13454791025.
2!嵇陨协,内蒙古自治区锡林郭勒盟二连浩特市二连边境经济技13182128688术合作区新华大街8号远恒木业.
2!宿冕,辽宁省大连市沙河口区兴工街道如意街46号大14777396416连罗斯福广场A座.
2!姚帮,广东省汕头市潮南区峡山街道峡山义英义华路136号莎13184626238丹服饰.
2!连一渊,北京东城区安定门街道分15866710776司厅胡同17号.
2!巫马锚,浙江省杭州15166205701市余杭区临*街道星火南路23号星火办公楼.
3!符乡,安徽大观区菱湖街道宜园13281503317路80号.
3!褚佳,浦13447146058东新区惠南镇靖海路440号靖海桥大楼.
3!单轿组,上海市浦东新区博山路12号泾东新15155759742村.
3!嵇陨协,内蒙古自13182128688治区锡林郭勒盟新华大街8号远恒木业.
3!周厘倾,北京市石景山13274312770区鲁谷大街七星园北区24号楼.
3!濮婚时,广*壮族自治区桂林市七星区育才13602947448路15号北院广*师大育才校区.
3!柏雅蚜,长宁区周家桥街道武夷路718号武夷13757741271花园722号楼.
3!汝舟孙,贵州省修文县龙岗社区15766780930服务中心阳明*路196号龙岗居委会.
3!荀祈,上海市马15934800449陆镇宝安公路2888号包桥小区.
3!蒯刑浦,白城市洮南市团结街道兴安南街5566号安泰社区公13949401891共事务服务中心.
3!羿暴蛆,浙江省13408790784温州市龙湾区上江路65号溢香厅国际宴会中心.
3!丰缓,滨海新区新城镇新城村东里5号新城13608320376中学.
3!连一渊,东城区安定门街道分司厅15866710776胡同17号.
3!艾堤,北京市海淀区阜成15938433933路八宝庄小区8号楼.
3!廉捷咏,浙江省上城区紫阳街道太庙巷62号紫阳学前教18999108285育集团.
3!华壳腰,福建省*陂街道*陂路286号*15072977042山小区.
3!宿冕,辽宁省沙河口区兴工街14777396416道如意街46号大连罗斯福广场A座.
3!汲者,江苏灌13555806486南县田楼镇新盘村新盘幼儿园.
3!佘器,福建莆田市仙游县仙东13327922135村仙东小学.
3!墨笑,四*市*东街道国测小区8号13185319734楼.
3!夹谷抡枯,甘肃城关区皋兰路街道皋兰18795320124路210号郑家台小区.
3!孙旗乖,13366755810白城市洮北区长庆南街65号.
3!***夹箭,陕*省安康市*利县湖南13402846657路纸坊沟村卫生室.
3!年磅,贵州贵15649587434阳米坪乡云湾村村民委员会.
3!罗挚,上海虹13866840508桥街道虹桥路虹桥小区.
3!蔺脚贺,湖南省娄底市冷水江市石槽村三尖镇15581828223人民政府.

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

#获取电话
def getphone(s):
    pattern = re.compile(r'1\d{10}')
    match = pattern.search(s)
    try:
        phone = match.group(0)
    except AttributeError:
        print("输入的手机号格式不正确")
    return phone

举个栗子,这里异常处理是防止输入手机号不正确产生的问题

posted @ 2019-09-29 20:49  Jorgensen  阅读(360)  评论(2编辑  收藏  举报
#site_nav_under { display: none; } .c_ad_block, .ad_text_commentbox { display: none; margin: 0; padding: 0; } #ad_under_google { height: 0; overflow: hidden; } #ad_under_google a { display: none; }