wcj 6 år sedan
förälder
incheckning
2f6fd0e0df

+ 3239 - 0
fullproject/src/city.json

@@ -0,0 +1,3239 @@
+{
+    "city": {
+        "金银川镇": "新疆",
+        "郑东新区": "河南",
+        "信阳客整所": "湖北",
+        "北屯": "新疆",
+        "鼓楼区": "江苏",
+        "辽河": "辽宁",
+        "南大港": "河北",
+        "北京": "北京",
+        "密云": "北京",
+        "延庆": "北京",
+        "天津": "天津",
+        "宁河": "天津",
+        "静海": "天津",
+        "蓟县": "天津",
+        "河北": "河北",
+        "石家庄": "河北",
+        "井陉": "河北",
+        "正定": "河北",
+        "栾城": "河北",
+        "行唐": "河北",
+        "灵寿": "河北",
+        "高邑": "河北",
+        "深泽": "河北",
+        "赞皇": "河北",
+        "无极县": "河北",
+        "平山县": "河北",
+        "元氏": "河北",
+        "赵县": "河北",
+        "辛集市": "河北",
+        "藁城": "河北",
+        "晋州": "河北",
+        "新乐": "河北",
+        "鹿泉": "河北",
+        "唐山": "河北",
+        "滦县": "河北",
+        "滦南": "河北",
+        "乐亭": "河北",
+        "迁西": "河北",
+        "玉田": "河北",
+        "唐海": "河北",
+        "遵化": "河北",
+        "迁安市": "河北",
+        "秦皇岛": "河北",
+        "青龙县": "河北",
+        "青龙满族自治县": "河北",
+        "昌黎": "河北",
+        "抚宁": "河北",
+        "卢龙": "河北",
+        "邯郸": "河北",
+        "临漳": "河北",
+        "成安": "河北",
+        "大名县": "河北",
+        "涉县": "河北",
+        "磁县": "河北",
+        "肥乡": "河北",
+        "永年": "河北",
+        "邱县": "河北",
+        "鸡泽": "河北",
+        "广平县": "河北",
+        "馆陶": "河北",
+        "魏县": "河北",
+        "曲周": "河北",
+        "武安": "河北",
+        "邢台": "河北",
+        "临城": "河北",
+        "内丘": "河北",
+        "柏乡县": "河北",
+        "隆尧": "河北",
+        "任县": "河北",
+        "南和": "河北",
+        "宁晋": "河北",
+        "巨鹿": "河北",
+        "新河县": "河北",
+        "广宗": "河北",
+        "平乡": "河北",
+        "威县": "河北",
+        "清河": "河北",
+        "临西": "河北",
+        "南宫": "河北",
+        "沙河市": "河北",
+        "保定": "河北",
+        "满城": "河北",
+        "清苑": "河北",
+        "涞水": "河北",
+        "阜平": "河北",
+        "徐水": "河北",
+        "定兴": "河北",
+        "唐县": "河北",
+        "高阳": "河北",
+        "容城": "河北",
+        "涞源": "河北",
+        "望都": "河北",
+        "安新": "河北",
+        "易县": "河北",
+        "曲阳": "河北",
+        "蠡县": "河北",
+        "顺平": "河北",
+        "博野": "河北",
+        "雄县": "河北",
+        "涿州": "河北",
+        "定州": "河北",
+        "安国": "河北",
+        "高碑店": "河北",
+        "张家口": "河北",
+        "宣化": "河北",
+        "张北": "河北",
+        "康保": "河北",
+        "沽源": "河北",
+        "尚义": "河北",
+        "蔚县": "河北",
+        "阳原": "河北",
+        "怀安": "河北",
+        "万全县": "河北",
+        "怀来": "河北",
+        "涿鹿": "河北",
+        "赤城": "河北",
+        "崇礼": "河北",
+        "承德": "河北",
+        "兴隆": "河北",
+        "平泉县": "河北",
+        "滦平": "河北",
+        "隆化": "河北",
+        "丰宁": "河北",
+        "宽城满族自治县": "河北",
+        "宽城县": "河北",
+        "围场": "河北",
+        "沧州": "河北",
+        "沧县": "河北",
+        "青县": "河北",
+        "东光县": "河北",
+        "海兴": "河北",
+        "盐山": "河北",
+        "肃宁": "河北",
+        "南皮": "河北",
+        "吴桥县": "河北",
+        "献县": "河北",
+        "孟村回族自治县": "河北",
+        "孟村县": "河北",
+        "泊头": "河北",
+        "任丘": "河北",
+        "黄骅": "河北",
+        "河间市": "河北",
+        "廊坊": "河北",
+        "固安": "河北",
+        "永清": "河北",
+        "香河": "河北",
+        "大城县": "河北",
+        "文安": "河北",
+        "大厂回族自治县": "河北",
+        "大厂县": "河北",
+        "霸州": "河北",
+        "三河": "河北",
+        "衡水": "河北",
+        "枣强": "河北",
+        "武邑": "河北",
+        "武强": "河北",
+        "饶阳": "河北",
+        "安平": "河北",
+        "故城县": "河北",
+        "景县": "河北",
+        "阜城县": "河北",
+        "冀州": "河北",
+        "深州": "河北",
+        "山西": "山西",
+        "太原": "山西",
+        "清徐": "山西",
+        "阳曲": "山西",
+        "娄烦": "山西",
+        "古交": "山西",
+        "大同市": "山西",
+        "阳高": "山西",
+        "天镇": "山西",
+        "广灵": "山西",
+        "灵丘": "山西",
+        "浑源": "山西",
+        "左云": "山西",
+        "阳泉": "山西",
+        "平定": "山西",
+        "盂县": "山西",
+        "长治": "山西",
+        "襄垣": "山西",
+        "屯留": "山西",
+        "平顺": "山西",
+        "黎城": "山西",
+        "壶关": "山西",
+        "长子": "山西",
+        "武乡": "山西",
+        "沁县": "山西",
+        "沁源": "山西",
+        "潞城": "山西",
+        "晋城": "山西",
+        "沁水": "山西",
+        "阳城": "山西",
+        "陵川": "山西",
+        "泽州": "山西",
+        "高平": "山西",
+        "朔州": "山西",
+        "山阴": "山西",
+        "应县": "山西",
+        "右玉": "山西",
+        "怀仁": "山西",
+        "晋中": "山西",
+        "榆社": "山西",
+        "左权县": "山西",
+        "和顺": "山西",
+        "昔阳": "山西",
+        "寿阳": "山西",
+        "太谷": "山西",
+        "祁县": "山西",
+        "平遥": "山西",
+        "灵石": "山西",
+        "介休": "山西",
+        "运城": "山西",
+        "临猗": "山西",
+        "万荣": "山西",
+        "闻喜": "山西",
+        "稷山": "山西",
+        "新绛": "山西",
+        "绛县": "山西",
+        "垣曲": "山西",
+        "夏县": "山西",
+        "平陆": "山西",
+        "芮城": "山西",
+        "永济": "山西",
+        "河津市": "山西",
+        "忻州": "山西",
+        "定襄": "山西",
+        "五台县": "山西",
+        "代县": "山西",
+        "繁峙": "山西",
+        "宁武": "山西",
+        "静乐": "山西",
+        "神池": "山西",
+        "五寨": "山西",
+        "岢岚": "山西",
+        "河曲": "山西",
+        "保德": "山西",
+        "偏关": "山西",
+        "原平": "山西",
+        "临汾": "山西",
+        "曲沃": "山西",
+        "翼城": "山西",
+        "襄汾": "山西",
+        "洪洞": "山西",
+        "古县": "山西",
+        "安泽": "山西",
+        "浮山": "山西",
+        "吉县": "山西",
+        "乡宁": "山西",
+        "大宁": "山西",
+        "隰县": "山西",
+        "永和": "山西",
+        "蒲县": "山西",
+        "汾西": "山西",
+        "侯马": "山西",
+        "霍州": "山西",
+        "吕梁": "山西",
+        "文水": "山西",
+        "交城": "山西",
+        "兴县": "山西",
+        "临县": "山西",
+        "柳林": "山西",
+        "石楼": "山西",
+        "岚县": "山西",
+        "方山县": "山西",
+        "中阳县": "山西",
+        "交口县": "山西",
+        "孝义市": "山西",
+        "汾阳": "山西",
+        "内蒙古": "内蒙古",
+        "呼和浩特": "内蒙古",
+        "土默特左旗": "内蒙古",
+        "托克托": "内蒙古",
+        "和林格尔": "内蒙古",
+        "清水河": "内蒙古",
+        "武川": "内蒙古",
+        "包头": "内蒙古",
+        "土默特右旗": "内蒙古",
+        "固阳": "内蒙古",
+        "达尔罕茂明安联合旗": "内蒙古",
+        "乌海": "内蒙古",
+        "赤峰": "内蒙古",
+        "阿鲁科尔沁旗": "内蒙古",
+        "巴林左旗": "内蒙古",
+        "巴林右旗": "内蒙古",
+        "林西": "内蒙古",
+        "克什克腾旗": "内蒙古",
+        "翁牛特旗": "内蒙古",
+        "喀喇沁旗": "内蒙古",
+        "宁城": "内蒙古",
+        "敖汉旗": "内蒙古",
+        "通辽": "内蒙古",
+        "科尔沁左翼中旗": "内蒙古",
+        "科尔沁左翼后旗": "内蒙古",
+        "开鲁": "内蒙古",
+        "库伦旗": "内蒙古",
+        "奈曼旗": "内蒙古",
+        "扎鲁特旗": "内蒙古",
+        "霍林郭勒": "内蒙古",
+        "鄂尔多斯": "内蒙古",
+        "达拉特旗": "内蒙古",
+        "准格尔旗": "内蒙古",
+        "鄂托克前旗": "内蒙古",
+        "鄂托克旗": "内蒙古",
+        "杭锦旗": "内蒙古",
+        "乌审旗": "内蒙古",
+        "伊金霍洛旗": "内蒙古",
+        "呼伦贝尔": "内蒙古",
+        "阿荣旗": "内蒙古",
+        "莫力达瓦达斡尔族自治旗": "内蒙古",
+        "鄂伦春自治旗": "内蒙古",
+        "鄂温克族自治旗": "内蒙古",
+        "陈巴尔虎旗": "内蒙古",
+        "新巴尔虎左旗": "内蒙古",
+        "新巴尔虎右旗": "内蒙古",
+        "满洲里": "内蒙古",
+        "牙克石": "内蒙古",
+        "扎兰屯": "内蒙古",
+        "额尔古纳": "内蒙古",
+        "根河": "内蒙古",
+        "巴彦淖尔": "内蒙古",
+        "五原": "内蒙古",
+        "磴口": "内蒙古",
+        "乌拉特前旗": "内蒙古",
+        "乌拉特中旗": "内蒙古",
+        "乌拉特后旗": "内蒙古",
+        "杭锦后旗": "内蒙古",
+        "乌兰察布": "内蒙古",
+        "卓资": "内蒙古",
+        "化德": "内蒙古",
+        "商都县": "内蒙古",
+        "兴和县": "内蒙古",
+        "凉城": "内蒙古",
+        "察哈尔右翼前旗": "内蒙古",
+        "察哈尔右翼中旗": "内蒙古",
+        "察哈尔右翼后旗": "内蒙古",
+        "四子王旗": "内蒙古",
+        "丰镇": "内蒙古",
+        "兴安盟": "内蒙古",
+        "乌兰浩特": "内蒙古",
+        "阿尔山": "内蒙古",
+        "科尔沁右翼前旗": "内蒙古",
+        "科尔沁右翼中旗": "内蒙古",
+        "扎赉特旗": "内蒙古",
+        "突泉": "内蒙古",
+        "锡林郭勒盟": "内蒙古",
+        "二连浩特": "内蒙古",
+        "锡林浩特": "内蒙古",
+        "阿巴嘎旗": "内蒙古",
+        "苏尼特左旗": "内蒙古",
+        "苏尼特右旗": "内蒙古",
+        "东乌珠穆沁旗": "内蒙古",
+        "西乌珠穆沁旗": "内蒙古",
+        "太仆寺旗": "内蒙古",
+        "镶黄旗": "内蒙古",
+        "正镶白旗": "内蒙古",
+        "正蓝旗": "内蒙古",
+        "多伦": "内蒙古",
+        "阿拉善盟": "内蒙古",
+        "阿拉善左旗": "内蒙古",
+        "阿拉善右旗": "内蒙古",
+        "额济纳旗": "内蒙古",
+        "辽宁": "辽宁",
+        "沈阳": "辽宁",
+        "辽中": "辽宁",
+        "康平": "辽宁",
+        "法库": "辽宁",
+        "新民市": "辽宁",
+        "大连": "辽宁",
+        "长海": "辽宁",
+        "瓦房店": "辽宁",
+        "普兰店": "辽宁",
+        "庄河": "辽宁",
+        "鞍山": "辽宁",
+        "台安县": "辽宁",
+        "岫岩": "辽宁",
+        "海城市": "辽宁",
+        "抚顺": "辽宁",
+        "新宾": "辽宁",
+        "清原": "辽宁",
+        "本溪": "辽宁",
+        "桓仁": "辽宁",
+        "丹东": "辽宁",
+        "宽甸": "辽宁",
+        "东港市": "辽宁",
+        "凤城": "辽宁",
+        "锦州": "辽宁",
+        "黑山县": "辽宁",
+        "义县": "辽宁",
+        "凌海": "辽宁",
+        "北镇": "辽宁",
+        "营口": "辽宁",
+        "盖州": "辽宁",
+        "大石桥市": "辽宁",
+        "阜新": "辽宁",
+        "彰武": "辽宁",
+        "辽阳": "辽宁",
+        "灯塔市": "辽宁",
+        "盘锦": "辽宁",
+        "大洼": "辽宁",
+        "盘山": "辽宁",
+        "铁岭": "辽宁",
+        "西丰": "辽宁",
+        "昌图": "辽宁",
+        "调兵山": "辽宁",
+        "开原": "辽宁",
+        "朝阳市": "辽宁",
+        "建平": "辽宁",
+        "喀喇沁": "辽宁",
+        "北票": "辽宁",
+        "凌源": "辽宁",
+        "葫芦岛": "辽宁",
+        "绥中": "辽宁",
+        "建昌": "辽宁",
+        "兴城": "辽宁",
+        "吉林": "吉林",
+        "长春": "吉林",
+        "农安": "吉林",
+        "九台": "吉林",
+        "榆树": "吉林",
+        "德惠": "吉林",
+        "吉林": "吉林",
+        "永吉": "吉林",
+        "蛟河": "吉林",
+        "桦甸": "吉林",
+        "舒兰": "吉林",
+        "磐石": "吉林",
+        "四平": "吉林",
+        "梨树县": "吉林",
+        "伊通": "吉林",
+        "公主岭": "吉林",
+        "双辽": "吉林",
+        "辽源": "吉林",
+        "东丰": "吉林",
+        "东辽": "吉林",
+        "通化": "吉林",
+        "辉南": "吉林",
+        "柳河": "吉林",
+        "梅河口": "吉林",
+        "集安": "吉林",
+        "白山市": "吉林",
+        "抚松": "吉林",
+        "靖宇": "吉林",
+        "长白": "吉林",
+        "临江": "吉林",
+        "松原": "吉林",
+        "前郭尔罗斯": "吉林",
+        "长岭": "吉林",
+        "乾安": "吉林",
+        "扶余": "吉林",
+        "白城": "吉林",
+        "镇赉": "吉林",
+        "通榆": "吉林",
+        "洮南": "吉林",
+        "大安市": "吉林",
+        "延边州": "吉林",
+        "延吉": "吉林",
+        "图们": "吉林",
+        "敦化": "吉林",
+        "珲春": "吉林",
+        "龙井市": "吉林",
+        "和龙": "吉林",
+        "汪清": "吉林",
+        "安图县": "吉林",
+        "黑龙江": "黑龙江",
+        "哈尔滨": "黑龙江",
+        "依兰县": "黑龙江",
+        "方正县": "黑龙江",
+        "宾县": "黑龙江",
+        "巴彦": "黑龙江",
+        "木兰县": "黑龙江",
+        "通河县": "黑龙江",
+        "延寿": "黑龙江",
+        "双城区": "黑龙江",
+        "尚志": "黑龙江",
+        "五常市": "黑龙江",
+        "齐齐哈尔": "黑龙江",
+        "龙江县": "黑龙江",
+        "依安": "黑龙江",
+        "泰来": "黑龙江",
+        "甘南": "黑龙江",
+        "富裕县": "黑龙江",
+        "克山县": "黑龙江",
+        "克东县": "黑龙江",
+        "拜泉": "黑龙江",
+        "讷河": "黑龙江",
+        "鸡西市": "黑龙江",
+        "鸡东县": "黑龙江",
+        "虎林": "黑龙江",
+        "密山": "黑龙江",
+        "鹤岗": "黑龙江",
+        "萝北": "黑龙江",
+        "绥滨": "黑龙江",
+        "双鸭山": "黑龙江",
+        "集贤": "黑龙江",
+        "友谊县": "黑龙江",
+        "宝清": "黑龙江",
+        "饶河": "黑龙江",
+        "大庆": "黑龙江",
+        "肇州": "黑龙江",
+        "肇源": "黑龙江",
+        "林甸": "黑龙江",
+        "杜尔伯特": "黑龙江",
+        "伊春市": "黑龙江",
+        "嘉荫": "黑龙江",
+        "铁力": "黑龙江",
+        "佳木斯": "黑龙江",
+        "桦南": "黑龙江",
+        "桦川": "黑龙江",
+        "汤原": "黑龙江",
+        "抚远": "黑龙江",
+        "同江市": "黑龙江",
+        "富锦": "黑龙江",
+        "七台河": "黑龙江",
+        "勃利": "黑龙江",
+        "牡丹江": "黑龙江",
+        "东宁": "黑龙江",
+        "林口": "黑龙江",
+        "绥芬河": "黑龙江",
+        "海林": "黑龙江",
+        "宁安": "黑龙江",
+        "穆棱": "黑龙江",
+        "黑河": "黑龙江",
+        "嫩江": "黑龙江",
+        "逊克": "黑龙江",
+        "孙吴": "黑龙江",
+        "北安": "黑龙江",
+        "五大连池": "黑龙江",
+        "绥化": "黑龙江",
+        "望奎": "黑龙江",
+        "兰西": "黑龙江",
+        "青冈": "黑龙江",
+        "庆安": "黑龙江",
+        "明水": "黑龙江",
+        "绥棱": "黑龙江",
+        "安达": "黑龙江",
+        "肇东": "黑龙江",
+        "海伦": "黑龙江",
+        "呼玛": "黑龙江",
+        "塔河": "黑龙江",
+        "漠河": "黑龙江",
+        "上海": "上海",
+        "崇明": "上海",
+        "江苏": "江苏",
+        "南京": "江苏",
+        "溧水": "江苏",
+        "高淳": "江苏",
+        "无锡": "江苏",
+        "江阴": "江苏",
+        "宜兴": "江苏",
+        "徐州": "江苏",
+        "丰县": "江苏",
+        "沛县": "江苏",
+        "铜山": "江苏",
+        "睢宁": "江苏",
+        "新沂": "江苏",
+        "邳州": "江苏",
+        "常州": "江苏",
+        "溧阳": "江苏",
+        "金坛": "江苏",
+        "苏州": "江苏",
+        "常熟": "江苏",
+        "张家港": "江苏",
+        "昆山": "江苏",
+        "吴江": "江苏",
+        "太仓": "江苏",
+        "南通": "江苏",
+        "海安": "江苏",
+        "如东": "江苏",
+        "启东": "江苏",
+        "如皋": "江苏",
+        "通州": "江苏",
+        "海门": "江苏",
+        "连云港": "江苏",
+        "赣榆": "江苏",
+        "东海": "江苏",
+        "灌云": "江苏",
+        "灌南": "江苏",
+        "淮安": "江苏",
+        "涟水": "江苏",
+        "洪泽区": "江苏",
+        "洪泽县": "江苏",
+        "盱眙": "江苏",
+        "金湖": "江苏",
+        "盐城": "江苏",
+        "响水": "江苏",
+        "滨海县": "江苏",
+        "阜宁": "江苏",
+        "射阳": "江苏",
+        "建湖": "江苏",
+        "东台": "江苏",
+        "大丰": "江苏",
+        "扬州": "江苏",
+        "宝应": "江苏",
+        "仪征": "江苏",
+        "高邮": "江苏",
+        "江都": "江苏",
+        "镇江": "江苏",
+        "丹阳": "江苏",
+        "扬中": "江苏",
+        "句容": "江苏",
+        "泰州": "江苏",
+        "兴化": "江苏",
+        "靖江": "江苏",
+        "泰兴市": "江苏",
+        "泰兴镇": "四川",
+        "姜堰": "江苏",
+        "宿迁": "江苏",
+        "沭阳": "江苏",
+        "泗阳": "江苏",
+        "泗洪": "江苏",
+        "浙江": "浙江",
+        "杭州": "浙江",
+        "桐庐": "浙江",
+        "淳安": "浙江",
+        "建德": "浙江",
+        "富阳区": "浙江",
+        "临安": "浙江",
+        "宁波": "浙江",
+        "象山": "浙江",
+        "宁海": "浙江",
+        "余姚": "浙江",
+        "慈溪": "浙江",
+        "奉化": "浙江",
+        "温州": "浙江",
+        "洞头": "浙江",
+        "永嘉": "浙江",
+        "平阳": "浙江",
+        "苍南": "浙江",
+        "文成县": "浙江",
+        "泰顺": "浙江",
+        "瑞安": "浙江",
+        "乐清": "浙江",
+        "嘉兴": "浙江",
+        "嘉善": "浙江",
+        "海盐": "浙江",
+        "海宁": "浙江",
+        "平湖": "浙江",
+        "桐乡": "浙江",
+        "湖州": "浙江",
+        "德清": "浙江",
+        "长兴": "浙江",
+        "安吉": "浙江",
+        "绍兴": "浙江",
+        "新昌": "浙江",
+        "诸暨": "浙江",
+        "上虞": "浙江",
+        "嵊州": "浙江",
+        "金华": "浙江",
+        "武义": "浙江",
+        "浦江": "浙江",
+        "磐安": "浙江",
+        "兰溪": "浙江",
+        "义乌": "浙江",
+        "东阳": "浙江",
+        "永康": "浙江",
+        "衢州": "浙江",
+        "常山": "浙江",
+        "开化": "浙江",
+        "龙游": "浙江",
+        "江山市": "浙江",
+        "舟山": "浙江",
+        "岱山": "浙江",
+        "嵊泗": "浙江",
+        "台州": "浙江",
+        "玉环": "浙江",
+        "三门县": "浙江",
+        "天台县": "浙江",
+        "仙居": "浙江",
+        "温岭": "浙江",
+        "临海": "浙江",
+        "丽水": "浙江",
+        "青田": "浙江",
+        "缙云": "浙江",
+        "遂昌": "浙江",
+        "松阳": "浙江",
+        "云和": "浙江",
+        "庆元": "浙江",
+        "景宁": "浙江",
+        "龙泉市": "浙江",
+        "安徽": "安徽",
+        "合肥": "安徽",
+        "长丰": "安徽",
+        "肥东": "安徽",
+        "肥西": "安徽",
+        "芜湖": "安徽",
+        "繁昌": "安徽",
+        "南陵": "安徽",
+        "蚌埠": "安徽",
+        "怀远": "安徽",
+        "五河": "安徽",
+        "固镇": "安徽",
+        "淮南": "安徽",
+        "凤台": "安徽",
+        "马鞍山": "安徽",
+        "当涂": "安徽",
+        "含山": "安徽",
+        "和县": "安徽",
+        "淮北": "安徽",
+        "濉溪": "安徽",
+        "铜陵": "安徽",
+        "安庆": "安徽",
+        "怀宁": "安徽",
+        "枞阳": "安徽",
+        "潜山": "安徽",
+        "太湖县": "安徽",
+        "宿松": "安徽",
+        "望江": "安徽",
+        "岳西": "安徽",
+        "桐城": "安徽",
+        "黄山": "安徽",
+        "歙县": "安徽",
+        "休宁": "安徽",
+        "黟县": "安徽",
+        "祁门": "安徽",
+        "滁州": "安徽",
+        "来安": "安徽",
+        "全椒": "安徽",
+        "定远": "安徽",
+        "凤阳": "安徽",
+        "天长市": "安徽",
+        "明光市": "安徽",
+        "阜阳": "安徽",
+        "临泉": "安徽",
+        "太和县": "安徽",
+        "阜南": "安徽",
+        "颍上": "安徽",
+        "界首": "安徽",
+        "宿州": "安徽",
+        "砀山": "安徽",
+        "萧县": "安徽",
+        "灵璧": "安徽",
+        "泗县": "安徽",
+        "巢湖": "安徽",
+        "庐江": "安徽",
+        "无为县": "安徽",
+        "六安": "安徽",
+        "寿县": "安徽",
+        "霍邱": "安徽",
+        "舒城": "安徽",
+        "金寨": "安徽",
+        "霍山": "安徽",
+        "亳州": "安徽",
+        "涡阳": "安徽",
+        "蒙城": "安徽",
+        "利辛": "安徽",
+        "池州": "安徽",
+        "东至县": "安徽",
+        "石台": "安徽",
+        "青阳": "安徽",
+        "宣城": "安徽",
+        "郎溪": "安徽",
+        "广德": "安徽",
+        "泾县": "安徽",
+        "绩溪": "安徽",
+        "旌德": "安徽",
+        "宁国市": "安徽",
+        "福建": "福建",
+        "福州": "福建",
+        "闽侯": "福建",
+        "连江": "福建",
+        "罗源": "福建",
+        "闽清": "福建",
+        "永泰县": "福建",
+        "平潭": "福建",
+        "福清": "福建",
+        "长乐": "福建",
+        "厦门": "福建",
+        "莆田": "福建",
+        "仙游": "福建",
+        "三明": "福建",
+        "明溪": "福建",
+        "清流": "福建",
+        "宁化": "福建",
+        "大田": "福建",
+        "尤溪": "福建",
+        "沙县": "福建",
+        "将乐": "福建",
+        "泰宁": "福建",
+        "建宁": "福建",
+        "永安": "福建",
+        "泉州": "福建",
+        "惠安县": "福建",
+        "安溪": "福建",
+        "永春": "福建",
+        "德化": "福建",
+        "金门": "福建",
+        "石狮": "福建",
+        "晋江": "福建",
+        "南安": "福建",
+        "漳州": "福建",
+        "云霄": "福建",
+        "漳浦": "福建",
+        "诏安": "福建",
+        "长泰": "福建",
+        "东山县": "福建",
+        "南靖": "福建",
+        "平和县": "福建",
+        "华安": "福建",
+        "龙海": "福建",
+        "南平": "福建",
+        "顺昌": "福建",
+        "浦城": "福建",
+        "光泽": "福建",
+        "松溪": "福建",
+        "政和县": "福建",
+        "邵武": "福建",
+        "武夷山": "福建",
+        "建瓯": "福建",
+        "建阳": "福建",
+        "龙岩": "福建",
+        "长汀": "福建",
+        "永定": "福建",
+        "上杭": "福建",
+        "武平": "福建",
+        "连城": "福建",
+        "漳平": "福建",
+        "宁德": "福建",
+        "霞浦": "福建",
+        "古田": "福建",
+        "屏南": "福建",
+        "寿宁": "福建",
+        "周宁": "福建",
+        "柘荣": "福建",
+        "福安": "福建",
+        "福鼎": "福建",
+        "江西": "江西",
+        "南昌": "江西",
+        "新建区": "江西",
+        "安义": "江西",
+        "进贤": "江西",
+        "景德镇": "江西",
+        "浮梁": "江西",
+        "乐平市": "江西",
+        "萍乡": "江西",
+        "莲花": "江西",
+        "上栗": "江西",
+        "芦溪": "江西",
+        "九江市": "江西",
+        "武宁": "江西",
+        "修水县": "江西",
+        "永修": "江西",
+        "德安": "江西",
+        "星子县": "江西",
+        "都昌": "江西",
+        "湖口县": "江西",
+        "彭泽": "江西",
+        "瑞昌": "江西",
+        "新余": "江西",
+        "分宜": "江西",
+        "鹰潭": "江西",
+        "余江": "江西",
+        "贵溪": "江西",
+        "赣州": "江西",
+        "赣县": "江西",
+        "信丰": "江西",
+        "大余": "江西",
+        "上犹": "江西",
+        "崇义": "江西",
+        "安远": "江西",
+        "龙南县": "江西",
+        "定南": "江西",
+        "全南": "江西",
+        "宁都": "江西",
+        "于都": "江西",
+        "兴国县": "江西",
+        "会昌": "江西",
+        "寻乌": "江西",
+        "石城": "江西",
+        "瑞金": "江西",
+        "南康": "江西",
+        "吉安": "江西",
+        "吉水": "江西",
+        "峡江": "江西",
+        "新干": "江西",
+        "永丰": "江西",
+        "泰和县": "江西",
+        "遂川": "江西",
+        "万安县": "江西",
+        "安福县": "江西",
+        "永新县": "江西",
+        "井冈山": "江西",
+        "宜春": "江西",
+        "奉新": "江西",
+        "万载县": "江西",
+        "上高": "江西",
+        "宜丰": "江西",
+        "靖安": "江西",
+        "铜鼓": "江西",
+        "丰城": "江西",
+        "樟树": "江西",
+        "高安": "江西",
+        "抚州": "江西",
+        "南城": "江西",
+        "黎川": "江西",
+        "南丰": "江西",
+        "崇仁": "江西",
+        "乐安": "江西",
+        "宜黄": "江西",
+        "金溪": "江西",
+        "资溪": "江西",
+        "东乡县": "江西",
+        "广昌": "江西",
+        "上饶": "江西",
+        "广丰": "江西",
+        "玉山": "江西",
+        "铅山": "江西",
+        "横峰": "江西",
+        "弋阳": "江西",
+        "余干": "江西",
+        "鄱阳": "江西",
+        "万年县": "江西",
+        "婺源": "江西",
+        "德兴": "江西",
+        "山东": "山东",
+        "济南": "山东",
+        "平阴": "山东",
+        "济阳": "山东",
+        "商河县": "山东",
+        "章丘": "山东",
+        "青岛": "山东",
+        "胶州": "山东",
+        "即墨": "山东",
+        "平度市": "山东",
+        "胶南": "山东",
+        "莱西": "山东",
+        "淄博": "山东",
+        "桓台": "山东",
+        "高青": "山东",
+        "沂源": "山东",
+        "枣庄": "山东",
+        "滕州": "山东",
+        "东营市": "山东",
+        "东营区": "山东",
+        "垦利": "山东",
+        "利津": "山东",
+        "广饶": "山东",
+        "烟台": "山东",
+        "长岛县": "山东",
+        "龙口市": "山东",
+        "莱阳": "山东",
+        "莱州": "山东",
+        "蓬莱": "山东",
+        "招远": "山东",
+        "栖霞市": "山东",
+        "海阳": "山东",
+        "潍坊": "山东",
+        "临朐": "山东",
+        "昌乐": "山东",
+        "青州": "山东",
+        "诸城": "山东",
+        "寿光": "山东",
+        "安丘": "山东",
+        "高密": "山东",
+        "昌邑市": "山东",
+        "济宁": "山东",
+        "微山": "山东",
+        "鱼台": "山东",
+        "金乡": "山东",
+        "嘉祥": "山东",
+        "汶上": "山东",
+        "泗水": "山东",
+        "梁山": "山东",
+        "曲阜": "山东",
+        "兖州": "山东",
+        "邹城": "山东",
+        "泰安": "山东",
+        "宁阳": "山东",
+        "东平": "山东",
+        "新泰": "山东",
+        "肥城": "山东",
+        "威海": "山东",
+        "文登": "山东",
+        "荣成": "山东",
+        "乳山": "山东",
+        "日照": "山东",
+        "五莲": "山东",
+        "莒县": "山东",
+        "莱芜": "山东",
+        "临沂": "山东",
+        "沂南": "山东",
+        "郯城": "山东",
+        "沂水": "山东",
+        "苍山": "山东",
+        "费县": "山东",
+        "平邑": "山东",
+        "莒南": "山东",
+        "蒙阴": "山东",
+        "临沭": "山东",
+        "德州": "山东",
+        "陵县": "山东",
+        "宁津": "山东",
+        "庆云": "山东",
+        "临邑": "山东",
+        "齐河": "山东",
+        "平原": "山东",
+        "夏津": "山东",
+        "武城": "山东",
+        "乐陵": "山东",
+        "禹城": "山东",
+        "聊城": "山东",
+        "阳谷": "山东",
+        "莘县": "山东",
+        "茌平": "山东",
+        "东阿": "山东",
+        "冠县": "山东",
+        "高唐": "山东",
+        "临清": "山东",
+        "滨州": "山东",
+        "惠民": "山东",
+        "阳信": "山东",
+        "无棣": "山东",
+        "沾化": "山东",
+        "博兴": "山东",
+        "邹平": "山东",
+        "菏泽": "山东",
+        "曹县": "山东",
+        "单县": "山东",
+        "成武": "山东",
+        "巨野": "山东",
+        "郓城": "山东",
+        "鄄城": "山东",
+        "定陶": "山东",
+        "东明县": "山东",
+        "河南": "河南",
+        "郑州": "河南",
+        "管城": "河南",
+        "中牟": "河南",
+        "巩义": "河南",
+        "荥阳": "河南",
+        "新密": "河南",
+        "新郑": "河南",
+        "登封": "河南",
+        "开封": "河南",
+        "杞县": "河南",
+        "通许": "河南",
+        "尉氏": "河南",
+        "兰考": "河南",
+        "洛阳": "河南",
+        "孟津": "河南",
+        "新安": "河南",
+        "栾川": "河南",
+        "嵩县": "河南",
+        "汝阳": "河南",
+        "宜阳": "河南",
+        "洛宁": "河南",
+        "伊川": "河南",
+        "偃师": "河南",
+        "平顶山": "河南",
+        "宝丰": "河南",
+        "叶县": "河南",
+        "鲁山": "河南",
+        "郏县": "河南",
+        "舞钢": "河南",
+        "汝州": "河南",
+        "安阳": "河南",
+        "汤阴": "河南",
+        "滑县": "河南",
+        "内黄": "河南",
+        "林州": "河南",
+        "鹤壁": "河南",
+        "浚县": "河南",
+        "淇县": "河南",
+        "新乡": "河南",
+        "获嘉": "河南",
+        "原阳": "河南",
+        "延津": "河南",
+        "封丘": "河南",
+        "长垣": "河南",
+        "卫辉": "河南",
+        "辉市": "河南",
+        "焦作": "河南",
+        "修武": "河南",
+        "博爱": "河南",
+        "武陟": "河南",
+        "温县": "河南",
+        "沁阳": "河南",
+        "孟州": "河南",
+        "濮阳": "河南",
+        "清丰": "河南",
+        "南乐": "河南",
+        "范县": "河南",
+        "台前": "河南",
+        "许昌": "河南",
+        "鄢陵": "河南",
+        "襄城县": "河南",
+        "禹州": "河南",
+        "长葛": "河南",
+        "漯河": "河南",
+        "舞阳": "河南",
+        "临颍": "河南",
+        "三门峡": "河南",
+        "渑池": "河南",
+        "陕县": "河南",
+        "卢氏": "河南",
+        "义马": "河南",
+        "灵宝": "河南",
+        "南阳": "河南",
+        "南召": "河南",
+        "方城": "河南",
+        "西峡": "河南",
+        "镇平县": "河南",
+        "内乡": "河南",
+        "淅川": "河南",
+        "社旗": "河南",
+        "唐河": "河南",
+        "新野": "河南",
+        "桐柏": "河南",
+        "邓州": "河南",
+        "商丘": "河南",
+        "民权": "河南",
+        "睢县": "河南",
+        "宁陵": "河南",
+        "柘城": "河南",
+        "虞城": "河南",
+        "夏邑": "河南",
+        "永城": "河南",
+        "信阳": "河南",
+        "罗山": "河南",
+        "光山": "河南",
+        "新县": "河南",
+        "商城": "河南",
+        "固始": "河南",
+        "潢川": "河南",
+        "淮滨": "河南",
+        "息县": "河南",
+        "周口": "河南",
+        "扶沟": "河南",
+        "西华": "河南",
+        "商水": "河南",
+        "沈丘": "河南",
+        "郸城": "河南",
+        "淮阳": "河南",
+        "太康": "河南",
+        "鹿邑": "河南",
+        "项城": "河南",
+        "驻马店": "河南",
+        "西平": "河南",
+        "上蔡": "河南",
+        "平舆": "河南",
+        "正阳": "河南",
+        "确山": "河南",
+        "泌阳": "河南",
+        "汝南": "河南",
+        "遂平": "河南",
+        "新蔡": "河南",
+        "济源": "河南",
+        "湖北": "湖北",
+        "武汉": "湖北",
+        "黄石市": "湖北",
+        "阳新县": "湖北",
+        "大冶": "湖北",
+        "十堰": "湖北",
+        "郧县": "湖北",
+        "郧西": "湖北",
+        "竹山": "湖北",
+        "竹溪": "湖北",
+        "房县": "湖北",
+        "丹江口": "湖北",
+        "宜昌": "湖北",
+        "远安": "湖北",
+        "兴山": "湖北",
+        "秭归": "湖北",
+        "长阳": "湖北",
+        "五峰": "湖北",
+        "宜都": "湖北",
+        "当阳": "湖北",
+        "枝江": "湖北",
+        "襄阳": "湖北",
+        "南漳": "湖北",
+        "谷城": "湖北",
+        "保康": "湖北",
+        "老河口": "湖北",
+        "枣阳": "湖北",
+        "宜城": "湖北",
+        "鄂州": "湖北",
+        "荆门": "湖北",
+        "京山县": "湖北",
+        "沙洋": "湖北",
+        "钟祥": "湖北",
+        "屈家岭": "湖北",
+        "孝感": "湖北",
+        "孝昌": "湖北",
+        "大悟": "湖北",
+        "云梦": "湖北",
+        "应城": "湖北",
+        "安陆": "湖北",
+        "汉川": "湖北",
+        "荆州": "湖北",
+        "公安县": "湖北",
+        "监利": "湖北",
+        "江陵": "湖北",
+        "石首": "湖北",
+        "洪湖": "湖北",
+        "松滋": "湖北",
+        "黄冈市": "湖北",
+        "团风县": "湖北",
+        "红安": "湖北",
+        "罗田": "湖北",
+        "英山": "湖北",
+        "浠水": "湖北",
+        "蕲春": "湖北",
+        "黄梅": "湖北",
+        "麻城": "湖北",
+        "武穴": "湖北",
+        "咸宁": "湖北",
+        "嘉鱼": "湖北",
+        "通城": "湖北",
+        "崇阳": "湖北",
+        "通山": "湖北",
+        "赤壁": "湖北",
+        "随州": "湖北",
+        "随县": "湖北",
+        "广水": "湖北",
+        "恩施州": "湖北",
+        "恩施": "湖北",
+        "利川": "湖北",
+        "建始县": "湖北",
+        "巴东": "湖北",
+        "宣恩": "湖北",
+        "咸丰": "湖北",
+        "来凤": "湖北",
+        "鹤峰": "湖北",
+        "仙桃": "湖北",
+        "潜江": "湖北",
+        "天门市": "湖北",
+        "神农架": "湖北",
+        "江汉油田": "湖北",
+        "湖南": "湖南",
+        "长沙": "湖南",
+        "望城": "湖南",
+        "宁乡": "湖南",
+        "浏阳": "湖南",
+        "株洲": "湖南",
+        "攸县": "湖南",
+        "茶陵": "湖南",
+        "炎陵": "湖南",
+        "醴陵": "湖南",
+        "湘潭": "湖南",
+        "湘乡": "湖南",
+        "韶山": "湖南",
+        "衡阳": "湖南",
+        "衡南": "湖南",
+        "衡山": "湖南",
+        "衡东": "湖南",
+        "祁东": "湖南",
+        "耒阳": "湖南",
+        "常宁": "湖南",
+        "邵阳": "湖南",
+        "邵东": "湖南",
+        "新邵": "湖南",
+        "隆回": "湖南",
+        "洞口县": "湖南",
+        "绥宁": "湖南",
+        "新宁县": "湖南",
+        "城步": "湖南",
+        "武冈": "湖南",
+        "岳阳": "湖南",
+        "华容县": "湖南",
+        "湘阴": "湖南",
+        "平江": "湖南",
+        "汨罗": "湖南",
+        "临湘": "湖南",
+        "常德": "湖南",
+        "安乡县": "湖南",
+        "汉寿": "湖南",
+        "澧县": "湖南",
+        "临澧": "湖南",
+        "桃源县": "湖南",
+        "石门": "湖南",
+        "津市市": "湖南",
+        "张家界": "湖南",
+        "慈利": "湖南",
+        "桑植": "湖南",
+        "益阳": "湖南",
+        "南县": "湖南",
+        "桃江": "湖南",
+        "安化": "湖南",
+        "沅江": "湖南",
+        "郴州": "湖南",
+        "桂阳": "湖南",
+        "宜章": "湖南",
+        "永兴": "湖南",
+        "嘉禾": "湖南",
+        "临武": "湖南",
+        "汝城": "湖南",
+        "桂东": "湖南",
+        "安仁": "湖南",
+        "资兴": "湖南",
+        "永州": "湖南",
+        "祁阳": "湖南",
+        "东安县": "湖南",
+        "双牌": "湖南",
+        "道县": "湖南",
+        "江永": "湖南",
+        "宁远": "湖南",
+        "蓝山": "湖南",
+        "新田": "湖南",
+        "江华": "湖南",
+        "怀化": "湖南",
+        "中方县": "湖南",
+        "沅陵": "湖南",
+        "辰溪": "湖南",
+        "溆浦": "湖南",
+        "会同": "湖南",
+        "麻阳": "湖南",
+        "新晃": "湖南",
+        "芷江": "湖南",
+        "靖州": "湖南",
+        "通道县": "湖南",
+        "通道侗族自治县": "湖南",
+        "洪江": "湖南",
+        "娄底": "湖南",
+        "双峰": "湖南",
+        "新化": "湖南",
+        "冷水江": "湖南",
+        "涟源": "湖南",
+        "湘西": "湖南",
+        "吉首": "湖南",
+        "泸溪": "湖南",
+        "凤凰县": "湖南",
+        "花垣": "湖南",
+        "保靖": "湖南",
+        "古丈": "湖南",
+        "永顺": "湖南",
+        "龙山县": "湖南",
+        "广东": "广东",
+        "广州": "广东",
+        "增城": "广东",
+        "从化": "广东",
+        "韶关": "广东",
+        "始兴": "广东",
+        "仁化": "广东",
+        "翁源": "广东",
+        "乳源": "广东",
+        "新丰": "广东",
+        "乐昌": "广东",
+        "南雄": "广东",
+        "深圳": "广东",
+        "珠海": "广东",
+        "汕头": "广东",
+        "南澳": "广东",
+        "佛山": "广东",
+        "江门市": "广东",
+        "台山市": "广东",
+        "开平市": "广东",
+        "鹤山市": "广东",
+        "恩平": "广东",
+        "湛江": "广东",
+        "遂溪": "广东",
+        "徐闻": "广东",
+        "廉江": "广东",
+        "雷州": "广东",
+        "吴川": "广东",
+        "茂名": "广东",
+        "电白": "广东",
+        "高州": "广东",
+        "化州": "广东",
+        "信宜": "广东",
+        "肇庆": "广东",
+        "广宁": "广东",
+        "怀集": "广东",
+        "封开": "广东",
+        "德庆": "广东",
+        "高要区": "广东",
+        "四会市": "广东",
+        "惠州": "广东",
+        "博罗": "广东",
+        "惠东": "广东",
+        "龙门县": "广东",
+        "梅州": "广东",
+        "梅县": "广东",
+        "大埔": "广东",
+        "丰顺": "广东",
+        "五华县": "广东",
+        "平远": "广东",
+        "蕉岭": "广东",
+        "兴宁市": "广东",
+        "汕尾": "广东",
+        "海丰": "广东",
+        "陆河": "广东",
+        "陆丰": "广东",
+        "河源": "广东",
+        "紫金县": "广东",
+        "龙川": "广东",
+        "连平": "广东",
+        "和平县": "广东",
+        "东源": "广东",
+        "阳江市": "广东",
+        "阳西": "广东",
+        "阳东": "广东",
+        "阳春": "广东",
+        "清远": "广东",
+        "佛冈": "广东",
+        "阳山": "广东",
+        "连山县": "广东",
+        "连山壮族瑶族自治县": "广东",
+        "连南": "广东",
+        "清新区": "广东",
+        "英德": "广东",
+        "连州": "广东",
+        "东莞": "广东",
+        "中山市": "广东",
+        "潮州": "广东",
+        "潮安": "广东",
+        "饶平": "广东",
+        "揭阳": "广东",
+        "揭东": "广东",
+        "揭西": "广东",
+        "惠来": "广东",
+        "普宁": "广东",
+        "云浮": "广东",
+        "新兴": "广东",
+        "郁南": "广东",
+        "云安": "广东",
+        "罗定": "广东",
+        "广西": "广西",
+        "南宁": "广西",
+        "武鸣": "广西",
+        "隆安": "广西",
+        "马山": "广西",
+        "上林": "广西",
+        "宾阳": "广西",
+        "横县": "广西",
+        "柳州": "广西",
+        "柳江": "广西",
+        "柳城": "广西",
+        "鹿寨": "广西",
+        "融安": "广西",
+        "融水": "广西",
+        "三江侗族自治县": "广西",
+        "三江县": "广西",
+        "桂林": "广西",
+        "阳朔": "广西",
+        "临桂": "广西",
+        "灵川": "广西",
+        "全州": "广西",
+        "兴安": "广西",
+        "永福": "广西",
+        "灌阳": "广西",
+        "龙胜": "广西",
+        "资源县": "广西",
+        "平乐": "广西",
+        "荔蒲": "广西",
+        "恭城": "广西",
+        "梧州": "广西",
+        "苍梧": "广西",
+        "藤县": "广西",
+        "蒙山": "广西",
+        "岑溪": "广西",
+        "北海市": "广西",
+        "北海经济开发区": "山东",
+        "合浦": "广西",
+        "防城港": "广西",
+        "上思": "广西",
+        "东兴市": "广西",
+        "钦州": "广西",
+        "灵山县": "广西",
+        "浦北": "广西",
+        "贵港": "广西",
+        "平南": "广西",
+        "桂平": "广西",
+        "玉林": "广西",
+        "容县": "广西",
+        "陆川": "广西",
+        "博白": "广西",
+        "兴业县": "广西",
+        "北流": "广西",
+        "百色": "广西",
+        "田阳": "广西",
+        "田东": "广西",
+        "平果县": "广西",
+        "德保": "广西",
+        "靖西": "广西",
+        "那坡": "广西",
+        "凌云县": "广西",
+        "乐业县": "广西",
+        "田林县": "广西",
+        "西林": "广西",
+        "隆林": "广西",
+        "贺州": "广西",
+        "昭平": "广西",
+        "钟山县": "广西",
+        "富川": "广西",
+        "河池": "广西",
+        "南丹": "广西",
+        "天峨": "广西",
+        "凤山": "广西",
+        "东兰": "广西",
+        "罗城": "广西",
+        "环江": "广西",
+        "巴马": "广西",
+        "都安": "广西",
+        "大化": "广西",
+        "宜州": "广西",
+        "来宾": "广西",
+        "忻城": "广西",
+        "象州": "广西",
+        "武宣": "广西",
+        "金秀": "广西",
+        "合山": "广西",
+        "崇左": "广西",
+        "扶绥": "广西",
+        "宁明": "广西",
+        "龙州": "广西",
+        "大新县": "广西",
+        "天等": "广西",
+        "凭祥": "广西",
+        "海南": "海南",
+        "三沙": "海南",
+        "海口": "海南",
+        "三亚": "海南",
+        "五指山": "海南",
+        "琼海": "海南",
+        "儋州": "海南",
+        "文昌": "海南",
+        "万宁": "海南",
+        "东方市": "海南",
+        "定安": "海南",
+        "屯昌": "海南",
+        "澄迈": "海南",
+        "临高": "海南",
+        "白沙县": "海南",
+        "白沙黎族自治县": "海南",
+        "昌江自治县": "海南",
+        "乐东": "海南",
+        "陵水": "海南",
+        "保亭": "海南",
+        "琼中": "海南",
+        "重庆": "重庆",
+        "綦江": "重庆",
+        "潼南": "重庆",
+        "铜梁": "重庆",
+        "大足": "重庆",
+        "荣昌": "重庆",
+        "璧山": "重庆",
+        "梁平": "重庆",
+        "城口县": "重庆",
+        "丰都": "重庆",
+        "垫江": "重庆",
+        "武隆": "重庆",
+        "忠县": "重庆",
+        "开县": "重庆",
+        "云阳": "重庆",
+        "奉节": "重庆",
+        "巫山": "重庆",
+        "巫溪": "重庆",
+        "石柱土家族自治": "重庆",
+        "秀山土家族苗族自治": "重庆",
+        "酉阳土家族苗族自治": "重庆",
+        "彭水苗族土家族自治": "重庆",
+        "四川": "四川",
+        "成都": "四川",
+        "金堂": "四川",
+        "双流": "四川",
+        "郫县": "四川",
+        "大邑": "四川",
+        "蒲江": "四川",
+        "新津": "四川",
+        "都江堰": "四川",
+        "彭州": "四川",
+        "邛崃": "四川",
+        "崇州": "四川",
+        "自贡": "四川",
+        "荣县": "四川",
+        "富顺": "四川",
+        "攀枝花": "四川",
+        "米易": "四川",
+        "盐边": "四川",
+        "泸州": "四川",
+        "泸县": "四川",
+        "合江": "四川",
+        "叙永": "四川",
+        "古蔺": "四川",
+        "南部县": "四川",
+        "德阳": "四川",
+        "中江": "四川",
+        "罗江": "四川",
+        "广汉": "四川",
+        "什邡": "四川",
+        "绵竹": "四川",
+        "绵阳": "四川",
+        "三台县": "四川",
+        "盐亭": "四川",
+        "安县": "四川",
+        "梓潼": "四川",
+        "北川羌族自治": "四川",
+        "平武": "四川",
+        "江油": "四川",
+        "广元": "四川",
+        "旺苍": "四川",
+        "青川": "四川",
+        "剑阁": "四川",
+        "苍溪": "四川",
+        "遂宁": "四川",
+        "蓬溪": "四川",
+        "射洪": "四川",
+        "大英": "四川",
+        "内江": "四川",
+        "威远": "四川",
+        "资中": "四川",
+        "隆昌": "四川",
+        "乐山": "四川",
+        "犍为": "四川",
+        "井研": "四川",
+        "夹江": "四川",
+        "沐川": "四川",
+        "峨边彝族自治": "四川",
+        "马边彝族自治": "四川",
+        "峨眉山": "四川",
+        "南充": "四川",
+        "营山": "四川",
+        "蓬安": "四川",
+        "仪陇": "四川",
+        "西充": "四川",
+        "阆中": "四川",
+        "眉山": "四川",
+        "仁寿": "四川",
+        "彭山": "四川",
+        "洪雅": "四川",
+        "丹棱": "四川",
+        "青神": "四川",
+        "宜宾": "四川",
+        "南溪": "四川",
+        "江安": "四川",
+        "长宁县": "四川",
+        "高县": "四川",
+        "珙县": "四川",
+        "筠连": "四川",
+        "兴文": "四川",
+        "屏山": "四川",
+        "广安": "四川",
+        "岳池": "四川",
+        "武胜": "四川",
+        "邻水": "四川",
+        "华蓥": "四川",
+        "达州": "四川",
+        "达县": "四川",
+        "宣汉": "四川",
+        "开江县": "四川",
+        "大竹县": "四川",
+        "渠县": "四川",
+        "万源市": "四川",
+        "雅安市": "四川",
+        "名山县": "四川",
+        "荥经": "四川",
+        "汉源": "四川",
+        "石棉县": "四川",
+        "天全": "四川",
+        "芦山": "四川",
+        "宝兴": "四川",
+        "巴中": "四川",
+        "通江": "四川",
+        "南江县": "四川",
+        "平昌": "四川",
+        "资阳": "四川",
+        "安岳": "四川",
+        "乐至县": "四川",
+        "简阳": "四川",
+        "阿坝州": "四川",
+        "汶川": "四川",
+        "理县": "四川",
+        "茂县": "四川",
+        "松潘": "四川",
+        "九寨沟": "四川",
+        "金川县": "四川",
+        "小金县": "四川",
+        "黑水县": "四川",
+        "马尔康": "四川",
+        "壤塘": "四川",
+        "阿坝": "四川",
+        "若尔盖": "四川",
+        "红原": "四川",
+        "甘孜": "四川",
+        "康定": "四川",
+        "泸定": "四川",
+        "丹巴": "四川",
+        "九龙县": "四川",
+        "雅江": "四川",
+        "道孚": "四川",
+        "炉霍": "四川",
+        "新龙": "四川",
+        "德格": "四川",
+        "白玉县": "四川",
+        "石渠": "四川",
+        "色达": "四川",
+        "理塘": "四川",
+        "巴塘": "四川",
+        "乡城县": "四川",
+        "稻城": "四川",
+        "得荣": "四川",
+        "凉山": "四川",
+        "西昌": "四川",
+        "木里": "四川",
+        "盐源": "四川",
+        "德昌": "四川",
+        "会理": "四川",
+        "会东": "四川",
+        "宁南": "四川",
+        "普格": "四川",
+        "布拖": "四川",
+        "金阳": "四川",
+        "昭觉": "四川",
+        "喜德": "四川",
+        "冕宁": "四川",
+        "越西": "四川",
+        "甘洛": "四川",
+        "美姑": "四川",
+        "雷波": "四川",
+        "贵州": "贵州",
+        "贵阳": "贵州",
+        "开阳": "贵州",
+        "息烽": "贵州",
+        "修文": "贵州",
+        "清镇": "贵州",
+        "六盘水": "贵州",
+        "水城": "贵州",
+        "盘县": "贵州",
+        "遵义": "贵州",
+        "桐梓": "贵州",
+        "绥阳": "贵州",
+        "正安": "贵州",
+        "道真": "贵州",
+        "务川": "贵州",
+        "凤冈": "贵州",
+        "湄潭": "贵州",
+        "余庆": "贵州",
+        "习水": "贵州",
+        "赤水": "贵州",
+        "仁怀": "贵州",
+        "安顺": "贵州",
+        "平坝": "贵州",
+        "普定": "贵州",
+        "镇宁": "贵州",
+        "关岭": "贵州",
+        "紫云县": "贵州",
+        "紫云苗族布依族自治县": "贵州",
+        "毕节": "贵州",
+        "大方县": "贵州",
+        "黔西": "贵州",
+        "金沙县": "贵州",
+        "织金": "贵州",
+        "纳雍": "贵州",
+        "威宁": "贵州",
+        "赫章": "贵州",
+        "铜仁": "贵州",
+        "江口县": "贵州",
+        "玉屏": "贵州",
+        "石阡": "贵州",
+        "思南": "贵州",
+        "印江": "贵州",
+        "德江": "贵州",
+        "沿河": "贵州",
+        "松桃": "贵州",
+        "黔西南": "贵州",
+        "兴义": "贵州",
+        "兴仁": "贵州",
+        "普安": "贵州",
+        "晴隆": "贵州",
+        "贞丰": "贵州",
+        "望谟": "贵州",
+        "册亨": "贵州",
+        "安龙县": "贵州",
+        "黔东南": "贵州",
+        "凯里市": "贵州",
+        "黄平县": "贵州",
+        "施秉": "贵州",
+        "三穗": "贵州",
+        "镇远县": "贵州",
+        "岑巩": "贵州",
+        "天柱": "贵州",
+        "锦屏": "贵州",
+        "剑河": "贵州",
+        "台江县": "贵州",
+        "台江区": "福建",
+        "黎平": "贵州",
+        "榕江": "贵州",
+        "从江": "贵州",
+        "雷山": "贵州",
+        "麻江": "贵州",
+        "丹寨": "贵州",
+        "黔南布": "贵州",
+        "都匀": "贵州",
+        "福泉": "贵州",
+        "荔波": "贵州",
+        "贵定": "贵州",
+        "瓮安": "贵州",
+        "独山县": "贵州",
+        "平塘": "贵州",
+        "罗甸": "贵州",
+        "长顺": "贵州",
+        "龙里": "贵州",
+        "惠水": "贵州",
+        "三都": "贵州",
+        "云南": "云南",
+        "昆明": "云南",
+        "呈贡": "云南",
+        "晋宁": "云南",
+        "富民县": "云南",
+        "宜良": "云南",
+        "石林": "云南",
+        "嵩明": "云南",
+        "禄劝": "云南",
+        "寻甸": "云南",
+        "安宁": "云南",
+        "曲靖": "云南",
+        "马龙": "云南",
+        "陆良": "云南",
+        "师宗": "云南",
+        "罗平县": "云南",
+        "富源": "云南",
+        "会泽": "云南",
+        "沾益": "云南",
+        "宣威": "云南",
+        "玉溪": "云南",
+        "江川": "云南",
+        "澄江": "云南",
+        "通海": "云南",
+        "华宁": "云南",
+        "易门": "云南",
+        "峨山": "云南",
+        "新平": "云南",
+        "元江": "云南",
+        "保山": "云南",
+        "施甸": "云南",
+        "腾冲": "云南",
+        "龙陵": "云南",
+        "昌宁": "云南",
+        "昭通": "云南",
+        "鲁甸": "云南",
+        "巧家": "云南",
+        "盐津": "云南",
+        "大关县": "云南",
+        "永善": "云南",
+        "绥江": "云南",
+        "镇雄": "云南",
+        "彝良": "云南",
+        "威信": "云南",
+        "水富": "云南",
+        "丽江": "云南",
+        "玉龙县": "云南",
+        "玉龙纳西族自治县": "云南",
+        "永胜": "云南",
+        "华坪": "云南",
+        "宁蒗": "云南",
+        "普洱": "云南",
+        "宁洱": "云南",
+        "墨江": "云南",
+        "景东县": "云南",
+        "景东彝族自治县": "云南",
+        "景谷": "云南",
+        "镇沅": "云南",
+        "江城自治县": "云南",
+        "江城县": "云南",
+        "孟连": "云南",
+        "澜沧": "云南",
+        "西盟": "云南",
+        "临沧": "云南",
+        "凤庆": "云南",
+        "云县": "云南",
+        "永德": "云南",
+        "镇康": "云南",
+        "双江": "云南",
+        "耿马": "云南",
+        "沧源": "云南",
+        "楚雄": "云南",
+        "双柏": "云南",
+        "牟定": "云南",
+        "南华": "云南",
+        "姚安": "云南",
+        "大姚": "云南",
+        "永仁": "云南",
+        "元谋": "云南",
+        "武定": "云南",
+        "禄丰": "云南",
+        "红河": "云南",
+        "个旧": "云南",
+        "开远": "云南",
+        "蒙自": "云南",
+        "屏边": "云南",
+        "建水": "云南",
+        "石屏": "云南",
+        "弥勒": "云南",
+        "泸西": "云南",
+        "元阳": "云南",
+        "金平自治县": "云南",
+        "金平县": "云南",
+        "绿春": "云南",
+        "河口自治县": "云南",
+        "文山": "云南",
+        "砚山": "云南",
+        "西畴": "云南",
+        "麻栗坡": "云南",
+        "马关县": "云南",
+        "丘北县": "云南",
+        "广南": "云南",
+        "富宁": "云南",
+        "西双版纳": "云南",
+        "景洪": "云南",
+        "勐海": "云南",
+        "勐腊": "云南",
+        "大理白族自治州": "云南",
+        "大理州": "云南",
+        "大理市": "云南",
+        "漾濞": "云南",
+        "祥云": "云南",
+        "宾川": "云南",
+        "弥渡": "云南",
+        "南涧": "云南",
+        "巍山": "云南",
+        "永平": "云南",
+        "云龙": "云南",
+        "洱源": "云南",
+        "剑川": "云南",
+        "鹤庆": "云南",
+        "德宏": "云南",
+        "瑞丽": "云南",
+        "潞西": "云南",
+        "梁河": "云南",
+        "盈江": "云南",
+        "陇川": "云南",
+        "怒江": "云南",
+        "泸水": "云南",
+        "福贡": "云南",
+        "贡山": "云南",
+        "兰坪": "云南",
+        "迪庆": "云南",
+        "香格里拉": "云南",
+        "德钦": "云南",
+        "维西": "云南",
+        "西藏": "西藏",
+        "拉萨": "西藏",
+        "林周": "西藏",
+        "当雄": "西藏",
+        "尼木": "西藏",
+        "曲水": "西藏",
+        "堆龙德庆": "西藏",
+        "达孜": "西藏",
+        "墨竹工卡": "西藏",
+        "昌都": "西藏",
+        "江达": "西藏",
+        "贡觉": "西藏",
+        "类乌齐": "西藏",
+        "丁青": "西藏",
+        "察雅": "西藏",
+        "八宿": "西藏",
+        "左贡": "西藏",
+        "芒康": "西藏",
+        "洛隆": "西藏",
+        "边坝": "西藏",
+        "乃东": "西藏",
+        "扎囊": "西藏",
+        "贡嘎": "西藏",
+        "桑日": "西藏",
+        "琼结": "西藏",
+        "曲松": "西藏",
+        "措美": "西藏",
+        "洛扎": "西藏",
+        "加查": "西藏",
+        "隆子": "西藏",
+        "错那": "西藏",
+        "浪卡子": "西藏",
+        "日喀则": "西藏",
+        "南木林": "西藏",
+        "江孜": "西藏",
+        "定日": "西藏",
+        "萨迦": "西藏",
+        "拉孜": "西藏",
+        "昂仁": "西藏",
+        "谢通门": "西藏",
+        "白朗": "西藏",
+        "仁布": "西藏",
+        "康马": "西藏",
+        "定结": "西藏",
+        "仲巴": "西藏",
+        "亚东": "西藏",
+        "吉隆": "西藏",
+        "聂拉木": "西藏",
+        "萨嘎": "西藏",
+        "岗巴": "西藏",
+        "那曲": "西藏",
+        "嘉黎": "西藏",
+        "比如县": "西藏",
+        "聂荣县": "西藏",
+        "安多县": "西藏",
+        "申扎": "西藏",
+        "索县": "西藏",
+        "班戈": "西藏",
+        "巴青": "西藏",
+        "尼玛": "西藏",
+        "普兰": "西藏",
+        "札达": "西藏",
+        "噶尔": "西藏",
+        "日土": "西藏",
+        "革吉": "西藏",
+        "改则": "西藏",
+        "措勤": "西藏",
+        "林芝市": "西藏",
+        "林芝县": "西藏",
+        "工布江达": "西藏",
+        "米林": "西藏",
+        "墨脱": "西藏",
+        "波密": "西藏",
+        "察隅": "西藏",
+        "朗县": "西藏",
+        "陕西": "陕西",
+        "西安": "陕西",
+        "蓝田": "陕西",
+        "周至": "陕西",
+        "户县": "陕西",
+        "高陵": "陕西",
+        "铜川": "陕西",
+        "宜君": "陕西",
+        "宝鸡": "陕西",
+        "凤翔县": "陕西",
+        "岐山": "陕西",
+        "扶风": "陕西",
+        "眉县": "陕西",
+        "陇县": "陕西",
+        "千阳": "陕西",
+        "麟游": "陕西",
+        "凤县": "陕西",
+        "太白县": "陕西",
+        "咸阳": "陕西",
+        "三原县": "陕西",
+        "泾阳": "陕西",
+        "乾县": "陕西",
+        "礼泉": "陕西",
+        "永寿": "陕西",
+        "彬县": "陕西",
+        "长武": "陕西",
+        "旬邑": "陕西",
+        "淳化": "陕西",
+        "武功县": "陕西",
+        "兴平": "陕西",
+        "渭南": "陕西",
+        "潼关": "陕西",
+        "大荔": "陕西",
+        "合阳": "陕西",
+        "澄城": "陕西",
+        "蒲城": "陕西",
+        "白水": "陕西",
+        "富平": "陕西",
+        "韩城": "陕西",
+        "华阴": "陕西",
+        "延安": "陕西",
+        "延长县": "陕西",
+        "延川": "陕西",
+        "子长": "陕西",
+        "安塞": "陕西",
+        "志丹": "陕西",
+        "吴起": "陕西",
+        "甘泉": "陕西",
+        "富县": "陕西",
+        "洛川": "陕西",
+        "宜川": "陕西",
+        "黄龙": "陕西",
+        "黄陵": "陕西",
+        "汉中": "陕西",
+        "南郑县": "陕西",
+        "城固": "陕西",
+        "洋县": "陕西",
+        "西乡": "陕西",
+        "勉县": "陕西",
+        "宁强": "陕西",
+        "略阳": "陕西",
+        "镇巴": "陕西",
+        "留坝": "陕西",
+        "佛坪": "陕西",
+        "榆林": "陕西",
+        "神木": "陕西",
+        "府谷": "陕西",
+        "横山": "陕西",
+        "靖边": "陕西",
+        "定边": "陕西",
+        "绥德": "陕西",
+        "米脂": "陕西",
+        "佳县": "陕西",
+        "吴堡": "陕西",
+        "清涧": "陕西",
+        "子洲": "陕西",
+        "安康": "陕西",
+        "汉阴": "陕西",
+        "石泉": "陕西",
+        "宁陕": "陕西",
+        "紫阳": "陕西",
+        "岚皋": "陕西",
+        "平利": "陕西",
+        "镇坪": "陕西",
+        "旬阳": "陕西",
+        "白河县": "陕西",
+        "商洛": "陕西",
+        "洛南": "陕西",
+        "丹凤": "陕西",
+        "商南": "陕西",
+        "山阳": "陕西",
+        "镇安县": "陕西",
+        "柞水": "陕西",
+        "甘肃": "甘肃",
+        "兰州": "甘肃",
+        "东乡自治县": "甘肃",
+        "永登": "甘肃",
+        "皋兰": "甘肃",
+        "榆中": "甘肃",
+        "嘉峪关": "甘肃",
+        "金昌": "甘肃",
+        "永昌": "甘肃",
+        "白银市": "甘肃",
+        "靖远": "甘肃",
+        "会宁": "甘肃",
+        "景泰县": "甘肃",
+        "天水": "甘肃",
+        "清水县": "甘肃",
+        "秦安": "甘肃",
+        "甘谷": "甘肃",
+        "武山": "甘肃",
+        "张家川": "甘肃",
+        "武威": "甘肃",
+        "民勤": "甘肃",
+        "古浪": "甘肃",
+        "天祝": "甘肃",
+        "张掖": "甘肃",
+        "肃南": "甘肃",
+        "民乐县": "甘肃",
+        "临泽": "甘肃",
+        "高台": "甘肃",
+        "山丹": "甘肃",
+        "平凉": "甘肃",
+        "泾川": "甘肃",
+        "灵台": "甘肃",
+        "崇信": "甘肃",
+        "华亭": "甘肃",
+        "庄浪": "甘肃",
+        "静宁": "甘肃",
+        "酒泉": "甘肃",
+        "金塔": "甘肃",
+        "瓜州": "甘肃",
+        "肃北": "甘肃",
+        "阿克塞": "甘肃",
+        "玉门": "甘肃",
+        "敦煌": "甘肃",
+        "庆阳": "甘肃",
+        "庆城": "甘肃",
+        "环县": "甘肃",
+        "华池": "甘肃",
+        "合水县": "甘肃",
+        "正宁": "甘肃",
+        "宁县": "甘肃",
+        "镇原县": "甘肃",
+        "定西": "甘肃",
+        "通渭": "甘肃",
+        "陇西": "甘肃",
+        "渭源": "甘肃",
+        "临洮": "甘肃",
+        "漳县": "甘肃",
+        "岷县": "甘肃",
+        "陇南": "甘肃",
+        "成县": "甘肃",
+        "文县": "甘肃",
+        "宕昌": "甘肃",
+        "康县": "甘肃",
+        "西和": "甘肃",
+        "礼县": "甘肃",
+        "徽县": "甘肃",
+        "两当县": "甘肃",
+        "临夏": "甘肃",
+        "康乐县": "甘肃",
+        "永靖": "甘肃",
+        "广河": "甘肃",
+        "和政": "甘肃",
+        "积石山": "甘肃",
+        "合作市": "甘肃",
+        "临潭": "甘肃",
+        "卓尼": "甘肃",
+        "舟曲": "甘肃",
+        "迭部": "甘肃",
+        "玛曲": "甘肃",
+        "碌曲": "甘肃",
+        "夏河": "甘肃",
+        "青海": "青海",
+        "共和县": "青海",
+        "西宁": "青海",
+        "大通自治县": "青海",
+        "大通县": "青海",
+        "湟中": "青海",
+        "湟源": "青海",
+        "平安县": "青海",
+        "民和": "青海",
+        "乐都": "青海",
+        "河南蒙古族自治县": "青海",
+        "互助土族自治县": "青海",
+        "互助县": "青海",
+        "化隆": "青海",
+        "循化": "青海",
+        "海北州": "青海",
+        "海北藏族自治州": "青海",
+        "门源": "青海",
+        "祁连": "青海",
+        "海晏": "青海",
+        "刚察": "青海",
+        "黄南": "青海",
+        "同仁": "青海",
+        "尖扎": "青海",
+        "泽库": "青海",
+        "同德": "青海",
+        "贵德": "青海",
+        "兴海": "青海",
+        "贵南": "青海",
+        "果洛": "青海",
+        "玛沁": "青海",
+        "班玛": "青海",
+        "甘德": "青海",
+        "达日": "青海",
+        "久治": "青海",
+        "玛多": "青海",
+        "玉树": "青海",
+        "杂多": "青海",
+        "称多": "青海",
+        "治多": "青海",
+        "囊谦": "青海",
+        "曲麻莱": "青海",
+        "海西州": "青海",
+        "海西蒙古族藏族自治州": "青海",
+        "格尔木": "青海",
+        "德令哈": "青海",
+        "乌兰": "青海",
+        "都兰": "青海",
+        "天峻": "青海",
+        "宁夏": "宁夏",
+        "银川": "宁夏",
+        "永宁": "宁夏",
+        "贺兰": "宁夏",
+        "灵武": "宁夏",
+        "石嘴山": "宁夏",
+        "平罗": "宁夏",
+        "吴忠": "宁夏",
+        "盐池": "宁夏",
+        "同心县": "宁夏",
+        "青铜峡": "宁夏",
+        "固原": "宁夏",
+        "西吉": "宁夏",
+        "隆德": "宁夏",
+        "泾源": "宁夏",
+        "彭阳": "宁夏",
+        "中卫": "宁夏",
+        "中宁": "宁夏",
+        "海原": "宁夏",
+        "新疆": "新疆",
+        "乌鲁木齐": "新疆",
+        "克拉玛依": "新疆",
+        "吐鲁番": "新疆",
+        "鄯善": "新疆",
+        "托克逊": "新疆",
+        "哈密": "新疆",
+        "巴里坤": "新疆",
+        "伊吾": "新疆",
+        "昌吉": "新疆",
+        "阜康": "新疆",
+        "呼图壁": "新疆",
+        "玛纳斯": "新疆",
+        "奇台": "新疆",
+        "吉木萨尔": "新疆",
+        "木垒哈萨克": "新疆",
+        "博尔塔拉": "新疆",
+        "博乐": "新疆",
+        "精河": "新疆",
+        "温泉县": "新疆",
+        "巴音郭楞": "新疆",
+        "库尔勒": "新疆",
+        "轮台": "新疆",
+        "尉犁": "新疆",
+        "若羌": "新疆",
+        "且末": "新疆",
+        "焉耆": "新疆",
+        "和静": "新疆",
+        "和硕": "新疆",
+        "博湖": "新疆",
+        "阿克苏": "新疆",
+        "温宿": "新疆",
+        "库车": "新疆",
+        "沙雅": "新疆",
+        "新和县": "新疆",
+        "拜城": "新疆",
+        "乌什": "新疆",
+        "阿瓦提": "新疆",
+        "柯坪": "新疆",
+        "克孜勒": "新疆",
+        "阿图什": "新疆",
+        "阿克陶": "新疆",
+        "阿合奇": "新疆",
+        "乌恰": "新疆",
+        "喀什": "新疆",
+        "疏附": "新疆",
+        "疏勒": "新疆",
+        "英吉沙": "新疆",
+        "泽普": "新疆",
+        "莎车": "新疆",
+        "叶城": "新疆",
+        "麦盖提": "新疆",
+        "岳普湖": "新疆",
+        "伽师": "新疆",
+        "巴楚": "新疆",
+        "塔什": "新疆",
+        "和田": "新疆",
+        "墨玉": "新疆",
+        "皮山": "新疆",
+        "洛浦": "新疆",
+        "策勒": "新疆",
+        "于田县": "新疆",
+        "民丰": "新疆",
+        "伊犁": "新疆",
+        "伊宁": "新疆",
+        "奎屯": "新疆",
+        "察布查尔锡伯": "新疆",
+        "霍城": "新疆",
+        "巩留": "新疆",
+        "新源": "新疆",
+        "昭苏": "新疆",
+        "特克斯": "新疆",
+        "尼勒克": "新疆",
+        "塔城": "新疆",
+        "乌苏": "新疆",
+        "额敏": "新疆",
+        "沙湾": "新疆",
+        "托里": "新疆",
+        "裕民": "新疆",
+        "和布克赛尔": "新疆",
+        "阿勒泰": "新疆",
+        "布尔津": "新疆",
+        "富蕴": "新疆",
+        "福海": "新疆",
+        "哈巴河": "新疆",
+        "青河": "新疆",
+        "吉木乃": "新疆",
+        "石河子": "新疆",
+        "阿拉尔": "新疆",
+        "图木舒克": "新疆",
+        "五家渠": "新疆",
+        "台湾": "台湾",
+        "台北": "台湾",
+        "高雄": "台湾",
+        "基隆": "台湾",
+        "台中市": "台湾",
+        "台南": "台湾",
+        "新竹": "台湾",
+        "嘉义": "台湾",
+        "宜兰": "台湾",
+        "桃园市": "台湾",
+        "苗栗": "台湾",
+        "彰化": "台湾",
+        "南投": "台湾",
+        "云林": "台湾",
+        "屏东": "台湾",
+        "台东": "台湾",
+        "花莲": "台湾",
+        "澎湖": "台湾",
+        "香港": "香港",
+        "澳门": "澳门",
+        "东城区": "北京",
+        "西城区": "北京",
+        "崇文": "北京",
+        "宣武": "北京",
+        "丰台": "北京",
+        "石景山": "北京",
+        "海淀": "北京",
+        "门头沟": "北京",
+        "房山": "北京",
+        "顺义": "北京",
+        "昌平": "北京",
+        "大兴区": "北京",
+        "怀柔": "北京",
+        "平谷": "北京",
+        "河西区": "天津",
+        "滨海新区": "天津",
+        "南开区": "天津",
+        "红桥区": "天津",
+        "塘沽": "天津",
+        "汉沽": "天津",
+        "大港": "天津",
+        "东丽": "天津",
+        "西青": "天津",
+        "津南": "天津",
+        "北辰": "天津",
+        "武清": "天津",
+        "宝坻": "天津",
+        "井陉矿": "河北",
+        "裕华": "河北",
+        "路南区": "河北",
+        "路北区": "河北",
+        "古冶": "河北",
+        "丰南": "河北",
+        "丰润": "河北",
+        "海港区": "河北",
+        "山海关": "河北",
+        "北戴河": "河北",
+        "邯山": "河北",
+        "丛台": "河北",
+        "复兴区": "河北",
+        "峰峰矿": "河北",
+        "北市区": "河北",
+        "南市区": "河北",
+        "下花园": "河北",
+        "双滦": "河北",
+        "鹰手营子矿": "河北",
+        "运河区": "河北",
+        "安次": "河北",
+        "广阳": "河北",
+        "桃城": "河北",
+        "小店区": "山西",
+        "迎泽": "山西",
+        "杏花岭": "山西",
+        "尖草坪": "山西",
+        "万柏林": "山西",
+        "晋源": "山西",
+        "南郊区": "山西",
+        "新荣": "山西",
+        "朔城": "山西",
+        "平鲁": "山西",
+        "榆次": "山西",
+        "盐湖": "山西",
+        "忻府": "山西",
+        "尧都": "山西",
+        "离石": "山西",
+        "玉泉": "内蒙古",
+        "赛罕": "内蒙古",
+        "东河区": "内蒙古",
+        "昆都仑": "内蒙古",
+        "石拐": "内蒙古",
+        "白云矿": "内蒙古",
+        "九原": "内蒙古",
+        "海勃湾": "内蒙古",
+        "乌达": "内蒙古",
+        "红山区": "内蒙古",
+        "元宝山": "内蒙古",
+        "松山": "内蒙古",
+        "科尔沁": "内蒙古",
+        "东胜": "内蒙古",
+        "海拉尔": "内蒙古",
+        "临河": "内蒙古",
+        "集宁": "内蒙古",
+        "沈河": "辽宁",
+        "大东区": "辽宁",
+        "皇姑区": "辽宁",
+        "苏家屯": "辽宁",
+        "东陵区": "辽宁",
+        "沈北新": "辽宁",
+        "于洪": "辽宁",
+        "西岗区": "辽宁",
+        "沙河口": "辽宁",
+        "甘井子": "辽宁",
+        "旅顺口": "辽宁",
+        "金州": "辽宁",
+        "立山": "辽宁",
+        "千山": "辽宁",
+        "新抚": "辽宁",
+        "东洲": "辽宁",
+        "望花": "辽宁",
+        "顺城": "辽宁",
+        "溪湖": "辽宁",
+        "明山区": "辽宁",
+        "南芬": "辽宁",
+        "元宝区": "辽宁",
+        "振兴区": "辽宁",
+        "振安": "辽宁",
+        "古塔区": "辽宁",
+        "凌河": "辽宁",
+        "站前区": "辽宁",
+        "西市区": "辽宁",
+        "鲅鱼圈": "辽宁",
+        "老边": "辽宁",
+        "新邱": "辽宁",
+        "太平区": "辽宁",
+        "清河门": "辽宁",
+        "细河": "辽宁",
+        "白塔": "辽宁",
+        "文圣区": "辽宁",
+        "宏伟区": "辽宁",
+        "弓长岭": "辽宁",
+        "太子河": "辽宁",
+        "双台子": "辽宁",
+        "兴隆台": "辽宁",
+        "银州": "辽宁",
+        "双塔区": "辽宁",
+        "龙城区": "辽宁",
+        "龙港区": "辽宁",
+        "南票区": "辽宁",
+        "杨家杖子开发": "辽宁",
+        "南关区": "吉林",
+        "二道区": "吉林",
+        "绿园区": "吉林",
+        "双阳区": "吉林",
+        "龙潭区": "吉林",
+        "船营": "吉林",
+        "丰满区": "吉林",
+        "东昌区": "吉林",
+        "东昌府区": "山东",
+        "二道江": "吉林",
+        "八道江": "吉林",
+        "江源区": "吉林",
+        "宁江": "吉林",
+        "洮北": "吉林",
+        "道里": "黑龙江",
+        "南岗区": "黑龙江",
+        "道外区": "黑龙江",
+        "平房区": "黑龙江",
+        "松北": "黑龙江",
+        "香坊": "黑龙江",
+        "呼兰": "黑龙江",
+        "阿城": "黑龙江",
+        "龙沙": "黑龙江",
+        "建华区": "黑龙江",
+        "铁锋": "黑龙江",
+        "昂昂溪": "黑龙江",
+        "富拉尔基": "黑龙江",
+        "碾子山": "黑龙江",
+        "梅里斯达斡尔族": "黑龙江",
+        "鸡冠区": "黑龙江",
+        "恒山": "黑龙江",
+        "滴道": "黑龙江",
+        "城子河": "黑龙江",
+        "麻山": "黑龙江",
+        "工农区": "黑龙江",
+        "尖山": "黑龙江",
+        "岭东": "黑龙江",
+        "四方台区": "黑龙江",
+        "萨尔图": "黑龙江",
+        "龙凤区": "黑龙江",
+        "让胡路": "黑龙江",
+        "红岗区": "黑龙江",
+        "南岔": "黑龙江",
+        "友好区": "黑龙江",
+        "翠峦": "黑龙江",
+        "新青区": "黑龙江",
+        "美溪": "黑龙江",
+        "金山屯": "黑龙江",
+        "五营区": "黑龙江",
+        "乌马河": "黑龙江",
+        "汤旺河": "黑龙江",
+        "带岭": "黑龙江",
+        "乌伊岭": "黑龙江",
+        "上甘岭": "黑龙江",
+        "东风区": "黑龙江",
+        "桃山": "黑龙江",
+        "茄子河": "黑龙江",
+        "阳明区": "黑龙江",
+        "爱民区": "黑龙江",
+        "爱辉区": "黑龙江",
+        "北林区": "黑龙江",
+        "大兴安岭": "黑龙江",
+        "加格达奇": "黑龙江",
+        "松岭区": "黑龙江",
+        "新林区": "黑龙江",
+        "呼中": "黑龙江",
+        "黄浦": "上海",
+        "徐汇": "上海",
+        "静安": "上海",
+        "闸北": "上海",
+        "虹口": "上海",
+        "杨浦": "上海",
+        "闵行": "上海",
+        "嘉定": "上海",
+        "浦东新": "上海",
+        "金山区 ": "上海",
+        "松江": "上海",
+        "青浦": "上海",
+        "奉贤": "上海",
+        "玄武": "江苏",
+        "白下": "江苏",
+        "秦淮": "江苏",
+        "建邺": "江苏",
+        "下关区": "江苏",
+        "浦口区": "江苏",
+        "雨花台": "江苏",
+        "江宁": "江苏",
+        "六合": "江苏",
+        "崇安": "江苏",
+        "南长": "江苏",
+        "北塘": "江苏",
+        "锡山": "江苏",
+        "惠山": "江苏",
+        "滨湖": "江苏",
+        "九里": "江苏",
+        "贾汪": "江苏",
+        "泉山": "江苏",
+        "天宁": "江苏",
+        "钟楼": "江苏",
+        "戚墅堰": "江苏",
+        "新北": "江苏",
+        "武进": "江苏",
+        "沧浪": "江苏",
+        "金阊": "江苏",
+        "虎丘": "江苏",
+        "吴中": "江苏",
+        "相城": "江苏",
+        "崇川": "江苏",
+        "港闸": "江苏",
+        "新浦": "江苏",
+        "楚州": "江苏",
+        "淮阴区": "江苏",
+        "清浦": "江苏",
+        "亭湖": "江苏",
+        "盐都": "江苏",
+        "广陵": "江苏",
+        "邗江": "江苏",
+        "维扬": "江苏",
+        "京口": "江苏",
+        "润州": "江苏",
+        "丹徒": "江苏",
+        "海陵": "江苏",
+        "高港": "江苏",
+        "宿城": "江苏",
+        "宿豫": "江苏",
+        "上城区": "浙江",
+        "下城区": "浙江",
+        "江干区": "浙江",
+        "拱墅": "浙江",
+        "滨江区": "浙江",
+        "萧山": "浙江",
+        "余杭": "浙江",
+        "海曙": "浙江",
+        "江东区": "浙江",
+        "北仑": "浙江",
+        "镇海": "浙江",
+        "鄞州": "浙江",
+        "鹿城": "浙江",
+        "龙湾区": "浙江",
+        "瓯海": "浙江",
+        "南湖区": "浙江",
+        "秀洲": "浙江",
+        "吴兴": "浙江",
+        "南浔": "浙江",
+        "越城": "浙江",
+        "婺城": "浙江",
+        "金东": "浙江",
+        "柯城": "浙江",
+        "衢江": "浙江",
+        "定海": "浙江",
+        "椒江": "浙江",
+        "黄岩": "浙江",
+        "路桥区": "浙江",
+        "莲都": "浙江",
+        "瑶海": "安徽",
+        "庐阳": "安徽",
+        "蜀山": "安徽",
+        "新站": "安徽",
+        "包河": "安徽",
+        "镜湖区": "安徽",
+        "镜湖新区": "浙江",
+        "弋江": "安徽",
+        "鸠江": "安徽",
+        "三山区": "安徽",
+        "蚌山": "安徽",
+        "禹会": "安徽",
+        "淮上": "安徽",
+        "田家庵": "安徽",
+        "谢家集": "安徽",
+        "八公山": "安徽",
+        "潘集": "安徽",
+        "金家庄": "安徽",
+        "花山区": "安徽",
+        "雨山": "安徽",
+        "博望新": "安徽",
+        "杜集区": "安徽",
+        "相山": "安徽",
+        "烈山": "安徽",
+        "铜官山": "安徽",
+        "狮子山": "安徽",
+        "迎江": "安徽",
+        "大观区": "安徽",
+        "宜秀": "安徽",
+        "屯溪": "安徽",
+        "徽州": "安徽",
+        "琅琊区": "安徽",
+        "南谯": "安徽",
+        "颍州": "安徽",
+        "颍东": "安徽",
+        "颍泉": "安徽",
+        "埇桥": "安徽",
+        "居巢区": "安徽",
+        "金安": "安徽",
+        "裕安": "安徽",
+        "谯城": "安徽",
+        "贵池": "安徽",
+        "宣州": "安徽",
+        "仓山": "福建",
+        "马尾": "福建",
+        "晋安": "福建",
+        "思明区": "福建",
+        "海沧": "福建",
+        "湖里": "福建",
+        "集美区": "福建",
+        "同安区": "福建",
+        "同安县": "福建",
+        "翔安区": "福建",
+        "城厢": "福建",
+        "涵江": "福建",
+        "荔城": "福建",
+        "秀屿区": "福建",
+        "梅列": "福建",
+        "三元区": "福建",
+        "鲤城": "福建",
+        "丰泽区": "福建",
+        "洛江": "福建",
+        "泉港": "福建",
+        "芗城": "福建",
+        "龙文": "福建",
+        "延平": "福建",
+        "新罗": "福建",
+        "蕉城": "福建",
+        "东湖区": "江西",
+        "青云谱": "江西",
+        "湾里区": "江西",
+        "青山湖": "江西",
+        "珠山": "江西",
+        "安源": "江西",
+        "湘东": "江西",
+        "庐山": "江西",
+        "浔阳": "江西",
+        "渝水": "江西",
+        "月湖区": "江西",
+        "章贡": "江西",
+        "吉州": "江西",
+        "青原区": "江西",
+        "袁州": "江西",
+        "临川": "江西",
+        "信州": "江西",
+        "历下": "山东",
+        "槐荫": "山东",
+        "天桥区": "山东",
+        "历城": "山东",
+        "长清": "山东",
+        "市南区": "山东",
+        "市北区": "山东",
+        "四方区": "山东",
+        "黄岛": "山东",
+        "崂山": "山东",
+        "李沧": "山东",
+        "城阳": "山东",
+        "淄川": "山东",
+        "张店": "山东",
+        "博山": "山东",
+        "临淄": "山东",
+        "周村": "山东",
+        "薛城": "山东",
+        "峄城": "山东",
+        "台儿庄": "山东",
+        "山亭": "山东",
+        "芝罘": "山东",
+        "福山": "山东",
+        "牟平": "山东",
+        "莱山": "山东",
+        "潍城": "山东",
+        "寒亭": "山东",
+        "坊子": "山东",
+        "奎文": "山东",
+        "任城": "山东",
+        "泰山区": "山东",
+        "岱岳": "山东",
+        "环翠": "山东",
+        "岚山": "山东",
+        "莱城": "山东",
+        "钢城区": "山东",
+        "兰山": "山东",
+        "罗庄区": "山东",
+        "德城区": "山东",
+        "东昌府": "山东",
+        "滨城区": "山东",
+        "牡丹区": "山东",
+        "中原区": "河南",
+        "二七区": "河南",
+        "金水区": "河南",
+        "上街": "河南",
+        "惠济区": "河南",
+        "龙亭区": "河南",
+        "顺河回族": "河南",
+        "禹王台": "河南",
+        "金明": "河南",
+        "西工区": "河南",
+        "瀍河回族": "河南",
+        "涧西": "河南",
+        "吉利区": "河南",
+        "洛龙": "河南",
+        "卫东区": "河南",
+        "石龙": "河南",
+        "湛河": "河南",
+        "文峰": "河南",
+        "北关区": "河南",
+        "殷都": "河南",
+        "龙安": "河南",
+        "山城区": "河南",
+        "淇滨": "河南",
+        "红旗区": "河南",
+        "卫滨": "河南",
+        "凤泉": "河南",
+        "牧野区": "河南",
+        "中站区": "河南",
+        "马村区": "河南",
+        "华龙区": "河南",
+        "魏都": "河南",
+        "源汇": "河南",
+        "郾城": "河南",
+        "召陵": "河南",
+        "湖滨": "河南",
+        "宛城": "河南",
+        "卧龙区": "河南",
+        "梁园": "河南",
+        "睢阳": "河南",
+        "浉河": "河南",
+        "平桥区": "河南",
+        "川汇": "河南",
+        "驿城": "河南",
+        "江岸区": "湖北",
+        "江汉区": "湖北",
+        "硚口": "湖北",
+        "汉阳": "湖北",
+        "武昌": "湖北",
+        "洪山": "湖北",
+        "东西湖": "湖北",
+        "汉南": "湖北",
+        "蔡甸": "湖北",
+        "江夏": "湖北",
+        "黄陂": "湖北",
+        "新洲区": "湖北",
+        "东湖开发": "湖北",
+        "武汉经济开发": "湖北",
+        "黄石港": "湖北",
+        "西塞山": "湖北",
+        "下陆": "湖北",
+        "铁山区": "湖北",
+        "黄石经济开发": "湖北",
+        "茅箭": "湖北",
+        "张湾": "湖北",
+        "十堰经济开发": "湖北",
+        "武当山旅游经济特": "湖北",
+        "西陵": "湖北",
+        "伍家岗": "湖北",
+        "点军": "湖北",
+        "猇亭": "湖北",
+        "夷陵": "湖北",
+        "樊城": "湖北",
+        "隆中风景": "湖北",
+        "高新开发": "湖北",
+        "鱼梁洲开发": "湖北",
+        "梁子湖": "湖北",
+        "鄂城": "湖北",
+        "葛店开发": "湖北",
+        "鄂州经济开发": "湖北",
+        "东宝": "湖北",
+        "掇刀": "湖北",
+        "荆门经济开发": "湖北",
+        "孝南": "湖北",
+        "沙市": "湖北",
+        "荆州经济开发": "湖北",
+        "黄州": "湖北",
+        "龙感湖管理": "湖北",
+        "咸安": "湖北",
+        "曾都": "湖北",
+        "芙蓉区": "湖南",
+        "天心区": "湖南",
+        "岳麓": "湖南",
+        "开福": "湖南",
+        "雨花区": "湖南",
+        "荷塘区": "湖南",
+        "芦淞": "湖南",
+        "石峰": "湖南",
+        "天元区": "湖南",
+        "雨湖": "湖南",
+        "岳塘": "湖南",
+        "珠晖": "湖南",
+        "雁峰": "湖南",
+        "石鼓": "湖南",
+        "蒸湘": "湖南",
+        "南岳": "湖南",
+        "双清": "湖南",
+        "大祥": "湖南",
+        "北塔区": "湖南",
+        "岳阳楼": "湖南",
+        "云溪": "湖南",
+        "君山": "湖南",
+        "武陵": "湖南",
+        "鼎城": "湖南",
+        "武陵源": "湖南",
+        "赫山": "湖南",
+        "北湖": "湖南",
+        "苏仙": "湖南",
+        "零陵": "湖南",
+        "冷水滩": "湖南",
+        "鹤城": "湖南",
+        "娄星": "湖南",
+        "荔湾": "广东",
+        "越秀": "广东",
+        "海珠": "广东",
+        "天河区": "广东",
+        "黄埔": "广东",
+        "番禺": "广东",
+        "花都区": "广东",
+        "南沙区": "广东",
+        "萝岗": "广东",
+        "武江": "广东",
+        "浈江": "广东",
+        "曲江": "广东",
+        "罗湖": "广东",
+        "福田": "广东",
+        "宝安": "广东",
+        "龙岗": "广东",
+        "盐田": "广东",
+        "香洲": "广东",
+        "斗门区": "广东",
+        "斗门镇": "广东",
+        "金湾区": "广东",
+        "龙湖区": "广东",
+        "濠江": "广东",
+        "潮阳": "广东",
+        "潮南": "广东",
+        "澄海": "广东",
+        "禅城": "广东",
+        "南海区": "广东",
+        "顺德": "广东",
+        "三水": "广东",
+        "高明区": "广东",
+        "蓬江": "广东",
+        "江海区": "广东",
+        "新会": "广东",
+        "赤坎": "广东",
+        "霞山": "广东",
+        "坡头区": "广东",
+        "麻章": "广东",
+        "茂南": "广东",
+        "茂港": "广东",
+        "端州": "广东",
+        "鼎湖": "广东",
+        "惠城": "广东",
+        "惠阳": "广东",
+        "梅江": "广东",
+        "源城": "广东",
+        "清城": "广东",
+        "枫溪": "广东",
+        "湘桥": "广东",
+        "榕城": "广东",
+        "云城": "广东",
+        "青秀": "广西",
+        "江南区": "广西",
+        "西乡塘": "广西",
+        "良庆": "广西",
+        "邕宁": "广西",
+        "鱼峰": "广西",
+        "柳南": "广西",
+        "柳北": "广西",
+        "秀峰区": "广西",
+        "叠彩": "广西",
+        "七星区": "广西",
+        "雁山区": "广西",
+        "万秀区": "广西",
+        "蝶山": "广西",
+        "长洲": "广西",
+        "银海": "广西",
+        "铁山港": "广西",
+        "港口区": "广西",
+        "防城": "广西",
+        "钦南": "广西",
+        "钦北": "广西",
+        "港北": "广西",
+        "港南": "广西",
+        "覃塘": "广西",
+        "玉州": "广西",
+        "右江区": "广西",
+        "八步": "广西",
+        "金城江": "广西",
+        "兴宾": "广西",
+        "江洲": "广西",
+        "秀英区": "海南",
+        "龙华区": "海南",
+        "琼山": "海南",
+        "美兰": "海南",
+        "洋浦经济开发": "海南",
+        "万州": "重庆",
+        "涪陵": "重庆",
+        "渝中": "重庆",
+        "大渡口区": "重庆",
+        "沙坪坝": "重庆",
+        "九龙坡": "重庆",
+        "南岸区": "重庆",
+        "北碚": "重庆",
+        "万盛区": "重庆",
+        "渝北": "重庆",
+        "巴南": "重庆",
+        "黔江": "重庆",
+        "长寿区": "重庆",
+        "江津区": "重庆",
+        "合川": "重庆",
+        "南川": "重庆",
+        "永川": "重庆",
+        "北部新": "重庆",
+        "锦江": "四川",
+        "青羊": "四川",
+        "金牛": "四川",
+        "武侯": "四川",
+        "成华": "四川",
+        "龙泉驿": "四川",
+        "青白江": "四川",
+        "新都区": "四川",
+        "温江区": "四川",
+        "自流井": "四川",
+        "贡井": "四川",
+        "沿滩区": "四川",
+        "仁和区": "四川",
+        "江阳区": "四川",
+        "纳溪": "四川",
+        "龙马潭": "四川",
+        "旌阳": "四川",
+        "涪城": "四川",
+        "游仙": "四川",
+        "元坝": "四川",
+        "朝天区": "四川",
+        "船山": "四川",
+        "安居区": "四川",
+        "五通桥": "四川",
+        "金口河": "四川",
+        "顺庆": "四川",
+        "高坪": "四川",
+        "嘉陵": "四川",
+        "东坡区": "四川",
+        "翠屏": "四川",
+        "通川": "四川",
+        "雨城": "四川",
+        "巴州": "四川",
+        "雁江": "四川",
+        "南明": "贵州",
+        "云岩": "贵州",
+        "花溪": "贵州",
+        "乌当": "贵州",
+        "小河区": "贵州",
+        "金阳新": "贵州",
+        "六枝特": "贵州",
+        "红花岗": "贵州",
+        "汇川": "贵州",
+        "新浦新": "贵州",
+        "西秀": "贵州",
+        "黄果树开发": "贵州",
+        "七星关": "贵州",
+        "碧江": "贵州",
+        "万山特": "贵州",
+        "凯里经济开发": "贵州",
+        "盘龙": "云南",
+        "官渡区": "云南",
+        "西山区": "云南",
+        "东川区": "云南",
+        "麒麟区": "云南",
+        "红塔区": "云南",
+        "隆阳": "云南",
+        "昭阳": "云南",
+        "古城区": "云南",
+        "思茅": "云南",
+        "临翔": "云南",
+        "山南市": "西藏",
+        "阿里地区": "西藏",
+        "碑林": "陕西",
+        "莲湖": "陕西",
+        "灞桥": "陕西",
+        "未央": "陕西",
+        "雁塔": "陕西",
+        "阎良": "陕西",
+        "临潼": "陕西",
+        "沣渭新": "陕西",
+        "王益": "陕西",
+        "印台": "陕西",
+        "耀州": "陕西",
+        "渭滨": "陕西",
+        "金台": "陕西",
+        "陈仓": "陕西",
+        "秦都": "陕西",
+        "渭城": "陕西",
+        "临渭": "陕西",
+        "宝塔区": "陕西",
+        "汉台": "陕西",
+        "榆阳": "陕西",
+        "汉滨": "陕西",
+        "商州": "陕西",
+        "杨凌示范": "陕西",
+        "七里河区": "甘肃",
+        "西固": "甘肃",
+        "红古": "甘肃",
+        "平川": "甘肃",
+        "秦州": "甘肃",
+        "麦积": "甘肃",
+        "凉州": "甘肃",
+        "甘州": "甘肃",
+        "崆峒": "甘肃",
+        "肃州": "甘肃",
+        "西峰": "甘肃",
+        "安定": "甘肃",
+        "武都": "甘肃",
+        "海东": "青海",
+        "兴庆": "宁夏",
+        "西夏区": "宁夏",
+        "金凤": "宁夏",
+        "大武口": "宁夏",
+        "惠农": "宁夏",
+        "利通": "宁夏",
+        "红寺堡": "宁夏",
+        "原州": "宁夏",
+        "沙坡头": "宁夏",
+        "天山区": "新疆",
+        "沙依巴克": "新疆",
+        "水磨沟": "新疆",
+        "头屯河": "新疆",
+        "达坂城": "新疆",
+        "米东": "新疆",
+        "独山子": "新疆",
+        "白碱滩": "新疆",
+        "乌尔禾": "新疆",
+        "中西区": "香港",
+        "九龙城": "香港",
+        "观塘": "香港",
+        "深水埗": "香港",
+        "湾仔区": "香港",
+        "黄大仙": "香港",
+        "油尖旺": "香港",
+        "离岛": "香港",
+        "葵青": "香港",
+        "西贡": "香港",
+        "沙田": "香港",
+        "屯门": "香港",
+        "荃湾": "香港",
+        "元朗": "香港",
+        "花地玛堂": "澳门",
+        "圣安多尼堂": "澳门",
+        "大堂": "澳门",
+        "望德堂": "澳门",
+        "风顺堂": "澳门",
+        "嘉模堂": "澳门",
+        "圣方济各堂": "澳门",
+        "大学": "大学",
+        "学院": "学院",
+        "医院": "医院",
+        "中学": "中学",
+        "小学": "小学",
+        "幼儿园": "幼儿园",
+        "中心": "中心",
+        "公司": "公司",
+        "集团": "集团",
+        "办事处": "办事处",
+        "研究院": "研究院",
+        "研究所": "研究所",
+        "移动": "移动",
+        "联通": "联通",
+        "电信": "电信",
+        "工商": "工商",
+        "公安": "公安",
+        "检察院": "检察院",
+        "检查院": "检查院",
+		"法院":"法院",
+		"司法":"司法",
+		"采购中心":"采购中心",
+		"办公室":"办公室",
+        "地税": "地税",
+        "国税": "国税",
+        "包钢": "包钢",
+        "镇": "镇",
+        "乡": "乡",
+        "市": "市",
+		"局":"局",
+		"厅":"厅",
+		"滇":"滇",
+		"辽":"辽",
+		"沪":"沪",
+		"浙":"浙",
+		"皖":"皖",
+		"闽":"闽",
+		"赣":"赣",
+		"鲁":"鲁",
+		"豫":"豫",
+		"鄂":"鄂",
+		"湘":"湘",
+		"粤":"粤",
+		"桂":"桂",
+		"琼":"琼",
+		"渝":"渝",
+		"川":"川",
+		"藏":"藏",
+		"陕":"陕",
+		"甘":"甘",
+		"黑":"黑",
+		"蒙":"蒙",
+		"吉":"吉",
+		"澳":"澳",
+		"湾":"湾",
+		"山":"山",
+		"河":"河",
+        "首钢": "首钢",
+        "太钢": "太钢",
+        "天钢": "天钢",
+        "国丰": "国丰",
+        "临钢": "临钢",
+        "文丰": "文丰",
+        "天铁": "天铁",
+        "普阳": "普阳",
+        "德龙": "德龙",
+        "港陆": "港陆",
+        "新金": "新金",
+        "宝钢": "宝钢",
+        "南钢": "南钢",
+        "梅钢": "梅钢",
+        "马钢": "马钢",
+        "济钢": "济钢",
+        "莱钢": "莱钢",
+        "沙钢": "沙钢",
+        "新钢": "新钢",
+        "泰钢": "泰钢",
+        "萍钢": "萍钢",
+        "华伟": "华伟",
+        "兆泰": "兆泰",
+        "西城": "西城",
+        "宁钢": "宁钢",
+        "春冶": "春冶",
+        "兆顺": "兆顺",
+        "长达": "长达",
+        "飞达": "飞达 ",
+        "武钢": "武钢",
+        "安钢": "安钢",
+        "涟钢": "涟钢",
+        "湘钢": "湘钢",
+        "鄂钢": "鄂钢",
+        "韶钢": "韶钢",
+        "柳钢": "柳钢",
+        "鞍钢": "鞍钢",
+        "本钢": "本钢",
+        "通钢": "通钢",
+        "北台": "北台",
+        "攀钢": "攀钢",
+        "重钢": "重钢",
+        "昆钢": "昆钢",
+        "包钢": "包钢",
+        "酒钢": "酒钢",
+        "八钢": "八钢"
+    }
+}

+ 110 - 0
fullproject/src/cleareids.go

@@ -0,0 +1,110 @@
+// cleareids
+package main
+
+import (
+	"encoding/json"
+	"log"
+	"qfw/util"
+	"qfw/util/redis"
+	"sync"
+
+	"github.com/robfig/cron"
+)
+
+var (
+	c            *cron.Cron
+	projectcycle int64
+)
+
+func clearedis() {
+	if credis, ok := Sysconfig["clearedis"].(map[string]interface{}); ok {
+		clearcron := util.ObjToString(credis["clearcron"])
+		projectcycle = util.Int64All(credis["projectcycle"])
+		log.Println(credis)
+		if credis["open"].(bool) {
+			c = cron.New()
+			c.AddFunc(clearcron, clearPKey)
+			c.Start()
+		}
+	}
+}
+
+func clearPKey() {
+	log.Println("开始清理")
+	nowtime := currentMegerTime //time.Now().Unix() int64(1461204000)
+	wg := sync.WaitGroup{}
+	for _, pncb := range []*KeyMap{PNKey, PCKey, PBKey} {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			clearPNCBKey(pncb, nowtime)
+		}()
+	}
+	wg.Wait()
+	log.Println("清理结束")
+}
+
+func clearPNCBKey(pncb *KeyMap, nowtime int64) {
+	delkey := clearIdsKeys(pncb, nowtime)
+	pncb.Lock.Lock()
+	for _, k := range delkey {
+		delete(pncb.Map, k)
+	}
+	pncb.Lock.Unlock()
+}
+
+func clearIdsKeys(pKey *KeyMap, nowtime int64) []string {
+	defer util.Catch()
+	delkey := []string{}
+	pKey.Lock.Lock()
+	for k, ma := range pKey.Map {
+		ids := ma.Arr
+		delids := []interface{}{}
+		res := redis.Mget(REDISIDS, *ids)
+		for _, b1 := range res {
+			if b1 != nil {
+				var info ProjectInfo
+				err := json.Unmarshal(b1.([]byte), &info)
+				if err != nil {
+					log.Println(err)
+					continue
+				}
+				publistime := info.Publistime[len(info.Publistime)-1]
+				if projectcycle < (nowtime-publistime)/86400 { //项目周期超时
+					delids = append(delids, info.Id)
+				}
+			}
+		}
+		if len(delids) < 1 {
+			continue
+		}
+		//删除redis相关信息
+		b := redis.Del(REDISIDS, delids...)
+		if b {
+			for _, id := range delids {
+				ids = deleteSliceId(*ids, id.(string))
+			}
+			//log.Println(ids, *ma.Arr)
+			ma.Arr = ids
+			if len(*ma.Arr) < 1 {
+				redis.Del(REDISKEYS, k)
+				delkey = append(delkey, k)
+			} else {
+				//更新REDISKEYS
+				redis.Put(REDISKEYS, k, *ma.Arr, 0)
+			}
+		}
+	}
+	pKey.Lock.Unlock()
+	return delkey
+}
+
+func deleteSliceId(a []string, id string) *[]string {
+	ret := make([]string, 0, len(a))
+	for _, val := range a {
+		if val != id {
+			ret = append(ret, val)
+		}
+	}
+	return &ret
+}

+ 427 - 0
fullproject/src/compare.go

@@ -0,0 +1,427 @@
+package main
+
+import (
+	"qfw/util"
+	"qfw/util/redis"
+	"regexp"
+	"sort"
+	"strings"
+	"time"
+
+	"gopkg.in/mgo.v2/bson"
+)
+
+/**
+发布时间(结合信息类型-->)
+信息类型(拟建、招标(变更)、结果(成交、中标、流标、废标、变更)、其他(合同、验收、违规、变更))
+项目代码(长度)
+采购单位(结合省份)
+招标机构
+所属省份
+信息标题(含有二次、标段、包的情况,结合分包情况处理)
+是否分包:
+**/
+type ProjectInfo struct {
+	Id            string                 `json:"id"`
+	Publistime    []int64                `json:"publistime"` //多条信息的发布时间、跨度
+	InfoType      [][]string             `json:"infotype"`   //多条信息内的 toptype、subtype
+	Ids           []string               `json:"ids"`
+	Topscopeclass []string               `json:"topscopeclass"`
+	Subscopeclass []string               `json:"subscopeclass"`
+	Winners       []string               `json:"winners"`
+	ProjectName   string                 `json:"projectname"`
+	ProjectCode   string                 `json:"projectcode"` //项目代码唯一(纯数字的权重低)
+	Buyer         string                 `json:"buyer"`       //采购单位唯一
+	Buyerperson   string                 `json:"buyerperson"`
+	Buyertel      string                 `json:"buyertel"`
+	Agency        string                 `json:"agency"`     //代理机构唯一
+	Area          string                 `json:"area"`       //地区唯一
+	City          string                 `json:"city"`       //地市
+	HasPackage    bool                   `json:"haspackage"` //是否有分包
+	Package       map[string]interface{} `json:"package"`    //分包的对比对象
+
+	Buyerclass  string   `json:"buyerclass"`  //采购单位分类
+	Bidopentime int64    `json:"bidopentime"` //开标时间
+	District    string   `json:"district"`    //区县
+	Winnerorder []string //中标候选人
+}
+
+type CompareOne struct {
+	ProjectNameType string //项目名称对比结果分类 A相等 B包含 C不相等 Dthis存在对比不存在 Ethis不存在
+	ProjectCodeType string //同上
+	BuyerType       string //同上
+	AreaType        string //同上
+	AgencyType      string //同上
+	PublistimeType  int    //1在时间范围  2不在
+	PackageType     int    //1都是多包 2都不是多包 3招标 4新信息是结果
+	Score           int
+	Parent          *CompareInfo
+	Pinfo           *ProjectInfo
+	Pos             int
+
+	Cresult string //对比结果
+}
+
+type CompareInfo struct {
+	Field  string        //对比属性 pn/pc/pb
+	Key    string        //存放rediskey
+	Scores []*CompareOne //对比分值 pinfo索引对应分值
+	Bfind  bool          //是否查找到
+	IdArr  []string
+	K      *Key
+	KeyMap *KeyMap
+}
+
+func NewCompareInfo(field, key string, KeyMap *KeyMap) *CompareInfo {
+	return &CompareInfo{
+		Field:  field,
+		Key:    key,
+		Scores: []*CompareOne{},
+		KeyMap: KeyMap,
+	}
+
+}
+
+var numreg2 = regexp.MustCompile("^[0-9]+$")
+var TitleReg = regexp.MustCompile("([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ、\\-~至]+(子|合同|分|施工|监理|标)?[包标段][号段]?[、]?)+|((子|合同|分|施工|监理|标)?[包标段][号段]?[一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ、\\-~至]+[、]?)+|(子|合同|分|施工|监理|标)?[包标段][号段]?[a-zA-Z0-9]+[\\-~-至、](子|合同|分|施工|监理|标)?[包标段][号段]?[a-zA-Z0-9]+")
+
+//没有在redis中查找到,新增项目
+func InsertProject(new_pn string, tmp, mess map[string]interface{}, pici int64, thisinfo *Info) string {
+	e := InitEL("")
+	set := map[string]interface{}{
+		"pici": pici,
+	}
+	set["s_projectname"] = new_pn
+	e.fieldpriority(&tmp, nil, &set)
+	set["extractpos"] = e.GetVal()
+	set["createtime"] = time.Now().Unix()
+	set["sourceinfoid"] = util.BsonIdToSId(tmp["_id"])
+	set["sourceinfourl"] = tmp["href"]
+	set["topscopeclass"] = thisinfo.Topscopeclass
+	set["subscopeclass"] = thisinfo.Subscopeclass
+	if thisinfo.Buyerperson != "" {
+		set["buyerperson"] = thisinfo.Buyerperson
+	}
+	if thisinfo.Buyertel != "" {
+		set["buyertel"] = thisinfo.Buyertel
+	}
+	if thisinfo.Buyerclass != "" {
+		set["buyertel"] = thisinfo.Buyerclass
+	}
+	if thisinfo.District != "" {
+		set["district"] = thisinfo.District
+	}
+	if thisinfo.Bidopentime > 0 {
+		set["bidopentime"] = thisinfo.Bidopentime
+	}
+	if len(thisinfo.Winnerorder) > 0 {
+		set["winnerorder"] = thisinfo.Winnerorder
+	}
+	s_subscopeclass := strings.Join(thisinfo.Subscopeclass, ",")
+	set["s_subscopeclass"] = s_subscopeclass
+	s_winner := strings.Join(thisinfo.Winners, ",")
+	set["s_winner"] = s_winner
+	if tmp["package"] != nil {
+		set["package"] = tmp["package"] //没定义优先级
+	}
+	push := NewPushInfo(tmp)
+	for tkey, _ := range extractpos {
+		if tmp[tkey] != nil {
+			push[tkey] = tmp[tkey]
+		}
+	}
+	set["list"] = []bson.M{
+		push,
+	}
+	if mess != nil { //项目标识
+		for k, v := range mess {
+			set[k] = v
+		}
+	}
+	return MQFW.Save(projectColl, set)
+}
+
+//生成存放在redis数组中的对象
+func NewPinfo(id string, thisinfo *Info) ProjectInfo {
+	p1 := ProjectInfo{
+		Publistime:    []int64{thisinfo.Publishtime},
+		InfoType:      [][]string{[]string{thisinfo.TopType, thisinfo.SubType}},
+		Id:            id,
+		Ids:           []string{thisinfo.Id},
+		Topscopeclass: thisinfo.Topscopeclass,
+		Subscopeclass: thisinfo.Subscopeclass,
+		Winners:       thisinfo.Winners,
+		ProjectName:   thisinfo.ProjectName,
+		ProjectCode:   thisinfo.ProjectCode,
+		Buyer:         thisinfo.Buyer,
+		Agency:        thisinfo.Agency,
+		Area:          thisinfo.Area,
+		HasPackage:    thisinfo.HasPackage,
+		Package:       map[string]interface{}{},
+		Buyerclass:    thisinfo.Buyerclass,
+		Bidopentime:   thisinfo.Bidopentime,
+		District:      thisinfo.District,
+		Winnerorder:   thisinfo.Winnerorder,
+	}
+	for k4, _ := range thisinfo.Package {
+		p1.Package[k4] = ""
+	}
+	return p1
+}
+
+//每一个字段的打分map,获取最高分
+func GetMaxScore(scoremap map[int]int) (find bool, index int) {
+	ks := []int{}
+	vs := []int{}
+	for k, v := range scoremap {
+		mk, mv := -1, -100
+		bf := false
+		for mk, mv = range vs {
+			if mv > v {
+				bf = true
+				break
+			}
+		}
+		if mk == -1 || !bf {
+			vs = append(vs, v)
+			ks = append(ks, k)
+		} else {
+			vs = append(append(vs[:mk], v), vs[mk:]...)
+			ks = append(append(ks[:mk], k), ks[mk:]...)
+		}
+	}
+	if len(ks) > 0 {
+		index = ks[len(ks)-1]
+		find = true
+	}
+	return
+}
+
+//往对应redis中更新信息
+func updateinfo(thisinfo *Info, tmp map[string]interface{}, pInfo *ProjectInfo, pici int64) string {
+	updateid := pInfo.Id
+	if BinarySearch(pInfo.Ids, thisinfo.Id) > -1 {
+		return updateid
+	}
+	set := map[string]interface{}{
+		"pici": pici,
+	}
+	res, bres := MQFW.FindById(projectColl, pInfo.Id, `{"list":0}`)
+	EqInfoUpdate(thisinfo, pInfo)
+	if bres && res != nil && *res != nil {
+		set["topscopeclass"] = pInfo.Topscopeclass
+		set["subscopeclass"] = pInfo.Subscopeclass
+		s_subscopeclass := strings.Join(pInfo.Subscopeclass, ",")
+		if len(s_subscopeclass) > 0 {
+			s_subscopeclass = "," + s_subscopeclass + ","
+		}
+		set["s_subscopeclass"] = s_subscopeclass
+		s_winner := strings.Join(pInfo.Winners, ",")
+		if len(s_winner) > 0 {
+			s_winner = "," + s_winner + ","
+		}
+		set["s_winner"] = s_winner
+		if pInfo.Buyerperson != "" && pInfo.Buyertel != "" {
+			set["buyerperson"] = pInfo.Buyerperson
+			set["buyertel"] = pInfo.Buyertel
+		}
+		if pInfo.Buyerclass != "" {
+			set["buyerclass"] = pInfo.Buyerclass
+		}
+		if pInfo.District != "" {
+			set["district"] = pInfo.District
+		}
+		if pInfo.Bidopentime > 0 {
+			set["bidopentime"] = pInfo.Bidopentime
+		}
+		if len(pInfo.Winnerorder) > 0 {
+			set["winnerorder"] = pInfo.Winnerorder
+		}
+		if thisinfo.HasPackage {
+			set["multipackage"] = 1
+		} else {
+			set["multipackage"] = 0
+		}
+		e := InitEL(util.ObjToString((*res)["extractpos"]))
+		if thisinfo.dealtype == 1 {
+			var sonpackage map[string]interface{}
+			for _, obj := range tmp["package"].(map[string]interface{}) {
+				sonpackage, _ = obj.(map[string]interface{})
+			}
+			for _, v2 := range []string{"budget", "budget_w", "winner", "winner_w", "bidstatus", "bidstatus_w"} {
+				if sonpackage[v2] != nil {
+					tmp[v2] = sonpackage[v2]
+				}
+			}
+		}
+		e.fieldpriority(&tmp, res, &set)
+		set["extractpos"] = e.GetVal()
+		if thisinfo.HasPackage { //多包处理
+			p1, _ := (*res)["package"].(map[string]interface{})
+			p2, _ := tmp["package"].(map[string]interface{})
+			if p2 != nil {
+				if p1 != nil {
+					for pk2, pv2 := range p2 {
+						if p1[pk2] != nil { //合并
+							item1, _ := p1[pk2].(map[string]interface{})
+							item2, _ := pv2.(map[string]interface{})
+							if item1 != nil && item2 != nil { //原始项
+								for ik1, iv1 := range item2 {
+									if item1[ik1] == nil {
+										item1[ik1] = iv1
+									}
+								}
+							}
+						} else {
+							p1[pk2] = pv2
+						}
+					}
+				} else {
+					p1 = p2
+				}
+			}
+			set["package"] = p1
+		}
+		//中标候选人合并
+
+		update := map[string]interface{}{}
+		if len(set) > 0 {
+			update["$set"] = set
+		}
+		//保留原数据吧
+		push := NewPushInfo(tmp)
+		for tkey, _ := range extractpos {
+			if tmp[tkey] != nil {
+				push[tkey] = tmp[tkey]
+			}
+		}
+		update["$push"] = map[string]interface{}{
+			"list": push,
+		}
+		if len(update) > 0 {
+			MQFW.Update(projectColl, map[string]interface{}{
+				"_id": util.StringTOBsonId(pInfo.Id),
+			}, &update, false, false)
+		}
+	}
+	//再往redis中放 index
+	//往队列中增加时间 -------------->start
+	redis.Put(REDISIDS, updateid, pInfo, 0)
+	return updateid
+}
+
+func EqInfoUpdate(thisinfo *Info, pInfo *ProjectInfo) {
+	var tk int
+	bf1 := false
+	for _k, tv := range pInfo.Publistime {
+		tk = _k
+		if tv > thisinfo.Publishtime {
+			bf1 = true
+			break
+		}
+	}
+	if bf1 {
+		pInfo.Publistime = append(append(pInfo.Publistime[:tk], thisinfo.Publishtime), pInfo.Publistime[tk:]...)
+		pInfo.InfoType = append(append(pInfo.InfoType[:tk], []string{thisinfo.TopType, thisinfo.SubType}), pInfo.InfoType[tk:]...)
+		pInfo.Ids = append(append(pInfo.Ids[:tk], thisinfo.Id), pInfo.Ids[tk:]...)
+	} else {
+		pInfo.Publistime = append(pInfo.Publistime, thisinfo.Publishtime)
+		pInfo.InfoType = append(pInfo.InfoType, []string{thisinfo.TopType, thisinfo.SubType})
+		pInfo.Ids = append(pInfo.Ids, thisinfo.Id)
+	}
+	//增加发布时间结束----------------->end
+
+	if (pInfo.Buyer == "" && thisinfo.Buyer != "") || (len([]rune(pInfo.Buyer)) < 5 && len([]rune(thisinfo.Buyer)) > 5) {
+		pInfo.Buyer = thisinfo.Buyer
+	}
+	if (pInfo.Agency == "" && thisinfo.Agency != "") || (len([]rune(pInfo.Agency)) < 5 && len([]rune(thisinfo.Agency)) > 5) {
+		pInfo.Agency = thisinfo.Agency
+	}
+	if (pInfo.ProjectCode == "" && thisinfo.ProjectCode != "") || (len([]rune(pInfo.ProjectCode)) < 6 && len([]rune(thisinfo.ProjectCode)) > 6) {
+		pInfo.ProjectCode = thisinfo.ProjectCode
+	}
+
+	if thisinfo.Buyerperson != "" && thisinfo.Buyertel != "" && len([]rune(thisinfo.Buyertel)) > 6 {
+		pInfo.Buyerperson = thisinfo.Buyerperson
+		pInfo.Buyertel = thisinfo.Buyertel
+	}
+	if thisinfo.Buyerclass != "" {
+		pInfo.Buyerclass = thisinfo.Buyerclass
+	}
+	if thisinfo.District != "" {
+		pInfo.District = thisinfo.District
+	}
+	if thisinfo.Bidopentime > 0 {
+		pInfo.Bidopentime = thisinfo.Bidopentime
+	}
+	if len(thisinfo.Topscopeclass) > 0 {
+		sort.Strings(pInfo.Topscopeclass)
+		for _, k := range thisinfo.Topscopeclass {
+			if BinarySearch(pInfo.Topscopeclass, k) == -1 {
+				pInfo.Topscopeclass = append(pInfo.Topscopeclass, k)
+				sort.Strings(pInfo.Topscopeclass)
+			}
+		}
+	}
+
+	if len(thisinfo.Subscopeclass) > 0 {
+		sort.Strings(pInfo.Subscopeclass)
+		for _, k := range thisinfo.Subscopeclass {
+			if BinarySearch(pInfo.Subscopeclass, k) == -1 {
+				pInfo.Subscopeclass = append(pInfo.Subscopeclass, k)
+				sort.Strings(pInfo.Subscopeclass)
+			}
+		}
+	}
+	//winner
+	if len(thisinfo.Winners) > 0 {
+		sort.Strings(pInfo.Winners)
+		for _, k := range thisinfo.Winners {
+			if BinarySearch(pInfo.Winners, k) == -1 {
+				pInfo.Winners = append(pInfo.Winners, k)
+				sort.Strings(pInfo.Winners)
+			}
+		}
+	}
+	//winnerorder
+	if len(thisinfo.Winnerorder) > 0 {
+		sort.Strings(pInfo.Winnerorder)
+		for _, k := range thisinfo.Winnerorder {
+			if BinarySearch(pInfo.Winnerorder, k) == -1 {
+				pInfo.Winnerorder = append(pInfo.Winnerorder, k)
+				sort.Strings(pInfo.Winnerorder)
+			}
+		}
+	}
+	//return pInfo
+}
+
+//二分字符串查找
+func BinarySearch(s []string, k string) int {
+	sort.Strings(s)
+	lo, hi := 0, len(s)-1
+	for lo <= hi {
+		m := (lo + hi) >> 1
+		if s[m] < k {
+			lo = m + 1
+		} else if s[m] > k {
+			hi = m - 1
+		} else {
+			return m
+		}
+	}
+	return -1
+}
+
+//移除数组中重复的元素
+func RemoveDup(arr []string) (newarr []string) {
+	m1 := map[string]bool{}
+	newarr = []string{}
+	for _, k := range arr {
+		if !m1[k] {
+			m1[k] = true
+			newarr = append(newarr, k)
+		}
+	}
+	return
+}

+ 36 - 0
fullproject/src/config.json

@@ -0,0 +1,36 @@
+{
+    "mongodbServers": "192.168.3.207:27082",
+    "mongodbPoolSize": 10,
+    "mongodbName": "extract_v3",
+    "jkmail": {
+        "to": "zhangjinkun@topnet.net.cn",
+        "api": "http://10.171.112.160:19281/_send/_mail"
+    },
+    "thread": 1,
+    "extractColl": "bidding20190521",
+    "projectColl": "projectset",
+    "lenprojectname": 18,
+    "redisPoolSize": 60,
+    "redisaddrs": "ids=192.168.3.18:3379,keys=192.168.3.18:3379,info=192.168.3.18:3379",
+    "clearedis": {
+        "open": true,
+        "clearcron": "0 10 15 ? * 4",
+        "projectcycle": 180
+    },
+    "megerfields": {
+        "projectlen": 5,
+        "projectcodelen": 8
+    },
+    "taskstock": {
+        "open": true,
+        "endate": "2019-06-30"
+    },
+    "udpport": ":1482",
+    "nextNode": [
+        {
+            "addr": "127.0.0.1",
+            "port": 1483,
+            "memo": "创建项目索引"
+        }
+    ]
+}

+ 50 - 0
fullproject/src/datamonitor.go

@@ -0,0 +1,50 @@
+package main
+
+import (
+	"sync"
+	"time"
+)
+
+/**
+增加数据监控服务,每15分钟保存一次抽取情况
+**/
+var IS = &InfoStatus{
+	time.Now().Unix(), 0, map[string]int{}, &sync.Mutex{}}
+
+func init() {
+	go IS.Save()
+}
+
+type InfoStatus struct {
+	Starttime int64
+	Endtime   int64
+	Val       map[string]int
+	Lock      *sync.Mutex
+}
+
+func (is *InfoStatus) Add(t string) {
+	is.Lock.Lock()
+	is.Val[t]++
+	is.Lock.Unlock()
+}
+
+func (is *InfoStatus) Save() {
+	is.Lock.Lock()
+	is.Endtime = time.Now().Unix()
+	save := map[string]interface{}{}
+	all := 0
+	for _, v := range is.Val {
+		all += v
+	}
+	if all > 0 {
+		save["receive"] = all
+		save["starttime"] = is.Starttime
+		save["endtime"] = is.Endtime
+		save["flag"] = "projectser"
+		is.Val = map[string]int{}
+		go MQFW.Save("datamonitor", save)
+	}
+	is.Starttime = is.Endtime
+	is.Lock.Unlock()
+	time.AfterFunc(15*time.Minute, is.Save)
+}

+ 79 - 0
fullproject/src/extractarea.go

@@ -0,0 +1,79 @@
+package main
+
+import (
+	"qfw/util"
+)
+
+var CityConfig map[string]interface{}
+var AreaGet DFA //敏感词
+
+func initarea() {
+	util.ReadConfig("city.json", &CityConfig)
+	cp := CityConfig["city"].(map[string]interface{})
+	citys := []string{}
+	for k, _ := range cp {
+		citys = append(citys, k)
+	}
+	AreaGet = DFA{}
+	AreaGet.AddWord(citys...)
+}
+
+type DFA struct {
+	Link map[string]interface{}
+}
+
+func (d *DFA) AddWordAll(haskey bool, keys ...string) {
+	if d.Link == nil {
+		d.Link = make(map[string]interface{})
+	}
+	for _, key := range keys {
+		nowMap := &d.Link
+		for i := 0; i < len(key); i++ {
+			kc := key[i : i+1]
+			if v, ok := (*nowMap)[kc]; ok {
+				nowMap, _ = v.(*map[string]interface{})
+			} else {
+				newMap := map[string]interface{}{}
+				newMap["YN"] = "0"
+				(*nowMap)[kc] = &newMap
+				nowMap = &newMap
+			}
+			if i == len(key)-1 {
+				(*nowMap)["YN"] = "1"
+				if haskey {
+					(*nowMap)["K"] = key
+				}
+			}
+		}
+	}
+}
+
+func (d *DFA) AddWord(keys ...string) {
+	d.AddWordAll(false, keys...)
+}
+
+//适合一次查找
+func (d *DFA) CheckSensitiveWord(src string) (b bool) {
+	pos := 0
+	nowMap := &d.Link
+	for i := 0; i < len(src); i++ {
+		word := src[i : i+1]
+		nowMap, _ = (*nowMap)[word].(*map[string]interface{})
+		if nowMap != nil { // 存在,则判断是否为最后一个
+			if pos == 0 {
+				pos = i
+			}
+			if "1" == util.ObjToString((*nowMap)["YN"]) { // 如果为最后一个匹配规则,结束循环,返回匹配标识数
+				b = true
+				break
+			}
+		} else {
+			nowMap = &d.Link
+			if pos > 0 {
+				i = pos
+				pos = 0
+			}
+		}
+	}
+	return
+}

+ 240 - 0
fullproject/src/fulldata.go

@@ -0,0 +1,240 @@
+package main
+
+import (
+	"log"
+	"strings"
+
+	"qfw/util"
+	"qfw/util/mongodb"
+
+	"qfw/util/redis"
+	"sync"
+	"time"
+)
+
+var FullCount = 0
+
+func RunFullData() {
+	defer util.Catch()
+	var wg = sync.WaitGroup{}
+	startTime := int64(1325347200) //2012-01-01
+	ps := 3
+	pool := make(chan *task, ps)
+	day := 0
+	endChan := make(chan bool, 1)
+	go func() {
+		now := time.Now().Unix()
+		bComplete := false
+		for {
+			if startTime > now || bComplete {
+				log.Println("任务结束")
+				endChan <- true
+				break
+			}
+			endTime := startTime + 86400
+			q := map[string]interface{}{
+				"publishtime": map[string]interface{}{
+					"$gt":  startTime,
+					"$lte": endTime,
+				},
+			}
+
+			//数据正序处理
+			sess := MQFW.GetMgoConn()
+			var result []map[string]interface{}
+			sess.DB(MQFW.DbName).C(extractColl).Find(q).All(&result)
+			MQFW.DestoryMongoConn(sess)
+			pool <- &task{result}
+			wg.Add(1)
+			startTime = endTime
+			day++
+			log.Println("day====", day)
+			if day > 0 && day%ps == 0 {
+				wg.Wait()
+				MQFW.Destory()
+				MQFW = mongodb.MongodbSim{
+					MongodbAddr: Sysconfig["mongodbServers"].(string),
+					Size:        2 * ps,
+					DbName:      Sysconfig["mongodbName"].(string),
+				}
+				MQFW.InitPool()
+			}
+
+		}
+	}()
+
+	for {
+		select {
+		case t := <-pool:
+			t.query()
+			t.result = nil
+			t = nil
+			wg.Done()
+		case <-endChan:
+			return
+		}
+	}
+
+}
+
+type task struct {
+	result []map[string]interface{}
+}
+
+func (t *task) query() {
+	index := 0
+	wg := &sync.WaitGroup{}
+	for _, tmp := range t.result {
+		if index%10000 == 0 {
+			log.Println(index, tmp["_id"])
+		}
+		index++
+		if util.IntAll(tmp["repeat"]) == 1 {
+			continue
+		}
+		pt := util.Int64All(tmp["publishtime"])
+		if pt > currentMegerTime {
+			currentMegerTime = pt
+		}
+		currentMegerCount++
+		if currentMegerCount > 300000 {
+			log.Println("执行清理", currentMegerTime)
+			clearPKey()
+			currentMegerCount = 0
+		}
+		wg.Add(1)
+		MultiThread <- true
+		go func(tmp map[string]interface{}) {
+			defer func() {
+				<-MultiThread
+				wg.Done()
+			}()
+			thisid := util.BsonIdToSId(tmp["_id"])
+			info := PreThisInfo(tmp)
+			if info != nil {
+				lockPNCBMap(info)
+				startProjectMerge(info, tmp)
+				redis.Put(INFOID, thisid, 1, INFOTIMEOUT)
+				currentMegerTime = info.Publishtime
+				unlockPNCBMap(info)
+			}
+		}(tmp)
+	}
+	wg.Wait()
+	FullCount += index
+
+	log.Println("currentFull", FullCount)
+
+}
+
+type KeyMapPC struct {
+	Lock sync.Mutex
+	Map  map[string]*KeyMap
+}
+
+type CompareInfoPC struct {
+	Field    string        //对比属性 pn/pc/pb
+	Key      string        //存放rediskey
+	Scores   []*CompareOne //对比分值 pinfo索引对应分值
+	Bfind    bool          //是否查找到
+	IdArr    []string
+	K        *Key
+	KeyMapPC *KeyMapPC
+}
+
+func NewCompareInfoPC(field, key string, KeyMapPC *KeyMapPC) *CompareInfoPC {
+	return &CompareInfoPC{
+		Field:    field,
+		Key:      key,
+		Scores:   []*CompareOne{},
+		KeyMapPC: KeyMapPC,
+	}
+
+}
+
+var PNIdMap, PCIdMap = &KeyMapPC{Map: map[string]*KeyMap{}}, &KeyMapPC{Map: map[string]*KeyMap{}}
+
+//获取对比项目数组
+func getComeperProjects2(p PCBV, thisinfo *Info) (res []interface{}, pncb []*CompareInfo) {
+	newarr := []string{}
+	repeatId := map[string]bool{}
+	if p.PnameLen > 0 {
+		pn := NewCompareInfoPC("pn", thisinfo.PNKey, PNIdMap)
+		//对比全国和本省
+		PNIdMap.Lock.Lock()
+		km := PNIdMap.Map[thisinfo.Area]
+		if km == nil {
+			km = &KeyMap{Map: map[string]*Key{}}
+			PNIdMap.Map[thisinfo.Area] = km
+		}
+
+		PNIdMap.Lock.Unlock()
+
+		thisinfo.AllRelatePNKeyMap = map[string]*Key{}
+		pn.KeyMap.Lock.Lock()
+		for k, v := range pn.KeyMap.Map {
+			if strings.Contains(k, pn.Key) || strings.Contains(pn.Key, k) {
+				thisinfo.AllRelatePNKeyMap[k] = v
+				for _, id := range *v.Arr {
+					if !repeatId[id] {
+						newarr = append(newarr, id)
+						repeatId[id] = true
+					}
+				}
+			}
+		}
+		if thisinfo.AllRelatePNKeyMap[pn.Key] == nil {
+			K := &Key{&[]string{}, &sync.Mutex{}}
+			thisinfo.AllRelatePNKeyMap[pn.Key] = K
+			pn.KeyMap.Map[pn.Key] = K
+		}
+		pn.KeyMap.Lock.Unlock()
+	}
+	if p.PcodeLen > 0 {
+		pc := NewCompareInfo("pc", thisinfo.PCKey, PCKey)
+		pncb = append(pncb, pc)
+		thisinfo.AllRelatePCKeyMap = map[string]*Key{}
+		pc.KeyMap.Lock.Lock()
+		for k, v := range pc.KeyMap.Map {
+			if strings.Contains(k, pc.Key) || strings.Contains(pc.Key, k) {
+				thisinfo.AllRelatePCKeyMap[k] = v
+				for _, id := range *v.Arr {
+					if !repeatId[id] {
+						newarr = append(newarr, id)
+						repeatId[id] = true
+					}
+				}
+			}
+		}
+		if thisinfo.AllRelatePCKeyMap[pc.Key] == nil {
+			K := &Key{&[]string{}, &sync.Mutex{}}
+			thisinfo.AllRelatePCKeyMap[pc.Key] = K
+			pc.KeyMap.Map[pc.Key] = K
+		}
+		pc.KeyMap.Lock.Unlock()
+	}
+
+	if p.BuyerLen > 0 {
+		pb := NewCompareInfo("pb", thisinfo.PBKey, PBKey)
+		pncb = append(pncb, pb)
+		pb.KeyMap.Lock.Lock()
+		K := pb.KeyMap.Map[pb.Key]
+		if K == nil {
+			K = &Key{&[]string{}, &sync.Mutex{}}
+			pb.KeyMap.Map[pb.Key] = K
+		} else {
+			for _, id := range *K.Arr {
+				if !repeatId[id] {
+					newarr = append(newarr, id)
+					repeatId[id] = true
+				}
+			}
+		}
+		pb.KeyMap.Lock.Unlock()
+	}
+
+	if len(newarr) > 0 {
+		res = redis.Mget(REDISIDS, newarr)
+	}
+	return
+}

+ 205 - 0
fullproject/src/handleproject.go

@@ -0,0 +1,205 @@
+package main
+
+import (
+	"fmt"
+	"qfw/util"
+	"regexp"
+	"strings"
+)
+
+var pnreg = regexp.MustCompile("^(及编号[::])|(项目|采购|招标|中标|成交|结果|[_]|公告)$")
+var numreg = regexp.MustCompile("^[0-9]$")
+
+/**
+0 项目名称不是多包结构,直接按项目名称查找
+1 项目名称多包,截去多包查找,再按不截取的查找
+2 非招标项目名称含单个子包,截取多包查找,再搂
+**/
+func handleprojectname(pn, buyer, toptype string) (string, int) {
+	for i := 0; i < 4; i++ {
+		opn := pn
+		pn = pnreg.ReplaceAllString(opn, "")
+		if opn == pn {
+			break
+		}
+	}
+	//return pn
+	if len([]rune(pn)) > lenprojectname || strings.Index(pn, buyer) > -1 || AreaGet.CheckSensitiveWord(pn) {
+		return pn, 0
+	} else {
+		return buyer + pn, 0
+	}
+}
+
+//对字段的优先级处理
+type ExtractLevel struct {
+	Strarr []string
+}
+
+func InitEL(v string) (e *ExtractLevel) {
+	if v == "" {
+		v = "0999999999"
+		//第1位一下标为0,不用
+	}
+	Strarr := strings.Split(v, "")
+	e = &ExtractLevel{Strarr}
+	return
+}
+
+func (e *ExtractLevel) PutVal(field, val string) {
+	e.Strarr[extractpos[field]] = val
+}
+
+func (e *ExtractLevel) GetVal() string {
+	return strings.Join(e.Strarr, "")
+}
+
+//字段优先级处理
+func (e *ExtractLevel) fieldpriority(info, project, set *map[string]interface{}) {
+	defer util.Catch()
+	for _k, v := range extractpos {
+		breplace := false
+		var _infov interface{}
+		_infopos := fmt.Sprintf("%d", (*info)[_k+"_w"])
+		if !numreg.MatchString(_infopos) {
+			_infopos = "9"
+		}
+		if project == nil {
+			breplace = true
+			_infov = (*info)[_k]
+		} else {
+			ty := cextractpos[_k]
+			switch ty {
+			case 's':
+				_v := util.ObjToString((*project)[_k])
+				_tv := util.ObjToString((*info)[_k])
+				_infov = _tv
+				if _v == "" && _tv != "" {
+					breplace = true
+				} else if _tv != "" { //对比
+					if e.Strarr[v] > _infopos {
+						breplace = true
+					}
+				}
+			case 'l':
+				_v := util.Float64All((*project)[_k])
+				_tv := util.Float64All((*info)[_k])
+				_infov = _tv
+				if _v == 0 && _tv > 0 {
+					breplace = true
+				} else if _tv > 0 {
+					if e.Strarr[v] > _infopos {
+						breplace = true
+					}
+				}
+
+			}
+		}
+		if breplace {
+			(*set)[_k] = _infov
+			e.PutVal(_k, _infopos)
+		}
+	}
+	otherfieldpriority(info, project, set)
+}
+
+//抽取字段
+var cextractpos = map[string]rune{
+	"projectname":  's',
+	"projectcode":  's',
+	"buyer":        's',
+	"winner":       's',
+	"budget":       'l',
+	"bidamount":    'l',
+	"bidstatus":    's',
+	"agency":       's',
+	"projectscope": 's',
+}
+var extractpos = map[string]int{
+	"projectname":  0,
+	"projectcode":  1,
+	"buyer":        2,
+	"winner":       3,
+	"budget":       4,
+	"bidamount":    5,
+	"bidstatus":    6,
+	"agency":       7,
+	"projectscope": 8,
+}
+
+//合并字段
+//"area","city","topscopeclass","subscopeclass","bidtype","zbtime","jgtime","buyerclass"
+var bidtype = map[string]string{
+	"招标": "招标",
+	"邀标": "邀标",
+	"询价": "询价",
+	"竞谈": "竞谈",
+	"单一": "单一",
+	"竞价": "竞价",
+}
+
+func otherfieldpriority(info, project, set *map[string]interface{}) {
+	area2 := util.ObjToString((*info)["area"])
+	infoformat := util.IntAll((*info)["infoformat"])
+	toptype := util.ObjToString((*info)["toptype"])
+	topscopeclass := util.ObjToString((*info)["topscopeclass"])
+	subscopeclass := util.ObjToString((*info)["subscopeclass"])
+	bt := bidtype[util.ObjToString((*info)["subtype"])]
+	if project == nil {
+		if area2 == "" || area2 == "全国" {
+			area2 = "A"
+		}
+		(*set)["area"] = area2
+		(*set)["city"] = util.ObjToString((*info)["city"])
+		(*set)["topscopeclass"] = topscopeclass
+		(*set)["subscopeclass"] = subscopeclass
+		if bt == "" {
+			bt = "招标"
+		}
+		(*set)["bidtype"] = bt
+		if infoformat == 2 {
+			(*set)["njtime"] = (*info)["publishtime"]
+		} else {
+			if toptype == "招标" {
+				(*set)["zbtime"] = (*info)["publishtime"]
+			} else if toptype == "结果" {
+				(*set)["jgtime"] = (*info)["publishtime"]
+			}
+		}
+		if (*set)["zbtime"] == nil {
+			(*set)["zbtime"] = (*info)["publishtime"]
+		}
+	} else {
+		area := util.ObjToString((*project)["area"])
+		if area == "A" && (area2 != "" && area2 != "A" && area2 != "全国") {
+			(*set)["area"] = area2
+		}
+		publishtime := util.Int64All((*info)["publishtime"])
+		if infoformat == 2 {
+			//拟建信息,先不判断
+			if publishtime > 0 {
+				(*set)["njtime"] = publishtime
+			}
+		} else {
+			//招标信息
+			if toptype == "招标" {
+				zbtime := util.Int64All((*project)["zbtime"])
+				if publishtime > 0 && publishtime < zbtime {
+					(*set)["zbtime"] = publishtime
+				}
+			} else if toptype == "结果" {
+				jgtime := util.Int64All((*project)["jgtime"])
+				if publishtime > 0 && publishtime > jgtime {
+					(*set)["jgtime"] = publishtime
+				}
+			}
+		}
+		if subscopeclass != "" {
+			(*set)["topscopeclass"] = topscopeclass
+			(*set)["subscopeclass"] = subscopeclass
+		}
+		if bt != "" && bt != "招标" {
+			(*set)["bidtype"] = bt
+		}
+	}
+}

+ 101 - 0
fullproject/src/main.go

@@ -0,0 +1,101 @@
+package main
+
+import (
+	"qfw/util"
+	"qfw/util/mongodb"
+	"qfw/util/redis"
+	"sync"
+	"time"
+
+	"gopkg.in/mgo.v2/bson"
+)
+
+const (
+	REDISIDS    = "ids"
+	REDISKEYS   = "keys"
+	INFOID      = "info"
+	INFOTIMEOUT = 86400 * 30
+)
+
+var (
+	Sysconfig                map[string]interface{}
+	MQFW                     mongodb.MongodbSim
+	extractColl, projectColl string
+	lenprojectname           int
+	MultiThread              chan bool
+	IdLock                   = &sync.Mutex{}
+	PncbMayLock              = &sync.Mutex{}
+	MegerFieldsLen           *MegerFields
+	//三组lock,对应的(PNKey)key为项目名称,值对应的是此项目名称对应的项目id数组
+	PNKey, PCKey, PBKey          = NewKeyMap(), NewKeyMap(), NewKeyMap()
+	PNKeyMap, PCKeyMap, PBKeyMap = sync.Map{}, sync.Map{}, sync.Map{}
+
+	currentMegerTime  int64 //合并项目的时间位置,用来清理几个月之前的项目
+	currentMegerCount int   //合并项目的计数,用来定时清理
+)
+
+type MegerFields struct {
+	ProjectNamelen int
+	ProjectCodelen int
+}
+
+type KeyMap struct {
+	Lock sync.Mutex
+	Map  map[string]*Key
+}
+
+type Key struct {
+	Arr  *[]string
+	Lock *sync.Mutex
+}
+
+func NewKeyMap() *KeyMap {
+	return &KeyMap{
+		Map: map[string]*Key{},
+	}
+}
+
+func init() {
+	initarea()
+
+	util.ReadConfig(&Sysconfig)
+	MultiThread = make(chan bool, util.IntAllDef(Sysconfig["thread"], 200))
+	lenprojectname = util.IntAllDef(Sysconfig["lenprojectname"], 20) - 1
+	megerfields, _ := Sysconfig["megerfields"].(map[string]interface{})
+	MegerFieldsLen = &MegerFields{
+		ProjectNamelen: util.IntAllDef(megerfields["projectlen"], 5),
+		ProjectCodelen: util.IntAllDef(megerfields["projectcodelen"], 8),
+	}
+	redis.InitRedisBySize(Sysconfig["redisaddrs"].(string), util.IntAllDef(Sysconfig["redisPoolSize"], 100), 30, 300)
+	MQFW = mongodb.MongodbSim{
+		MongodbAddr: Sysconfig["mongodbServers"].(string),
+		Size:        util.IntAll(Sysconfig["mongodbPoolSize"]),
+		DbName:      Sysconfig["mongodbName"].(string),
+	}
+	MQFW.InitPool()
+	extractColl = Sysconfig["extractColl"].(string)
+	projectColl = Sysconfig["projectColl"].(string)
+}
+
+func main() {
+	RunFullData()
+	time.Sleep(99999 * time.Hour)
+}
+
+func NewPushInfo(tmp map[string]interface{}) bson.M {
+	return bson.M{
+		"comeintime":  tmp["comeintime"],
+		"publishtime": tmp["publishtime"],
+		"title":       tmp["title"],
+		"toptype":     tmp["toptype"],
+		"subtype":     tmp["subtype"],
+		"infoformat":  tmp["infoformat"],
+		"infoid":      util.BsonIdToSId(tmp["_id"]),
+		"href":        tmp["href"],
+		"area":        tmp["area"],
+		"city":        tmp["city"],
+
+		"cresult": tmp["cresult"],
+		"score":   tmp["score"],
+	}
+}

+ 58 - 0
fullproject/src/main_test.go

@@ -0,0 +1,58 @@
+package main
+
+import (
+	"fmt"
+	"log"
+	"testing"
+)
+
+func Test_main(t *testing.T) {
+	m1 := map[string]*[]string{}
+	s := m1["dd"]
+	log.Println("aaaaa1")
+	func() {
+		if s == nil {
+			defer func() {
+				log.Println("defer")
+			}()
+			s = &[]string{}
+			m1["dd"] = s
+			log.Println("aaa3")
+		}
+	}()
+	n := 0
+	for {
+		defer func(n int) {
+			log.Println("for", n)
+		}(n)
+		n++
+		log.Println(n)
+		if n > 2 {
+			break
+		}
+	}
+	log.Println("aaa2")
+	*s = append(*s, "aa")
+	log.Println("---m1[dd]:", m1["dd"])
+
+	//arr := []string{"aa", "bb", "cc", "dd", "ee", "abdsfsdfsd"}
+	//log.Println("二分查找", binarySearch(arr, "bb"))
+}
+func Test_3t2(t *testing.T) {
+	pcb := [][]string{
+		[]string{"A", "B"},
+		[]string{"A", "B"},
+		[]string{"A", "B"},
+	}
+	for _, v1 := range pcb[0] {
+		tmp := []string{}
+		for _, v2 := range pcb[1] {
+			for _, v3 := range pcb[1] {
+				key := fmt.Sprintf("%s%s%s", v1, v2, v3)
+				tmp = append(tmp, key)
+			}
+		}
+		log.Println(tmp)
+	}
+
+}

+ 615 - 0
fullproject/src/projectmeger.go

@@ -0,0 +1,615 @@
+// projectmeger
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	du "jy/util"
+	"log"
+	qu "qfw/util"
+	"qfw/util/redis"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+//有效值三选一、三选二
+var ThreeToTow, ThreeToOne map[string]bool
+
+func init() {
+	ThreeToTow = map[string]bool{}
+	ThreeToOne = map[string]bool{
+		"AAA": true,
+		"AAB": true,
+	}
+	tows := [][][]string{
+		[][]string{
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+		},
+		[][]string{
+			[]string{"A", "B"},
+			[]string{"D", "E"},
+			[]string{"A", "B"},
+		},
+		[][]string{
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+			[]string{"D", "E"},
+		},
+		[][]string{
+			[]string{"D", "E"},
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+		},
+	}
+	for _, tow := range tows {
+		for _, v1 := range tow[0] {
+			for _, v2 := range tow[1] {
+				for _, v3 := range tow[2] {
+					key := fmt.Sprintf("%s%s%s", v1, v2, v3)
+					log.Println(key)
+					ThreeToTow[key] = true
+				}
+			}
+		}
+	}
+}
+
+func startProjectMerge(thisinfo *Info, tmp map[string]interface{}) {
+	bNormalScore := false
+	pcbv := PCBVal(tmp)
+	if checkInfoAlter(tmp) { //进入变更信息流程
+		if pcbv.Val > 1 { //判断三项至少包含两项
+			bNormalScore = true
+		} else {
+			extInfoTag("invalid", qu.BsonIdToSId(tmp["_id"])) //无效信息,打标记
+			//go IS.Add("invalid")                              //数据统计使用
+			return
+		}
+	} else {
+		bNormalScore = true
+	}
+	//合并流程
+	if bNormalScore {
+		PNKeyMap.Store(thisinfo.PNKey, true)
+		PBKeyMap.Store(thisinfo.PBKey, true)
+		PCKeyMap.Store(thisinfo.PCKey, true)
+		if pcbv.Buyer { //有采购单位
+			hasBuyer(pcbv, thisinfo, tmp)
+		} else { //无采购单位
+			noBuyer(pcbv, thisinfo, tmp)
+		}
+	}
+}
+
+//判断信息是否是变更
+func checkInfoAlter(tmp map[string]interface{} /*新信息*/) bool {
+	toptype := qu.ObjToString(tmp["toptype"])
+	subtype := qu.ObjToString(tmp["subtype"])
+	title := qu.ObjToString(tmp["title"])
+	if subtype == "变更" || strings.Index(title, "变更公告") > -1 || strings.Index(title, "更正公告") > -1 {
+		//当信息类型是变更或标题中含变更时
+		if toptype == "招标" {
+			//招标的变更公告,不作处理
+		} else if toptype == "结果" {
+			subtype = "变更"
+		}
+	}
+	return subtype == "变更"
+}
+
+//有采购单位
+func hasBuyer(p PCBV, thisinfo *Info, tmp map[string]interface{}) {
+	var pncb []*CompareInfo
+	var res []interface{}
+	sflag := ""
+	pici := time.Now().Unix()
+	if p.Pname || p.Pcode { //有项目名称或项目编号
+		//获取对比项目数组
+		res, pncb = getComeperProjects(p, thisinfo)
+		//三选二打分
+		scores := score3Select2(p, thisinfo, tmp, res, pncb)
+		//项目合并
+		sflag = mergeProject(tmp, thisinfo, scores, pncb)
+	} else {
+		//生成项目,不参与后续对比
+		sflag = "alone"
+		mess := map[string]interface{}{
+			"meger_mess":  "有采购单位,不满足三选二",
+			"meger_sflag": sflag,
+		}
+		newProject(tmp, mess, pici, thisinfo)
+	}
+	extInfoTag(sflag, thisinfo.Id)
+	//go IS.Add(sflag) //数据统计使用
+}
+
+//无采购单位
+func noBuyer(p PCBV, thisinfo *Info, tmp map[string]interface{}) {
+	var pncb []*CompareInfo
+	var res []interface{}
+	sflag := ""
+	pici := time.Now().Unix()
+	if p.Pname { //有项目名称
+		//获取对比项目数组
+		res, pncb = getComeperProjects(p, thisinfo)
+		if p.Pcode { //有项目编号
+			//三选二打分
+			scores := score3Select2(p, thisinfo, tmp, res, pncb)
+			//项目合并
+			sflag = mergeProject(tmp, thisinfo, scores, pncb)
+		} else { //无项目编号
+			if p.PnameLen > MegerFieldsLen.ProjectNamelen {
+				//三选一打分
+				scores := score3Select1(p, thisinfo, tmp, res, pncb)
+				//项目合并
+				sflag = mergeProject(tmp, thisinfo, scores, pncb)
+			} else {
+				//生成项目,不参与后续对比
+				sflag = "alone"
+				mess := map[string]interface{}{
+					"meger_mess":  "无采购单位,不满足三选一",
+					"meger_sflag": sflag,
+				}
+				newProject(tmp, mess, pici, thisinfo)
+			}
+		}
+	} else { //无项目名称
+		if p.Pcode {
+			//获取对比项目数组
+			res, pncb = getComeperProjects(p, thisinfo)
+			if p.PcodeLen > MegerFieldsLen.ProjectCodelen {
+				if p.Area && p.City && p.Agency { //有省市代理机构
+					//三选一打分
+					scores := score3Select1(p, thisinfo, tmp, res, pncb)
+					//项目合并
+					sflag = mergeProject(tmp, thisinfo, scores, pncb)
+				} else {
+					//生成项目,不参与后续对比
+					sflag = "alone"
+					mess := map[string]interface{}{
+						"meger_mess":  "无采购单位,不满足三选一",
+						"meger_sflag": sflag,
+					}
+					newProject(tmp, mess, pici, thisinfo)
+				}
+			} else {
+				//生成项目,不参与后续对比
+				sflag = "alone"
+				mess := map[string]interface{}{
+					"meger_mess":  "无采购单位,不满足三选一",
+					"meger_sflag": sflag,
+				}
+				newProject(tmp, mess, pici, thisinfo)
+			}
+		} else {
+			//信息无效,打标记
+			sflag = "invalid"
+		}
+	}
+	extInfoTag(sflag, thisinfo.Id)
+	//go IS.Add(sflag) //数据统计使用
+}
+
+//3选2打分
+func score3Select2(p PCBV, thisinfo *Info, tmp map[string]interface{}, res []interface{}, pncb []*CompareInfo) (scores []*CompareOne) {
+	defer qu.Catch()
+	if len(res) > 0 {
+		//对比打分
+		for k, tmps := range res { //遍历对象数组
+			if tmp, ok := tmps.([]interface{}); ok {
+				for _, b1 := range tmp {
+					if b1 != nil {
+						var info ProjectInfo
+						err := json.Unmarshal(b1.([]byte), &info)
+						if err != nil {
+							log.Println(err)
+						}
+						cone := &CompareOne{
+							Parent: pncb[k],
+							Pinfo:  &info,
+						}
+						cone.BuyerType, cone.Score = fieldPCBScore(thisinfo.Buyer, info.Buyer, cone.BuyerType, cone.Score)
+						if p.Buyer {
+							cone.ProjectNameType, cone.Score = fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
+							cone.ProjectCodeType, cone.Score = fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
+						} else { //无采购单位,打分考虑长度
+							if len([]rune(thisinfo.ProjectName)) > MegerFieldsLen.ProjectNamelen {
+								cone.ProjectNameType, cone.Score = fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
+							} else {
+								cone.ProjectNameType = "D"
+							}
+							if len(thisinfo.ProjectCode) > MegerFieldsLen.ProjectCodelen {
+								cone.ProjectCodeType, cone.Score = fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
+							} else {
+								cone.ProjectCodeType = "D"
+							}
+						}
+						//省市打分
+						if thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
+							if thisinfo.Area == info.Area && thisinfo.City == info.City {
+								cone.Score += 2
+							} else {
+								cone.Score -= 1
+							}
+						} else {
+							cone.Score += 1
+						}
+						//代理机构打分
+						if len([]rune(info.Agency)) > 0 {
+							if thisinfo.Agency == info.Agency { //A
+								cone.Score += 2
+							} else if strings.Index(info.Agency, thisinfo.Agency) > -1 || strings.Index(thisinfo.Agency, info.Agency) > -1 { //B
+								cone.Score += 1
+							} else {
+								if len(thisinfo.Agency) < 1 { //E
+									cone.Score -= 1
+								} else { //C
+									cone.Score -= 2
+								}
+							}
+						} else { //D不计分
+							//
+						}
+						skey := fmt.Sprintf("%s%s%s", cone.BuyerType, cone.ProjectNameType, cone.ProjectCodeType)
+						cone.Cresult = skey
+						if ThreeToTow[skey] {
+							scores = append(scores, cone)
+						}
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+//3选1打分
+func score3Select1(p PCBV, thisinfo *Info, tmp map[string]interface{}, res []interface{}, pncb []*CompareInfo) (scores []*CompareOne) {
+	defer qu.Catch()
+	//对比打分
+	if len(res) > 0 { //找到项目名称、项目编号或采购单位相同时
+		for k, tmps := range res { //遍历对象数组
+			if tmp, ok := tmps.([]interface{}); ok {
+				for _, b1 := range tmp {
+					if b1 != nil {
+						var info ProjectInfo
+						err := json.Unmarshal(b1.([]byte), &info)
+						if err != nil {
+							log.Println(err)
+						}
+						cone := &CompareOne{
+							Parent: pncb[k],
+							Pinfo:  &info,
+						}
+						if pncb[k].Field == "pn" { //比较字段项目名称
+							if len(info.ProjectName) > 0 {
+								if thisinfo.ProjectName == info.ProjectName { //A
+									cone.Score += 2
+									cone.ProjectNameType = "A"
+								} else if strings.Index(info.ProjectName, thisinfo.ProjectName) > -1 || strings.Index(thisinfo.ProjectName, info.ProjectName) > -1 { //B
+									cone.Score += 1
+									cone.ProjectNameType = "B"
+								} else { //C
+									cone.Score -= 2
+									cone.ProjectNameType = "C"
+								}
+							} else { //D不计分
+								cone.ProjectNameType = "D"
+							}
+						}
+						if pncb[k].Field == "pc" { //比较字段项目编号
+							if len(info.ProjectCode) > 0 {
+								if thisinfo.ProjectCode == info.ProjectCode { //A
+									cone.Score += 2
+									cone.ProjectCodeType = "A"
+								} else if strings.Index(info.ProjectCode, thisinfo.ProjectCode) > -1 || strings.Index(thisinfo.ProjectCode, info.ProjectCode) > -1 { //B
+									cone.Score += 1
+									cone.ProjectCodeType = "B"
+								} else { //C
+									cone.Score -= 2
+									cone.ProjectCodeType = "C"
+								}
+							} else { //D不计分
+								cone.ProjectCodeType = "D"
+							}
+						}
+						if thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
+							if thisinfo.Area == info.Area && thisinfo.City == info.City {
+								cone.Score += 2
+								cone.AreaType = "A"
+							} else {
+								cone.Score -= 1
+								cone.AreaType = "C"
+							}
+						} else {
+							cone.Score += 1
+							cone.AreaType = "B"
+						}
+						if len([]rune(info.Agency)) > 0 {
+							if thisinfo.Agency == info.Agency { //A
+								cone.Score += 2
+								cone.AgencyType = "A"
+							} else if strings.Index(info.Agency, thisinfo.Agency) > -1 || strings.Index(thisinfo.Agency, info.Agency) > -1 { //B
+								cone.Score += 1
+								cone.AgencyType = "B"
+							} else {
+								if len(thisinfo.Agency) < 1 { //E
+									cone.Score -= 1
+									cone.AgencyType = "E"
+								} else { //C
+									cone.Score -= 2
+									cone.AgencyType = "C"
+								}
+							}
+						} else { //D不计分
+							cone.AgencyType = "D"
+						}
+						skey := fmt.Sprintf("%s%s%s", cone.BuyerType, cone.ProjectNameType, cone.ProjectCodeType)
+						cone.Cresult = skey
+						if ThreeToOne[skey] {
+							scores = append(scores, cone)
+						}
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+//获取对比项目数组
+func getComeperProjects(p PCBV, thisinfo *Info) (res []interface{}, pncb []*CompareInfo) {
+	if p.PnameLen > 0 {
+		pn := NewCompareInfo("pn", thisinfo.PNKey, PNKey)
+		pncb = append(pncb, pn)
+	}
+	if p.PcodeLen > 0 {
+		pc := NewCompareInfo("pc", thisinfo.PCKey, PCKey)
+		pncb = append(pncb, pc)
+	}
+	if p.BuyerLen > 0 {
+		pb := NewCompareInfo("pb", thisinfo.PBKey, PBKey)
+		pncb = append(pncb, pb)
+	}
+	repeatId := map[string]bool{}
+	IdLock.Lock() //此处加id锁,会引进多线程的死锁,对比三个大map数组,找到key相同的项目id数组,并去重
+	for _, pv := range pncb {
+		if pv != nil {
+			pv.KeyMap.Lock.Lock()
+			K := pv.KeyMap.Map[pv.Key]
+			if K == nil {
+				K = &Key{&[]string{}, &sync.Mutex{}}
+				pv.KeyMap.Map[pv.Key] = K
+			}
+			pv.K = K
+			pv.K.Lock.Lock()
+			pv.KeyMap.Lock.Unlock()
+			defer pv.K.Lock.Unlock()
+			newarr := []string{}
+			for _, id := range *K.Arr {
+				if !repeatId[id] {
+					newarr = append(newarr, id)
+					repeatId[id] = true
+				}
+			}
+			pv.IdArr = newarr
+		}
+	}
+	IdLock.Unlock()
+	for _, pv := range pncb {
+		if len(pv.IdArr) > 0 {
+			res = append(res, redis.Mget(REDISIDS, pv.IdArr))
+		}
+	}
+	return
+}
+
+//合并项目
+func mergeProject(tmp map[string]interface{}, thisinfo *Info, scores []*CompareOne, pncb []*CompareInfo) (sflag string) {
+	var id = ""
+	//分值排序
+	sort.Slice(scores, func(i, j int) bool {
+		return scores[i].Score > scores[j].Score
+	})
+	if len(scores) > 0 {
+		//分值排序
+		sort.Slice(scores, func(i, j int) bool {
+			return scores[i].Score > scores[j].Score
+		})
+		max := scores[0]
+		if max.Score > 0 {
+			sflag = "repeat"
+			max.Parent.Bfind = true
+			tmp["cresult"] = max.Cresult
+			tmp["score"] = max.Score
+			id = updateinfo(thisinfo, tmp, max.Pinfo, time.Now().Unix())
+			//log.Println(sflag, id, max.Cresult)
+			if len(scores) > 1 && (scores[0].Score == scores[1].Score) {
+				//通知检查,异常数据存库
+				checkNotice(thisinfo.Id, id, scores)
+			}
+		} else {
+			sflag = "invalidscore"
+		}
+	} else {
+		//生成项目
+		sflag = "normal"
+		mess := map[string]interface{}{
+			"meger_sflag": sflag,
+		}
+		id = newProject(tmp, mess, time.Now().Unix(), thisinfo)
+	}
+	if id != "" { //更新REDISKEYS redis
+		put := []interface{}{}
+		for _, pv := range pncb {
+			if pv != nil && !pv.Bfind {
+				if BinarySearch(*pv.K.Arr, id) == -1 {
+					*(pv.K.Arr) = append(*(pv.K.Arr), id)
+					put = append(put, []interface{}{pv.Key, *(pv.K.Arr)})
+				}
+			}
+		}
+		if len(put) > 0 {
+			redis.BulkPut(REDISKEYS, 0, put...)
+		}
+	}
+	return sflag
+}
+
+//新增项目
+func newProject(tmp, mess map[string]interface{}, pipc int64, thisinfo *Info) (id string) {
+	id = InsertProject(thisinfo.NewPNKey, tmp, mess, pipc, thisinfo)
+	sflag := qu.ObjToString(mess["meger_sflag"])
+	if sflag != "alone" {
+		p1 := NewPinfo(id, thisinfo)
+		redis.PutCKV(REDISIDS, id, p1)
+	} else {
+		du.Debug("新增项目,不参与对比", id)
+	}
+	return id
+}
+
+//抽取信息打标记
+func extInfoTag(sflag, id string) {
+	MQFW.UpdateById(extractColl, id,
+		map[string]interface{}{
+			"$set": map[string]interface{}{
+				"meger_sflag": sflag,
+			},
+		})
+}
+
+//检查通知
+func checkNotice(infoid, pid string, scores []*CompareOne) {
+	MQFW.Update("project_unusual", `{"project_id":"`+pid+`"}`,
+		map[string]interface{}{
+			"$set": map[string]interface{}{
+				"project_id": pid,
+				"pici":       time.Now().Unix(),
+			},
+			"$push": map[string]interface{}{
+				"list": map[string]interface{}{
+					"infoid": infoid,
+					"pinfo1": scores[0].Pinfo.Id,
+					"pinfo2": scores[1].Pinfo.Id,
+				},
+			},
+		}, true, false)
+	du.Debug("通知检查,异常数据存库", infoid, pid)
+}
+
+//属性判断组
+func PCBVal(tmp map[string]interface{}) PCBV {
+	pcbv := PCBV{}
+	projectName := qu.ObjToString(tmp["projectname"])
+	if len([]rune(projectName)) > 1 {
+		pcbv.Val += 1
+		pcbv.Pname = true
+		pcbv.PnameLen = len([]rune(projectName))
+	}
+	projectCode := qu.ObjToString(tmp["projectcode"])
+	if len([]rune(projectCode)) > 1 {
+		pcbv.Val += 1
+		pcbv.Pcode = true
+		pcbv.PcodeLen = len(projectCode)
+	}
+	buyer := qu.ObjToString(tmp["buyer"])
+	if len([]rune(buyer)) > 1 {
+		pcbv.Val += 1
+		pcbv.Buyer = true
+		pcbv.BuyerLen = len([]rune(buyer))
+	}
+	//省市代理机构
+	if qu.ObjToString(tmp["area"]) != "" {
+		pcbv.Area = true
+	}
+	if qu.ObjToString(tmp["city"]) != "" {
+		pcbv.City = true
+	}
+	if qu.ObjToString(tmp["agency"]) != "" {
+		pcbv.Agency = true
+	}
+	return pcbv
+}
+
+//项目名称、项目编号、采购单位打分
+func fieldPCBScore(this, info, ctype string, score int) (string, int) {
+	if len(info) > 0 {
+		if this == info { //A
+			score += 5
+			ctype = "A"
+		} else if strings.Index(info, this) > -1 || strings.Index(this, info) > -1 { //B
+			score += 2
+			ctype = "B"
+		} else {
+			if len(this) < 1 { //E
+				score -= 1
+				ctype = "E"
+			} else { //C
+				score -= 2
+				ctype = "C"
+			}
+		}
+	} else { //D不计分
+		ctype = "D"
+	}
+	return ctype, score
+}
+
+//pncbMap加锁
+func lockPNCBMap(thisinfo *Info) {
+	for { //等待其他任务完成
+		ok := true
+		if len(thisinfo.PBKey) > 3 {
+			if _, b := PBKeyMap.Load(thisinfo.PBKey); b {
+				ok = false
+			}
+		}
+		if ok && len(thisinfo.PNKey) > 3 {
+			PNKeyMap.Range(func(k, v interface{}) bool {
+				if strings.Contains(k.(string), thisinfo.PNKey) || strings.Contains(thisinfo.PNKey, k.(string)) {
+					ok = false
+					return false
+				}
+				return true
+			})
+			//			if _, b := PNKeyMap.Load(thisinfo.PNKey); b {
+			//				ok = false
+			//			}
+		}
+		if ok && len(thisinfo.PCKey) > 3 {
+			PCKeyMap.Range(func(k, v interface{}) bool {
+				if strings.Contains(k.(string), thisinfo.PCKey) || strings.Contains(thisinfo.PCKey, k.(string)) {
+					ok = false
+					return false
+				}
+				return true
+			})
+			//			if _, b := PCKeyMap.Load(thisinfo.PCKey); b {
+			//				ok = false
+			//			}
+		}
+		if ok {
+			break
+		} else {
+			time.Sleep(10 * time.Millisecond)
+		}
+	}
+}
+
+//pncbMap解锁
+func unlockPNCBMap(thisinfo *Info) {
+	//if len(thisinfo.PNKey) > 3 {
+	PNKeyMap.Delete(thisinfo.PNKey)
+	//}
+	//if len(thisinfo.PCKey) > 3 {
+	PCKeyMap.Delete(thisinfo.PCKey)
+	//}
+	//if len(thisinfo.PBKey) > 3 {
+	PBKeyMap.Delete(thisinfo.PBKey)
+	//}
+}

+ 153 - 0
fullproject/src/thisinfo.go

@@ -0,0 +1,153 @@
+// thisinfo
+package main
+
+import (
+	"crypto/sha1"
+	"encoding/json"
+	"fmt"
+	"io"
+	du "jy/util"
+	"qfw/util"
+	"strings"
+
+	"gopkg.in/mgo.v2/bson"
+)
+
+//抽取信息映射实体类
+type Info struct {
+	Id            string                 `json:"_id"`
+	Href          string                 `json:"href"`
+	Publishtime   int64                  `json:"publishtime"`
+	Title         string                 `json:"title"`
+	TopType       string                 `json:"toptype"`
+	SubType       string                 `json:"subtype"`
+	ProjectName   string                 `json:"projectname"`
+	ProjectCode   string                 `json:"projectcode"`
+	Buyer         string                 `json:"buyer"`
+	Buyerperson   string                 `json:"buyerperson"`
+	Buyertel      string                 `json:"buyertel"`
+	Agency        string                 `json:"agency"`
+	Area          string                 `json:"area"`
+	City          string                 `json:"city"`
+	HasPackage    bool                   `json:"haspackage"`
+	Package       map[string]interface{} `json:"package"`
+	PNum          string                 `json:"pnum"`
+	Topscopeclass []string               `json:"topscopeclass"`
+	Subscopeclass []string               `json:"subscopeclass"`
+	Winners       []string
+	dealtype      int
+
+	Buyerclass  string `json:"buyerclass"`
+	Bidopentime int64  `json:"bidopentime"`
+	District    string `json:"district"`
+	Winnerorder []string
+
+	NewPNKey string
+	PNKey    string
+	PCKey    string
+	PBKey    string
+
+	AllRelatePNKeyMap map[string]*Key
+	AllRelatePCKeyMap map[string]*Key
+}
+
+//pcb三选值
+type PCBV struct {
+	Val    int  //1一项有效值,2二项有效值,3三项有效值
+	Pname  bool //有项目名称
+	Pcode  bool //有项目编号
+	Buyer  bool //有采购单位
+	Area   bool //区域
+	City   bool //市
+	Agency bool //代理机构
+
+	PnameLen int //值长度
+	PcodeLen int //值长度
+	BuyerLen int //值长度
+}
+
+func PreThisInfo(tmp map[string]interface{} /*新信息*/) *Info {
+	bys, _ := json.Marshal(tmp)
+	var thisinfo *Info
+	json.Unmarshal(bys, &thisinfo)
+	if thisinfo == nil {
+		return nil
+	}
+	if len(thisinfo.Topscopeclass) == 0 {
+		thisinfo.Topscopeclass = []string{}
+	}
+	if len(thisinfo.Subscopeclass) == 0 {
+		thisinfo.Subscopeclass = []string{}
+	}
+	//去重
+	thisinfo.Subscopeclass = RemoveDup(thisinfo.Subscopeclass)
+
+	if len(thisinfo.Package) > 0 { //信息是否分包
+		thisinfo.HasPackage = true
+	} else if thisinfo.TopType == "结果" && TitleReg.MatchString(thisinfo.Title) {
+		//当信息类型是结果时,并且标题中包含分包字样,找到包号,用以后面比较打分
+		res := TitleReg.FindAllStringSubmatch(thisinfo.Title, -1)
+		pnum := du.PackageNumberConvert(res[0][0])
+		//du.Debug(pnum, res)
+		thisinfo.PNum = pnum
+	}
+	if thisinfo.SubType == "变更" || strings.Index(thisinfo.Title, "变更公告") > -1 || strings.Index(thisinfo.Title, "更正公告") > -1 {
+		//当信息类型是变更或标题中含变更时
+		if thisinfo.TopType == "招标" {
+			//招标的变更公告过,不作处理
+			//du.Debug(thisinfo.Id, thisinfo.Href, thisinfo.ProjectName, thisinfo.ProjectCode)
+			return nil
+		} else if thisinfo.TopType == "结果" {
+			thisinfo.SubType = "变更"
+		}
+	}
+
+	//计算中标人
+	winner, _ := tmp["winner"].(string)
+	m1 := map[string]bool{}
+	winners := []string{}
+	if winner != "" {
+		m1[winner] = true
+		winners = append(winners, winner)
+	}
+	if thisinfo.HasPackage {
+		packageM, _ := tmp["package"].(bson.M)
+		for _, p := range packageM {
+			pm, _ := p.(map[string]interface{})
+			pw, _ := pm["winner"].(string)
+			if pw != "" {
+				m1[pw] = true
+				winners = append(winners, pw)
+			}
+		}
+	}
+	thisinfo.Winners = winners
+	m1 = nil
+	//中标候选人
+	winnerorder := []string{}
+	if winorders, ok := tmp["winnerorder"].([]interface{}); ok {
+		for _, wins := range winorders {
+			if win, ok := wins.(map[string]interface{}); ok {
+				entname := util.ObjToString(win["entname"])
+				if entname != "" && len([]rune(entname)) > 6 {
+					winnerorder = append(winnerorder, entname)
+				}
+			}
+		}
+	}
+	thisinfo.Winnerorder = winnerorder
+
+	new_pn, _ := handleprojectname(thisinfo.ProjectName, thisinfo.Buyer, thisinfo.TopType) //作为判断依据
+	thisinfo.NewPNKey = new_pn
+	thisinfo.PNKey = "pn_" + new_pn
+	thisinfo.PCKey = "pc_" + thisinfo.ProjectCode
+	thisinfo.PBKey = "pb_" + thisinfo.Buyer
+	return thisinfo
+}
+
+//获取hascode
+func GetHas1(key string) string {
+	t := sha1.New()
+	io.WriteString(t, key)
+	return fmt.Sprintf("%x", t.Sum(nil))
+}

+ 57 - 0
fullproject/src/udptaskmap.go

@@ -0,0 +1,57 @@
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+	"sync"
+	"time"
+)
+
+var udptaskmap = &sync.Map{}
+var tomail string
+var api string
+
+type udpNode struct {
+	data      []byte
+	addr      *net.UDPAddr
+	timestamp int64
+	retry     int
+}
+
+func checkMapJob() {
+	//阿里云内网无法发送邮件
+	jkmail, _ := Sysconfig["jkmail"].(map[string]interface{})
+	if jkmail != nil {
+		tomail, _ = jkmail["to"].(string)
+		api, _ = jkmail["api"].(string)
+	}
+	log.Println("start checkMapJob", tomail, Sysconfig["jkmail"])
+	for {
+		udptaskmap.Range(func(k, v interface{}) bool {
+			now := time.Now().Unix()
+			node, _ := v.(*udpNode)
+			if now-node.timestamp > 120 {
+				node.retry++
+				if node.retry > 5 {
+					log.Println("udp重试失败", k)
+					udptaskmap.Delete(k)
+					res, err := http.Get(fmt.Sprintf("%s?to=%s&title=%s&body=%s", api, tomail, "extract-send-fail", k.(string)))
+					if err == nil {
+						defer res.Body.Close()
+						read, err := ioutil.ReadAll(res.Body)
+						log.Println("邮件发发送:", string(read), err)
+					}
+				} else {
+					log.Println("udp重发", k)
+				}
+			} else if now-node.timestamp > 10 {
+				log.Println("udp任务超时中..", k)
+			}
+			return true
+		})
+		time.Sleep(60 * time.Second)
+	}
+}

+ 9 - 2
src/jy/admin/rulecheck.go

@@ -198,6 +198,8 @@ func checkPreReg(content, ruleText string) string {
 		tmp := strings.Split(ruleText, "__")
 		var pattern string
 		if strings.Contains(tmp[0], "\\u") {
+			tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+			tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 			pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 		} else {
 			pattern = tmp[0]
@@ -222,6 +224,8 @@ func checkBackReg(content, ruleText string) string {
 		tmp := strings.Split(ruleText, "__")
 		var pattern string
 		if strings.Contains(tmp[0], "\\u") {
+			tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+			tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 			pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 		} else {
 			pattern = tmp[0]
@@ -258,10 +262,13 @@ func checkCoreReg(field, content, ruleText string) map[string]string {
 			}
 			var pattern string
 			if strings.Contains(tmp[0], "\\u") {
+				tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+				tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 				pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 			} else {
 				pattern = tmp[0]
 			}
+			log.Println("pattern", pattern)
 			reg := regexp.MustCompile(pattern)
 			apos := reg.FindAllStringSubmatchIndex(content, -1)
 			if len(apos) > 0 {
@@ -313,7 +320,7 @@ func checkBackScript(table, code, name, version, infoid, script string, alone bo
 		doc = extract.ExtRegPre(doc, j, v, e.TaskInfo)
 	}
 	//抽取规则
-	if j.CategorySecond==""{
+	if j.CategorySecond == "" {
 		for _, vc1 := range e.RuleCores[j.Category] {
 			for _, vc := range vc1 {
 				tmp := ju.DeepCopy(doc).(map[string]interface{})
@@ -331,7 +338,7 @@ func checkBackScript(table, code, name, version, infoid, script string, alone bo
 				}
 			}
 		}
-	}else{
+	} else {
 		for _, vc1 := range e.RuleCores[j.Category+"_"+j.CategorySecond] {
 			for _, vc := range vc1 {
 				tmp := ju.DeepCopy(doc).(map[string]interface{})

+ 27 - 3
src/jy/clear/totimestamp.go

@@ -4,11 +4,12 @@ package clear
 import (
 	"fmt"
 	"regexp"
+	"strconv"
 	"strings"
 	"time"
 )
 
-var reg, regA, regB, regC, regAfter *regexp.Regexp
+var reg, regA, regB, regC, regD, regAfter *regexp.Regexp
 
 const (
 	T = 365 * 86400
@@ -22,10 +23,12 @@ var item = map[string]string{
 }
 
 func init() {
+	//二〇一五年十一月四日十五时
 	reg, _ = regexp.Compile(`\d+`)
 	regA, _ = regexp.Compile(`[一|二|三|四|五|六|七|八|九|十|零|〇|1|2|3|4|5|6|7|8|9|0]`)
 	regB, _ = regexp.Compile(`\d+年\d+月\d+日((上|下)午)?\s*\d+[::时]\d+分?[-—]\d+[::时]\d+时?分?`)
 	regC, _ = regexp.Compile(`\s*\d+[::时]\d+分?[-—]`)
+	regD, _ = regexp.Compile(`([一|二|三|四|五|六|七|八|九|十|零|〇]{4})年([一|二|三|四|五|六|七|八|九|十]{1,2})月([一|二|三|四|五|六|七|八|九|十]{1,3})日([一|二|三|四|五|六|七|八|九|十]{1,3})时`)
 	regAfter, _ = regexp.Compile(`(下午D?\d{1,2}[时|:|:|h|H])`)
 }
 
@@ -41,6 +44,27 @@ func init() {
 */
 func ObjToTimestamp(data []interface{}) []interface{} {
 	tmp := fmt.Sprint(data[0])
+	//处理类似:二〇一五年十一月四日十五时
+	cht := regD.FindStringSubmatch(tmp)
+	if len(cht) == 5 {
+		y := chineseToNumber(cht[1])
+		m := 0
+		for _, v := range []rune(cht[2]) {
+			it, _ := strconv.Atoi(item[string(v)])
+			m += it
+		}
+		d := 0
+		for _, v := range []rune(cht[3]) {
+			it, _ := strconv.Atoi(item[string(v)])
+			d += it
+		}
+		M := 0
+		for _, v := range []rune(cht[4]) {
+			it, _ := strconv.Atoi(item[string(v)])
+			M += it
+		}
+		tmp = fmt.Sprintf("%s年%d月%d日%d时", y, m, d, M)
+	}
 	//2016年12月7日上午9:00-11:30时 时间范围处理 取后面的时间
 	if regB.MatchString(tmp) {
 		tmp = regC.ReplaceAllString(tmp, "")
@@ -97,8 +121,8 @@ func ObjToTimestamp(data []interface{}) []interface{} {
 		t, _ := time.ParseInLocation("2006-01-02 15:04", timestr, time.Local)
 		timestamp = t.Unix()
 	}
-	if timestamp < 0 || timestamp > (time.Now().Unix()+T) {
-		data[0] = 0
+	if timestamp <= 0 || timestamp > (time.Now().Unix()+T) {
+		data[0] = ""
 	} else {
 		if addreptime > 0 {
 			timestamp += addreptime

+ 1 - 0
src/jy/extract/exportask.go

@@ -57,6 +57,7 @@ func extractAndExport(v string, t map[string]interface{}) {
 	e.InitTag()
 	e.InitClearFn()
 	e.InfoTypeList()
+	e.InitBlockRule()
 	//品牌抽取是否开启
 	ju.IsBrandGoods = ju.Config["brandgoods"].(bool)
 

+ 2 - 3
src/jy/extract/extract.go

@@ -46,6 +46,7 @@ func StartExtractTestTask(taskId, startId, num, resultcoll, trackcoll string) bo
 	ext.InitRuleCore()
 	ext.InitPkgCore()
 	ext.InitBlockRule()
+	ext.InfoTypeList()
 	ext.InitTag()
 	ext.InitClearFn()
 	if ext.IsExtractCity { //版本上控制是否开始城市抽取
@@ -118,6 +119,7 @@ func StartExtractTaskId(taskId string) bool {
 	ext.InitRuleCore()
 	ext.InitPkgCore()
 	ext.InitBlockRule()
+	ext.InfoTypeList()
 	ext.InitTag()
 	ext.InitClearFn()
 	if ext.IsExtractCity { //版本上控制是否开始城市抽取
@@ -374,9 +376,6 @@ func (e *ExtractTask) ExtractDetail(j *ju.Job) {
 				}
 			}
 		} else {
-			fmt.Println(e.RuleCores)
-			fmt.Println("++++++++++++++++")
-			fmt.Println(e.RuleCores[j.Category+"_"+j.CategorySecond])
 			for _, vc1 := range e.RuleCores[j.Category+"_"+j.CategorySecond] {
 				for _, vc := range vc1 {
 					tmp := ju.DeepCopy(doc).(map[string]interface{})

+ 12 - 0
src/jy/extract/extractInit.go

@@ -214,6 +214,8 @@ func (e *ExtractTask) InitRulePres() {
 				tmp := strings.Split(rinfo.RuleText, "__")
 				var pattern string
 				if strings.Contains(tmp[0], "\\u") {
+					tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+					tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 					pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 				} else {
 					pattern = tmp[0]
@@ -251,6 +253,8 @@ func (e *ExtractTask) InitRuleBacks() {
 				tmp := strings.Split(rinfo.RuleText, "__")
 				var pattern string
 				if strings.Contains(tmp[0], "\\u") {
+					tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+					tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 					pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 				} else {
 					pattern = tmp[0]
@@ -335,6 +339,8 @@ func (e *ExtractTask) InfoRole(vinfo map[string]interface{}) []*RuleCore {
 					tmp := strings.Split(rinfo.RuleText, "__")
 					var pattern string
 					if strings.Contains(tmp[0], "\\u") {
+							tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+							tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 						pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 					} else {
 						pattern = tmp[0]
@@ -371,6 +377,8 @@ func (e *ExtractTask) InfoRole(vinfo map[string]interface{}) []*RuleCore {
 					tmp := strings.Split(rinfo.RuleText, "__")
 					var pattern string
 					if strings.Contains(tmp[0], "\\u") {
+							tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+							tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 						pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 					} else {
 						pattern = tmp[0]
@@ -414,6 +422,8 @@ func (e *ExtractTask) InfoRole(vinfo map[string]interface{}) []*RuleCore {
 					tmp := strings.Split(rinfo.RuleText, "__")
 					var pattern string
 					if strings.Contains(tmp[0], "\\u") {
+							tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+							tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 						pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 					} else {
 						pattern = tmp[0]
@@ -485,6 +495,8 @@ func (e *ExtractTask) InitPkgCore() {
 						tmp := strings.Split(rinfo.RuleText, "__")
 						var pattern string
 						if strings.Contains(tmp[0], "\\u") {
+							tmp[0] = strings.Replace(tmp[0], "\\", "\\\\", -1)
+							tmp[0] = strings.Replace(tmp[0], "\\\\u", "\\u", -1)
 							pattern, _ = strconv.Unquote(`"` + tmp[0] + `"`)
 						} else {
 							pattern = tmp[0]

+ 9 - 5
src/jy/extract/score.go

@@ -17,7 +17,7 @@ func init() {
 	qu.ReadConfig("./res/fieldscore.json", &SoreConfig)
 	//实例化正则
 	for _, tmp := range SoreConfig {
-		log.Println(tmp)
+		//log.Println(tmp)
 		if tmp["type"] == "string" {
 			if positions, ok := tmp["position"].([]interface{}); ok {
 				for _, position := range positions {
@@ -25,8 +25,10 @@ func init() {
 						qu.Try(func() {
 							strReq, _ := p["regstr"].(string)
 							if strings.Contains(strReq, "\\u") {
-								pattern, _ := strconv.Unquote(`"` + strReq + `"`)
-								p["regexp"] = regexp.MustCompile(pattern)
+								strReq = strings.Replace(strReq, "\\", "\\\\", -1)
+								strReq = strings.Replace(strReq, "\\\\u", "\\u", -1)
+								strReq, _ = strconv.Unquote(`"` + strReq + `"`)
+								p["regexp"] = regexp.MustCompile(strReq)
 							} else {
 								p["regexp"] = regexp.MustCompile(strReq)
 							}
@@ -42,8 +44,10 @@ func init() {
 						qu.Try(func() {
 							strReq, _ := p["regstr"].(string)
 							if strings.Contains(strReq, "\\u") {
-								pattern, _ := strconv.Unquote(`"` + strReq + `"`)
-								p["regexp"] = regexp.MustCompile(pattern)
+								strReq = strings.Replace(strReq, "\\", "\\\\", -1)
+								strReq = strings.Replace(strReq, "\\\\u", "\\u", -1)
+								strReq, _ = strconv.Unquote(`"` + strReq + `"`)
+								p["regexp"] = regexp.MustCompile(strReq)
 							} else {
 								p["regexp"] = regexp.MustCompile(strReq)
 							}

+ 17 - 7
src/jy/pretreated/analystep.go

@@ -18,7 +18,7 @@ func AnalyStart(job *util.Job) {
 	//格式化正文
 	con = formatText(con, "all")
 	job.Content = con
-	//
+	//计算表格占比,返回表格数组、占比
 	tabs, ration := ComputeConRatio(con, 1)
 	if len(tabs) > 0 {
 		newcon, newtabs, newration := FindBigText(con, ration, tabs)
@@ -28,10 +28,10 @@ func AnalyStart(job *util.Job) {
 			ration = newration
 		}
 	}
-	blockArrays, _ := DivideBlock(con, 1, job.RuleBlock)
-	if len(blockArrays) > 0 { //有分块
+	blockArrays, _ := DivideBlock(con, 1, job.RuleBlock) //分块
+	if len(blockArrays) > 0 {                            //有分块
 		//从块里面找分包
-		job.BlockPackage = FindPackageFromBlocks(&blockArrays, job.Title)
+		job.BlockPackage = FindPackageFromBlocks(&blockArrays, job.Title) //从块里面找分包
 		for _, bl := range blockArrays {
 			if len([]rune(bl.Text)) > 80 {
 				bl.Block, _ = DivideBlock(bl.Text, 1, job.RuleBlock)
@@ -39,9 +39,9 @@ func AnalyStart(job *util.Job) {
 			//块中再查找表格(块,处理完把值赋到块)
 			t1, _ := ComputeConRatio(bl.Text, 2)
 			if len(t1) > 0 {
-				job.HasTable = 1 //添加标识:文本中有table
-				tabres := AnalyTableV2(t1, job.Category, bl.Title, bl.Text, 2, job.SourceMid, job.RuleBlock)
-				processTableResult(tabres, bl, job)
+				job.HasTable = 1                                                                             //添加标识:文本中有table
+				tabres := AnalyTableV2(t1, job.Category, bl.Title, bl.Text, 2, job.SourceMid, job.RuleBlock) //解析表格入口 返回:汇总表格对象
+				processTableResult(tabres, bl, job)                                                          //分析table解析结果
 				if bl.Title == "" && tabres.BlockTag != "" {
 					bl.Title = tabres.BlockTag
 				}
@@ -50,6 +50,11 @@ func AnalyStart(job *util.Job) {
 				//				}
 			}
 			job.Block = append(job.Block, bl)
+
+			if job.Winnerorder == nil || len(job.Winnerorder) == 0 {
+				//新加table未找到winnerorder, 从分块文本中找中标候选人
+				job.Winnerorder = winnerOrderEntity.Find(bl.Text, true, 1)
+			}
 		}
 	} else { //未分块,创建分块
 		bl := &util.Block{}
@@ -67,6 +72,11 @@ func AnalyStart(job *util.Job) {
 			//从正文里面找分包
 			job.BlockPackage = FindPackageFromText(job.Title, newCon)
 		}
+		//新加 未分块table中未能解析到中标候选人,从正文中解析
+		if job.Winnerorder == nil || len(job.Winnerorder) == 0 {
+			bl.Winnerorder = winnerOrderEntity.Find(bl.Text, true, 1)
+		}
+
 		//调用kv解析
 		bl.ColonKV = GetKVAll(newCon, "", nil, 1)
 		bl.SpaceKV = SspacekvEntity.Entrance(newCon, "", nil)

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 491 - 353
src/jy/pretreated/analytable.go


+ 2 - 2
src/jy/pretreated/colonkv.go

@@ -18,7 +18,7 @@ var (
 	regReplKV2    = regexp.MustCompile("(.+?[\u4e00-\u9fa5))][\\s\u3000\u2003\u00a0]*[::].*[((]?[^\r\n\\s\u3000\u2003\u00a0标段包]+?[))]?)([一二三四五六七八九十]+[、..][^一二三四五六七八九十]+?)")
 	regKV         = regexp.MustCompile("([\\p{Han}][^,,。、.;;\r\n]{1,30}?)[::](.*)")
 	filterK       = regexp.MustCompile("[((\\[【].*?[))\\]】]|<[^>].+?>|[①②③¥·;;‘“'’”,*<>((\\[【、))/\\]】??,。.\".\\s\u3000\u2003\u00a0]+|^[一二三四五六七八九十0-91234567890]+")
-	filterValue   = regexp.MustCompile("^(无)$")
+	filterValue   = regexp.MustCompile("(^(无)$|.+%.*|[\r\n\\s\u3000\u2003\u00a0]+|^<.*>)")
 	regReplKey    = regexp.MustCompile("^(包(.+[A-Za-z\\d])?|本项目|推荐|的|本次)|([约为元万亿]+|[大小]写|人民币|[全名]称|姓名)$")
 	BlockTagMap   = map[string]bool{
 		"招标范围": true,
@@ -87,7 +87,7 @@ func (ce *ColonkvEntity) GetKvs(con, title string, from int) []*Kv {
 
 //处理正文
 func (ce *ColonkvEntity) processText(con string) string {
-	con = ce.divisionMoreKV(con)
+	con = ce.divisionMoreKV(con)//一行多个冒号kv处理
 	for {
 		tmp := con
 		con = ce.divisionMoreKV(con)

+ 15 - 4
src/jy/pretreated/division.go

@@ -19,7 +19,7 @@ var (
 		"(\\d+)[\u3000\u2003\u00a0\\s]+([^\\d][^\r\n]+)",
 		"1[..](\\d+)[\u3000\u2003\u00a0\\s]+([^\\d..][^\r\n]+)",
 	}*/
-	/*regSerialTitles_1 = []*regexp.Regexp{
+	regSerialTitles_1 = []*regexp.Regexp{
 		regexp.MustCompile("([\r\n][\u3000\u2003\u00a0\\s]*|^[\u3000\u2003\u00a0\\s]*)([一二三四五六七八九十]+)[\u3000\u2003\u00a0\\s]*[、..::,](.*)"),
 		regexp.MustCompile("([\r\n][\u3000\u2003\u00a0\\s]*|^[\u3000\u2003\u00a0\\s]*)[((]([一二三四五六七八九十]+)[))][\u3000\u2003\u00a0\\s]*[、..::]?(.*)"),
 		regexp.MustCompile("([\r\n][\u3000\u2003\u00a0\\s]*|^[\u3000\u2003\u00a0\\s]*)(\\d+)[\u3000\u2003\u00a0\\s]*、(.*)"),
@@ -36,7 +36,7 @@ var (
 		regexp.MustCompile("^(\\d+)[\u3000\u2003\u00a0\\s]+([^\\d][^\r\n]+)$"),
 		regexp.MustCompile("^1[..](\\d+)[\u3000\u2003\u00a0\\s]+([^\\d..][^\r\n]+)$"),
 		regexp.MustCompile("^[(](\\d+)[\u3000\u2003\u00a0\\s)]+([^\r\n]+)$"),
-	}*/
+	}
 	regReplAllTd       = regexp.MustCompile("(?smi)<td.*?>.+?</td>")
 	regIsNumber        = regexp.MustCompile("^\\d+$")
 	regIsChineseNumber = regexp.MustCompile("^[一二三四五六七八九十]+$")
@@ -79,7 +79,13 @@ func DivideBlock(content string, from int, ruleBlock *util.RuleBlock) ([]*util.B
 	//contentTemp := regReplAllTd.ReplaceAllString(content, "")
 	contentTemp := TextAfterRemoveTable(content)
 	tdIndexs := regReplAllTd.FindAllStringSubmatchIndex(content, -1)
-	regContenSerialTitle, regSerialTitleIndex := getSerialType(contentTemp, ruleBlock.BlockRegs)
+	var regContenSerialTitle *regexp.Regexp
+	var regSerialTitleIndex int
+	if ruleBlock!=nil && len(ruleBlock.BlockRegs)>0{
+		regContenSerialTitle, regSerialTitleIndex = getSerialType(contentTemp, ruleBlock.BlockRegs)
+	}else {
+		regContenSerialTitle, regSerialTitleIndex = getSerialType(contentTemp,  regSerialTitles_1)
+	}
 	//没有分块
 	if regSerialTitleIndex == -1 {
 		if len(contentTemp) == len(content) {
@@ -90,7 +96,12 @@ func DivideBlock(content string, from int, ruleBlock *util.RuleBlock) ([]*util.B
 		}
 	}
 	//匹配序号和标题
-	regSerialTitle := ruleBlock.TitleRegs[regSerialTitleIndex]
+	var regSerialTitle *regexp.Regexp
+	if ruleBlock != nil && len(ruleBlock.TitleRegs)>0{
+		regSerialTitle = ruleBlock.TitleRegs[regSerialTitleIndex]
+	}else {
+		regSerialTitle = regSerialTitles_2[regSerialTitleIndex]
+	}
 	indexs := regContenSerialTitle.FindAllStringIndex(content, -1)
 	indexs = filterSerial(content, indexs, tdIndexs)
 	//头块

+ 112 - 82
src/jy/pretreated/tablev2.go

@@ -64,24 +64,24 @@ type TD struct {
 	Val            string             //值
 	Text           string             //原始串
 	SortKV         *SortMap           //存放kv值
-	Html           string
-	BH             bool         //是否是表头
-	MustBH         bool         //不能修改的表头
-	StandardKey    string       //标准表头
-	Colspan        int          //合并列
-	Rowspan        int          //合并行
-	StartCol       int          //起始列
-	EndCol         int          //终止列
-	StartRow       int          //起始行
-	EndRow         int          //终止行
-	ColPos         int          //当前在TR中的位置
-	HeadTd         *TD          //(是val元素)k节点
-	KVDirect       int          //键-值方向,0未知,1横 2纵//指值和k的方向
-	KeyDirect      int          //k方向,k纵值横,k横值纵 1横 2纵
-	SonTds         []*TD        //(是key元素)值节点数组
-	SonTableResult *TableResult //子值表格集
-	ArrVal         []string     //数组值,当是左临元素是合并行的元素时!
-	Valtype        string       //"BO=中标人顺序"
+	Html           string             //html值
+	BH             bool               //是否是表头
+	MustBH         bool               //不能修改的表头
+	StandardKey    string             //标准表头
+	Colspan        int                //合并列
+	Rowspan        int                //合并行
+	StartCol       int                //起始列
+	EndCol         int                //终止列
+	StartRow       int                //起始行
+	EndRow         int                //终止行
+	ColPos         int                //当前在TR中的位置
+	HeadTd         *TD                //(是val元素)k节点
+	KVDirect       int                //键-值方向,0未知,1横 2纵//指值和k的方向
+	KeyDirect      int                //k方向,k纵值横,k横值纵 1横 2纵
+	SonTds         []*TD              //(是key元素)值节点数组
+	SonTableResult *TableResult       //子值表格集
+	ArrVal         []string           //数组值,当是左临元素是合并行的元素时!
+	Valtype        string             //"BO=中标人顺序"
 }
 
 var submatchreg = regexp.MustCompile(`((?:[一二三四五六七八九十0-10]+[、])([\\S]{4,12})|([\\S]{2,12}))[::]([\\S]{5,60})([一二三四五六七八九]+[、])?`)
@@ -112,43 +112,68 @@ func NewTD(Goquery *goquery.Selection, tr *TR, table *Table) *TD {
 	if rowspan == 0 {
 		rowspan = 1
 	}
-	td.Colspan, td.Rowspan = colspan, rowspan
-	td.Html, _ = td.Goquery.Html()
-	ht := td.Goquery.ChildrenFiltered("table")
-	bsontable := false
+	td.Colspan, td.Rowspan = colspan, rowspan  //合并列,合并行
+	td.Html, _ = td.Goquery.Html()             //html值
+	ht := td.Goquery.ChildrenFiltered("table") //获取td的table
+	bsontable := false                         //默认td中没有table
 	txt := ""
+	//子table处理合并
 	if ht.Size() > 0 {
 		//qutil.Debug("有子表格")
 		txt = TextAfterRemoveTable(td.Html)
-		ts := td.TR.Table.TableResult
-		tabs, _ := ComputeConRatio(td.Html, 2)
-		if len(tabs) > 0 {
-			bsontable = true
-			stag := ts.BlockTag
-			if stag == "" {
-				var tdleft *TD
-				if len(tr.TDs) > 0 {
-					tdleft = tr.TDs[len(tr.TDs)-1]
-					if tdleft.BH {
-						//u.Debug(tdleft.Val),如果不存在就是上一行的
-						stag = tdleft.Val
-					}
-				} else if len(tr.Table.TRs) > 0 {
-					lasttr := tr.Table.TRs[len(tr.Table.TRs)-1]
-					str := ""
-					for _, td3 := range lasttr.TDs {
-						str += td3.Val
-						if len([]rune(str)) > 14 {
-							str = ""
-							break
-						}
+		td.tdHasTable(&bsontable, tr, table) //处理td中的table,块标签处理,子表解析集处理
+	} else {
+		txt = strings.TrimSpace(td.Goquery.Text())
+	}
+	text := dwReg.ReplaceAllString(u.TrimLRAll(txt, ""), "$1")
+	td.Val = text //值
+	td.Text = txt //原始串
+	//对td单元格值判断是否是表头和根据td内容长度进行分块处理
+	td.tdIsHb(tr, table, bsontable)
+	bhead := false
+	if td.TR.RowPos == 0 { //第一行
+		if td.Goquery.Closest("thead").Size() == 1 && !bsontable { //如果是thead确定为k值表头
+			bhead = true
+		}
+	}
+	if bhead && !bsontable {
+		td.BH = true
+		td.KeyDirect = 1 //k方向,k纵值横,k横值纵 1横 2纵
+		td.KVDirect = 2  //键-值方向,0未知,1横 2纵//指值和k的方向
+	}
+	//u.Debug(td.BH, td.Val)
+	return td
+}
+
+//处理td中的table,块标签处理,子表解析集处理
+func (td *TD) tdHasTable(bsontable *bool, tr *TR, table *Table) {
+	ts := td.TR.Table.TableResult
+	tabs, _ := ComputeConRatio(td.Html, 2) //计算表格占比
+	if len(tabs) > 0 {
+		(*bsontable) = true
+		stag := ts.BlockTag //块标签
+		if stag == "" {
+			var tdleft *TD
+			if len(tr.TDs) > 0 {
+				tdleft = tr.TDs[len(tr.TDs)-1]
+				if tdleft.BH {
+					//u.Debug(tdleft.Val),如果不存在就是上一行的
+					stag = tdleft.Val
+				}
+			} else if len(tr.Table.TRs) > 0 {
+				lasttr := tr.Table.TRs[len(tr.Table.TRs)-1]
+				str := ""
+				for _, td3 := range lasttr.TDs {
+					str += td3.Val
+					if len([]rune(str)) > 14 {
+						str = ""
+						break
 					}
-					stag = str
 				}
+				stag = str
 			}
-			sonts := AnalyTableV2(tabs, ts.Toptype, stag, td.Html, 2, ts.Id, table.TableResult.RuleBlock)
+			sonts := AnalyTableV2(tabs, ts.Toptype, stag, td.Html, 2, ts.Id, table.TableResult.RuleBlock) //又一次调用解析表格入口
 			td.BH = false
-
 			td.SonTableResult = sonts
 			//for _, k := range sonts.SortKV.Keys {
 			//u.Debug(k, sonts.SortKV.Map[k])
@@ -200,28 +225,26 @@ func NewTD(Goquery *goquery.Selection, tr *TR, table *Table) *TD {
 				//u.Debug(fmt.Sprintf("%v", td.TR.Table.BlockPackage.Map["1"]))
 			}
 		}
-	} else {
-		txt = td.Goquery.Text()
 	}
-	text := dwReg.ReplaceAllString(u.TrimLRAll(txt, ""), "$1")
-	//u.Debug(txt, text)
-	td.Val = text
-	td.Text = txt
-	//对td单元格值判断是否是key
-	lentxt := len([]rune(text))
+}
+
+//对td单元格值判断是否是表头和根据td内容长度进行分块处理
+func (td *TD) tdIsHb(tr *TR, table *Table, bsontable bool) {
+	lenval := len([]rune(td.Val)) //经过处理的td内容长度
 	//if lentxt > 9 {
 	//td.KV = GetKVAll(txt, "")
 	ub := []*u.Block{}
-	if lentxt > 50 { //看是否划块
+	//经过处理的td内容长度大于50,划块,分包
+	if lenval > 50 { //看是否划块
 		//u.Debug(txt)
-		ub, _ = DivideBlock(txt, 2, table.TableResult.RuleBlock)
+		ub, _ = DivideBlock(td.Text, 2, table.TableResult.RuleBlock) //对td的原始值
+		//看是否划块
 		if len(ub) > 0 {
 			colonKvWeight := map[string]int{}
 			spaceKvWeight := map[string]int{}
 			for _, bl := range ub {
 				//冒号kv
 				for bl_ck, bl_cv := range bl.ColonKV.Kv {
-					//u.Debug(bl_ck, bl_cv)
 					if td.SortKV.Map[bl_ck] == nil || bl.ColonKV.KvTag[bl_ck].Weight >= colonKvWeight[bl_ck] {
 						colonKvWeight[bl_ck] = bl.ColonKV.KvTag[bl_ck].Weight
 						td.SortKV.AddKey(bl_ck, bl_cv)
@@ -249,15 +272,15 @@ func NewTD(Goquery *goquery.Selection, tr *TR, table *Table) *TD {
 		}*/
 		if len(tr.TDs) > 0 {
 			tdleft := tr.TDs[len(tr.TDs)-1]
-			if tdleft.BH && excludeKey.MatchString(tdleft.Text) {
+			if tdleft.BH && excludeKey.MatchString(tdleft.Text) { //(涉及包号|包件号?|项目标号|规格|型号|招标范围|业绩|废标)|(^编号$)|([^包段标]编号)
 				isFindPkg = false
 			}
 		}
 		if isFindPkg {
 			if len(ub) > 0 {
-				blockPackage = FindPackageFromBlocks(&ub, "")
+				blockPackage = FindPackageFromBlocks(&ub, "") //从块里面找分包
 			} else {
-				blockPackage = FindPackageFromText("", text)
+				blockPackage = FindPackageFromText("", td.Val) //从正文里面找分包
 			}
 		}
 		if len(blockPackage) > 0 {
@@ -287,16 +310,28 @@ func NewTD(Goquery *goquery.Selection, tr *TR, table *Table) *TD {
 			}
 		}
 	}
-	//
-	if lentxt < 50 {
+	//经过处理的td内容长度小于50,冒号kv,td表头
+	if lenval < 50 {
 		//		td.SortKV = FindKv(text, "")
 		kvTitle := ""
 		if len(td.TR.TDs) > 0 {
 			kvTitle = td.TR.TDs[len(td.TR.TDs)-1].Val
 		}
-		_, resm := colonkvEntity.entrance(text, kvTitle, nil, 2)
+		/*
+					预算总价
+			(人民币:元)
+		*/
+		if td.Text != "" && strings.Contains(td.Text, "预算总价") && (strings.Contains(td.Text, "(") || strings.Contains(td.Text, "(")) {
+			tagindex := 0
+			if tagindex = strings.Index(td.Text, "("); tagindex <= 0 {
+				tagindex = strings.Index(td.Text, "(")
+			}
+			td.SortKV.AddKey(strings.TrimSpace(td.Text[:tagindex]), strings.TrimSpace(td.Text[tagindex:])) //存放kv值
+			td.BH = true
+		}
+		_, resm := colonkvEntity.entrance(td.Val, kvTitle, nil, 3) //td冒号kv
 		for k, v := range resm {
-			td.SortKV.AddKey(k, v)
+			td.SortKV.AddKey(k, v) //存放kv值
 		}
 		//u.Debug(td.SortKV.Keys, "-------2--------------------------------")
 		//		td.SortKV = FindKv(text, "") //GetKvFromtxt(text, "")
@@ -308,13 +343,21 @@ func NewTD(Goquery *goquery.Selection, tr *TR, table *Table) *TD {
 				td.BH = true
 			}
 		} else if !bsontable {
-			txt := repSpace.ReplaceAllString(text, "")
+			txt := repSpace.ReplaceAllString(td.Val, "")
 			btw, must, _, _, repl := CheckHeader(txt)
+			if lenval > 15 {
+				btw = false
+			}
+			if strings.Contains(td.Val, "个项目") {
+				must = false
+				btw = false
+			}
 			td.Valtype = repl
 			td.MustBH = must
 			td.BH = btw
 		}
-	} else if len(ub) == 0 { //之前这里没加判断,现在加上判断,造成分块之后的kv被覆盖掉
+	} else if len(ub) == 0 {
+		//之前这里没加判断,现在加上判断,造成分块之后的kv被覆盖掉
 		//u.Debug("----\n\n\n", txt, "\n\n\n----")
 		//u.Debug(GetKVAll(txt, ""))
 		/*
@@ -329,7 +372,7 @@ func NewTD(Goquery *goquery.Selection, tr *TR, table *Table) *TD {
 			}
 		*/
 
-		td.SortKV = FindKv(text, "", 2)
+		td.SortKV = FindKv(td.Val, "", 2)
 
 		//		td.LeftNode.Val
 		//		for _, vvv := range *td.TR {
@@ -339,24 +382,11 @@ func NewTD(Goquery *goquery.Selection, tr *TR, table *Table) *TD {
 		if len(td.TR.TDs) > 0 {
 			kvTitle = td.TR.TDs[len(td.TR.TDs)-1].Val
 		}
-		_, resm := colonkvEntity.entrance(text, kvTitle, nil, 2)
+		_, resm := colonkvEntity.entrance(td.Val, kvTitle, nil, 2) //获取冒号kv入口
 		for k, v := range resm {
 			td.SortKV.AddKey(k, v)
 		}
 	}
-	bhead := false
-	if td.TR.RowPos == 0 { //第一行
-		if td.Goquery.Closest("thead").Size() == 1 && !bsontable { //如果是thead确定为k值表头
-			bhead = true
-		}
-	}
-	if bhead && !bsontable {
-		td.BH = true
-		td.KeyDirect = 1
-		td.KVDirect = 2
-	}
-	//u.Debug(td.BH, td.Val)
-	return td
 }
 func (t *Table) Print() {
 	for row, trs := range t.TRs {

+ 36 - 11
src/jy/pretreated/winnerorder.go

@@ -24,19 +24,25 @@ type WinnerFlag struct {
 var (
 	winnerOrderEntity = &WinnerOrderEntity{}
 	numberReg         = regexp.MustCompile("[一二三四五六七八九十0-9]+")
+	numberReg2        = regexp.MustCompile("[\\d一二三四五六七八九十.,,]+")
 	thisNumberReg     = regexp.MustCompile("第" + numberReg.String())
 	winnerReg1        = regexp.MustCompile("(^|[^为])(【?(推荐)?第[一二三四五六七八九十1-9]+(合格|名|包|标段)?】?((候|侯)选)?(备选|成交|中(标|选))人?([((]成交[))])?((候|侯)选|排序)?(人(单位)?|供应商|单位|机构)(名称)?为?)($|[^,;;。,])")
 	winnerReg2        = regexp.MustCompile("(排名第[一二三四五六七八九十1-9]+|第[一二三四五六七八九十1-9]+(候|侯)选人)")
-	winnerReg3        = regexp.MustCompile("(第[一二三四五六七八九十1-9]+名)")
-	winnerReg4        = regexp.MustCompile("((确认|推荐|评审|排(名|序))[为::]+|(由高到低排序前.名|公示下列内容|(确定|推荐)的?中(标|选)候选人|\n中(标|选)候选.{1,3}\\s*\n|\n(中(标|选)候选.{1,3}[::\u3000\u2003\u00a0\\s]|成交候选供应商)|(排(名|序)|公(示|告)|具体|推荐|结果(公示)?|中(标|选)候选人.{0,2})如下|[一二三四五六七八九十\\d]+、(中(标|选)候选[^\n::]{1,8}|.{0,8}(成交|结果)信息|成交[^\n::]{2,8}))[为::]?)")
-	winnerReg5        = regexp.MustCompile("([^,;;。,、\n]+)(为?第[一二三四五六七八九十1-9]+(成交|中标)?((候|侯)选(人|供应商|单位|机构)|名)|排名第[一二三四五六七八九十1-9]+)([,;;。,、]|\\s+\n)")
-	colonEndReg       = regexp.MustCompile("[::]$")
-	toWarpReg         = regexp.MustCompile("[,。,;;]+")
-	findamountReg     = regexp.MustCompile("[,。,;;\u3000\u2003\u00a0\\s]+")
-	amountReg         = regexp.MustCompile("^\\d+(\\.\\d+)?((百|千)?元|(百|千)?(万|亿)元?)$")
-	companyWarpReg    = regexp.MustCompile("(公司)(.+?[::])")
-	findCompanyReg    = regexp.MustCompile("[^::]+公司")
-	colonSpaceReg     = regexp.MustCompile("[::]\\s+")
+	//winnerReg2     = regexp.MustCompile("(第[一二三四五六七八九十1-9]+(候|侯)选人)")
+	winnerReg3     = regexp.MustCompile("(第[一二三四五六七八九十1-9]+名)")
+	winnerReg4     = regexp.MustCompile("((确认|推荐|评审|排(名|序))[为::]+|(由高到低排序前.名|公示下列内容|(确定|推荐)的?中(标|选)候选人|\n中(标|选)候选.{1,3}\\s*\n|\n(中(标|选)候选.{1,3}[::\u3000\u2003\u00a0\\s]|成交候选供应商)|(排(名|序)|公(示|告)|具体|推荐|结果(公示)?|中(标|选)候选人.{0,2})如下|[一二三四五六七八九十\\d]+、(中(标|选)候选[^\n::]{1,8}|.{0,8}(成交|结果)信息|成交[^\n::]{2,8}))[为::]?)")
+	winnerReg5     = regexp.MustCompile("([^,;;。,、\n]+?)(为?)(第[一二三四五六七八九十1-9]+(成交|中标)?((候|侯)选(人|供应商|单位|机构)|名)|排名第[一二三四五六七八九十1-9]+)([,;;。,、]|\\s+\n)")
+	winnerReg6     = regexp.MustCompile("(^(排名)?第[一二三四五六七八九十1-9]+[名中标成交备选候选人单位供应商]*)")
+	colonEndReg    = regexp.MustCompile("[::]$")
+	toWarpReg      = regexp.MustCompile("[,。,;;]+")
+	findamountReg  = regexp.MustCompile("[,。,;;\u3000\u2003\u00a0\\s]+")
+	amountReg      = regexp.MustCompile("^\\d+(\\.\\d+)?((百|千)?元|(百|千)?(万|亿)元?)$")
+	companyWarpReg = regexp.MustCompile("(公司)(.+?[::])")
+	findCompanyReg = regexp.MustCompile("[^::]+公司")
+	colonSpaceReg  = regexp.MustCompile("[::]\\s+")
+	findCandidate  = regexp.MustCompile("(^.{5,}(公司|集团|单位|机构|企业|厂|场|院|所|店|中心|市|局|站|城|处|行|部|队|联合(会|体))|工作室)")
+	findCandidate2 = regexp.MustCompile("(^.{5,}(公司|集团|单位|机构|企业|厂|场|院|所|店|中心|市|局|站|城|处|行|部|队|联合(会|体)|工作室)$)")
+	clearSpace1    = regexp.MustCompile("([((][\\d一二三四五六七八九十][))][\\s\u3000\u2003\u00a0\\t]*|<[^>].+?>)")
 )
 
 /*
@@ -45,7 +51,17 @@ var (
  *from 来源
  */
 func (wo *WinnerOrderEntity) Find(text string, flag bool, from int) []map[string]interface{} {
-	text = winnerReg5.ReplaceAllString(text, "\n$2:$1\n")
+	text = winnerReg5.ReplaceAllString(text, "\n$3:$1\n")
+	/*
+		"_id" : ObjectId("5c2c6f60a5cb26b9b7b62cd8")
+
+		1 .第一中选候选人:
+		(1)	单位名称:成都维诺信科技有限公司
+		(2)	参选报价:522,00.00元
+		(3)	质量:符合比选文件规定的质量标准
+
+	*/
+	text = clearSpace1.ReplaceAllString(text, "") //清理(1)	单位名称:成都维诺信科技有限公司-->单位名称:成都维诺信科技有限公司
 	if strings.TrimSpace(text) == "" {
 		return []map[string]interface{}{}
 	}
@@ -192,6 +208,13 @@ func (wo *WinnerOrderEntity) findByReg(content string, blocks []string, reg_2 *r
 				winners = append(winners, object)
 				object = map[string]interface{}{}
 			}
+			//新加 从正文抽取时对v校验
+			if from == 1 || from == 3 {
+				v = findCandidate.FindString(v)
+				if v == "" {
+					continue
+				}
+			}
 			val := wo.clear("中标单位", v)
 			if val != nil {
 				count++
@@ -236,6 +259,8 @@ func (wo *WinnerOrderEntity) clear(typ, v string) interface{} {
 	if typ == "中标单位" && regDivision.MatchString(v) {
 		v = findCompanyReg.FindString(v)
 	}
+	v = filterValue.ReplaceAllString(v, "")
+	//过滤
 	return v //clear.ClearResult(typ, v)
 }
 

+ 15 - 14
src/jy/util/article.go

@@ -51,20 +51,21 @@ type RuleBlock struct {
 
 //块
 type Block struct {
-	Tags     []Tags          //对块做的标签,可以作为数据抽取的依据
-	Title    string          //块标题
-	Titles   []string        //拆分以后多个块标题
-	Index    int             //块索引
-	Text     string          //块内容
-	Start    int             //开始索引
-	End      int             //结束索引
-	ColonKV  *JobKv          //冒号kv (分出的对应的KV值)
-	TableKV  *JobKv          //table kv (分出的对应的KV值)
-	SpaceKV  *JobKv          //空格 kv (分出的对应的KV值)
-	BPackage *BlockPackage   //分包信息
-	Tag      map[string]bool //块标签
-	Block    []*Block        //子块
-	Category string          //块分类
+	Tags        []Tags                   //对块做的标签,可以作为数据抽取的依据
+	Title       string                   //块标题
+	Titles      []string                 //拆分以后多个块标题
+	Index       int                      //块索引
+	Text        string                   //块内容
+	Start       int                      //开始索引
+	End         int                      //结束索引
+	ColonKV     *JobKv                   //冒号kv (分出的对应的KV值)
+	TableKV     *JobKv                   //table kv (分出的对应的KV值)
+	SpaceKV     *JobKv                   //空格 kv (分出的对应的KV值)
+	BPackage    *BlockPackage            //分包信息
+	Tag         map[string]bool          //块标签
+	Block       []*Block                 //子块
+	Category    string                   //块分类
+	Winnerorder []map[string]interface{} //块中,中标候选人排序
 }
 
 //段落

+ 1 - 1
src/jy/util/config.go

@@ -13,7 +13,7 @@ var FormatTextMap map[string][]map[string]interface{}
 
 func init() {
 	loadFormatText()
-	//LoadTagDb("./res/tagdb")
+	LoadTagDb("./res/tagdb")
 	LoadTagDb("./res/blocktagdb")
 }
 

+ 5 - 5
src/main_test.go

@@ -29,7 +29,7 @@ func Test_han(t *testing.T) {
 func Test_task(t *testing.T) {
 	Mgo = MgoFactory(1, 3, 120, "192.168.3.207:27082", "extract_kf")
 	//extract.StartExtractTaskId("5b8f804025e29a290415aee1")5c528686698414055c47b115
-	extract.StartExtractTestTask("5b8f804025e29a290415aee1", "5a53966e40d2d9bbe8f7d30a", "1", "mxs_v2", "mxs_v2")
+	extract.StartExtractTestTask("5cdd3025698414032c8322b1", "5c2b55f1a5cb26b9b7fac3c3", "1", "mxs_v2", "mxs_v2")
 	//extract.StartExtractTestTask("5c3d75c96984142998eb00e1", "5c2a3d28a5cb26b9b76144dd", "100", "mxs_v3", "mxs_v3")
 	time.Sleep(5 * time.Second)
 }
@@ -40,11 +40,11 @@ func Test_extractcity(t *testing.T) {
 	extract.FindBuyer()
 }
 func Test_reg(t *testing.T) {
-	context := `sfsa.`
-	reg := regexp.MustCompile(`(勘察|设计|设备|项目|标段|工程|监理|范围|分包|月|日|天|[,,\.。、::“”‘’"])`)
-	//reg := regexp.MustCompile(`[\\p{Han}]`)
+	context := `sfsa发斯蒂芬.`
+	//reg := regexp.MustCompile(`(勘察|设计|设备|项目|标段|工程|监理|范围|分包|月|日|天|[,,\.。、::“”‘’"])`)
+	reg := regexp.MustCompile(`[\\p{Han}]`)
 	tmp := reg.MatchString(context)
-	log.Println(tmp)
+	log.Println("--", tmp)
 }
 
 func Test_reg1(t *testing.T) {

+ 1 - 1
src/res/fieldscore.json

@@ -172,7 +172,7 @@
         "position": [
             {
                 "describe": "全为中文汉字或符号",
-                "regstr": "^[\\u4e00-\\u9fa5()()【】\\\\[\\\\],,。、::《》]+$",
+                "regstr": "^[\\u4e00-\\u9fa5()()【】\\[\\],,。、::《》]+$",
                 "score": -20
             },
             {

+ 2 - 2
src/res/tablev1.json

@@ -62,7 +62,7 @@
 		"其他投标人"
 	],
 	"bidorder":[
-		".{0,8}排[序名]$__sort",
-		"(人|供应商|单位)(名称)?$__entname"
+		"(.{0,8}排[序名]$|名次|^序号$)__sort",
+		"([^负责联系需求]+人|供应商|^单位)(名称)?$__entname"
 	]
 }

+ 89 - 2
src/udpfileserver/main.go

@@ -2,6 +2,8 @@ package main
 
 import (
 	"encoding/json"
+	"fmt"
+	"github.com/go-gomail/gomail"
 	"gopkg.in/mgo.v2/bson"
 	"jy/mongodbutil"
 	"log"
@@ -9,8 +11,11 @@ import (
 	"net"
 	"net/rpc"
 	"path"
+	"qfw/common/src/qfw/util"
 	qu "qfw/util"
+	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -61,7 +66,7 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 		lid := strings.TrimSpace(mapInfo["lteid"].(string))
 		if bson.IsObjectIdHex(gid) && bson.IsObjectIdHex(lid) {
 			var jsq int64
-			query := bson.M{"_id": bson.M{"$gte": bson.ObjectIdHex(gid),"$lte": bson.ObjectIdHex(lid),}}
+			query := bson.M{"_id": bson.M{"$gt": bson.ObjectIdHex(gid),"$lte": bson.ObjectIdHex(lid),}}
 			log.Println("query---:", query)
 			sum :=mongodbutil.Mgo.Count(MgoC,query)
 			log.Println("sum:", sum)
@@ -71,7 +76,7 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 				limit = sum
 			}
 			for i := 0; i < pageNum; i++ {
-				query = bson.M{"_id": bson.M{"$gte": bson.ObjectIdHex(gid), "$lte": bson.ObjectIdHex(lid)}}
+				query = bson.M{"_id": bson.M{"$gt": bson.ObjectIdHex(gid), "$lte": bson.ObjectIdHex(lid)}}
 				log.Println("page=", i+1,"query=", query,limit)
 				list, b := mongodbutil.Mgo.Find(MgoC,query,nil,bson.M{"_id": 1,MgoFileFiled:1},false,0, limit)
 				if !b{
@@ -103,6 +108,11 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 										log.Println(mid, "mgo ", MgoFileFiled,"没有fid ")
 										continue
 									}
+									//if qu.ObjToString(fileinfo["update"]) ==""{
+									//	<-ChanB
+									//	log.Println(mid, "mgo ", MgoFileFiled,"没有update ")
+									//	continue
+									//}
 									save(mid,attk, qmap, &fileinfo,&updateNum)
 									<-ChanB
 								}
@@ -111,7 +121,10 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 					}
 				}
 			}
+			//识别完以后再次查询数据库,进行下一轮识别
 			log.Println("处理查询数据结束...",jsq,time.Now().Sub(stime))
+			//进行下一轮识别
+			forfunc(lid)
 		} else {
 			log.Println("开始id或结束id参数错误:", string(data))
 		}
@@ -185,6 +198,7 @@ func save(mid interface{},attk string, qmap, fileinfo *map[string]interface{},up
 			(*fileinfo)["content"] = rdata["context"]
 		}
 		(*fileinfo)["expend"] = rdata["expend"]
+		delete(*fileinfo,"update")
 		//log.Println((*fileinfo))
 
 		(*qmap)[MgoFileFiled].(map[string]interface{})["attachments"].(map[string]interface{})[attk]=*fileinfo
@@ -208,8 +222,81 @@ func save(mid interface{},attk string, qmap, fileinfo *map[string]interface{},up
 		}else {
 			log.Println(mid, "mongo更新数据失败",qu.ObjToString((*fileinfo)["fid"]))
 		}
+		nowHour := time.Now().Hour()
+		rdlock.Lock()
+		if nowHour != hourNum{
+			log.Println("send email:",SendMail(fmt.Sprint(updateBool,mid)))
+			hourNum = nowHour
+		}
+		rdlock.Unlock()
 	} else {
 		log.Println(mid, "调用rpc服务解析异常:",qu.ObjToString((*fileinfo)["fid"]), rdata["err"])
 	}
 
 }
+var hourNum int
+var rdlock sync.RWMutex
+func SendMail( body string ) error {
+	//定义邮箱服务器连接信息,如果是阿里邮箱 pass填密码,qq邮箱填授权码
+	mailConn := map[string]string {
+		"user": "550838476@qq.com",
+		"pass": "",
+		"host": "smtp.qq.com",
+		"port": "465",
+	}
+
+	port, _ := strconv.Atoi(mailConn["port"]) //转换端口类型为int
+
+	m := gomail.NewMessage()
+	m.SetHeader("From","Get to" + "<" + mailConn["user"] + ">")  //这种方式可以添加别名,即“XD Game”, 也可以直接用<code>m.SetHeader("From",mailConn["user"])</code> 读者可以自行实验下效果
+	m.SetHeader("To", []string{"550838476@qq.com"}...)  //发送给多个用户
+	m.SetHeader("Subject", "MongoId")  //设置邮件主题
+	m.SetBody("text/html", body)     //设置邮件正文
+
+	d := gomail.NewDialer(mailConn["host"], port, mailConn["user"], mailConn["pass"])
+
+	err := d.DialAndSend(m)
+	return err
+
+}
+
+func forfunc(lid string) {
+	for {
+		//查询最后一个id
+		lastObjectId, _ := mongodbutil.Mgo.Find(MgoC,nil,"-_id",bson.M{"_id":1},true,-1,-1)
+		lastId,ok := (*lastObjectId)[0]["_id"].(bson.ObjectId)
+		log.Println("lastID:",lastId)
+		//查询最后一个id出错重新查询
+		if!ok{//转换失败
+			log.Println("查询异常",*lastObjectId)
+			time.Sleep(time.Minute)
+			continue
+		}
+		//查询最后一个id等于上一轮的id就重新查询
+		if lastId.Hex() == lid {
+			log.Println("没有新数据",lastId.Hex())
+			SendMail(time.Now().String()+"没有最新数据,当前最后一条数据id:"+lastId.Hex())
+			time.Sleep(time.Hour)
+			continue
+		}
+		//不相等说明有新数据,进行下次处理
+		m := map[string]string{
+			"gtid":lid,//上一轮结束的最后id
+			"lteid":lastId.Hex(),//新一轮查询出来的id
+		}
+		bytes, _ := json.Marshal(m)
+		//发送udp
+		err := udpclient.WriteUdp(bytes,mu.OP_TYPE_DATA,&net.UDPAddr{
+			IP:   net.ParseIP( util.ObjToString(Sysconfig["udpip"])),
+			Port:  util.IntAll(Sysconfig["udpport"]),
+		})
+		if err != nil{
+			log.Println("发送udp失败",err,string(bytes))
+			time.Sleep(time.Minute)
+			continue
+		}
+		SendMail(time.Now().String()+fmt.Sprint("发送udp成功,gtid:",lid,",lteid:",lastId.Hex()))
+		log.Println("发送udp成功,gtid:",lid,",lteid:",lastId.Hex())
+		break//发送完后终止循环
+	}
+}

+ 9 - 5
udpprojectset/src/cleareids.go

@@ -7,7 +7,6 @@ import (
 	"qfw/util"
 	"qfw/util/redis"
 	"sync"
-	"time"
 
 	"github.com/robfig/cron"
 )
@@ -32,14 +31,14 @@ func clearedis() {
 
 func clearPKey() {
 	log.Println("开始清理")
-	nowtime := time.Now().Unix()
+	nowtime := currentMegerTime //time.Now().Unix() int64(1461204000)
 	wg := sync.WaitGroup{}
 	for _, pncb := range []*KeyMap{PNKey, PCKey, PBKey} {
 		wg.Add(1)
-		go func() {
+		go func(pncb *KeyMap) {
 			defer wg.Done()
 			clearPNCBKey(pncb, nowtime)
-		}()
+		}(pncb)
 	}
 	wg.Wait()
 	log.Println("清理结束")
@@ -57,9 +56,13 @@ func clearPNCBKey(pncb *KeyMap, nowtime int64) {
 func clearIdsKeys(pKey *KeyMap, nowtime int64) []string {
 	defer util.Catch()
 	delkey := []string{}
+	pKey.Lock.Lock()
 	for k, ma := range pKey.Map {
 		ids := ma.Arr
 		delids := []interface{}{}
+		if ids == nil {
+			continue
+		}
 		res := redis.Mget(REDISIDS, *ids)
 		for _, b1 := range res {
 			if b1 != nil {
@@ -95,11 +98,12 @@ func clearIdsKeys(pKey *KeyMap, nowtime int64) []string {
 			}
 		}
 	}
+	pKey.Lock.Unlock()
 	return delkey
 }
 
 func deleteSliceId(a []string, id string) *[]string {
-	ret := make([]string, 0, len(a))
+	ret := make([]string, 0)
 	for _, val := range a {
 		if val != id {
 			ret = append(ret, val)

+ 9 - 3
udpprojectset/src/config.json

@@ -6,12 +6,12 @@
         "to": "zhangjinkun@topnet.net.cn",
         "api": "http://10.171.112.160:19281/_send/_mail"
     },
-    "thread": 30,
-    "extractColl": "bidding20190423",
+    "thread": 1,
+    "extractColl": "bidding20190521",
     "projectColl": "projectset",
     "lenprojectname": 18,
     "redisPoolSize": 60,
-    "redisaddrs": "ids=127.0.0.1:6379,keys=127.0.0.1:6379,info=127.0.0.1:6379",
+    "redisaddrs": "ids=192.168.3.18:3379,keys=192.168.3.18:3379,info=192.168.3.18:3379",
     "clearedis": {
         "open": true,
         "clearcron": "0 10 15 ? * 4",
@@ -21,6 +21,12 @@
         "projectlen": 5,
         "projectcodelen": 8
     },
+    "taskstock": {
+        "open": true,
+		"startTime":1325347200,
+        "startdate": "2015-11-01",
+        "endate": "2019-06-30"
+    },
     "udpport": ":1482",
     "nextNode": [
         {

+ 131 - 0
udpprojectset/src/fulldata.go

@@ -0,0 +1,131 @@
+package main
+
+import (
+	"log"
+
+	"qfw/util"
+	"qfw/util/mongodb"
+
+	"qfw/util/redis"
+	"sync"
+	"time"
+)
+
+var FullCount = 0
+
+func RunFullData(startTime int64) {
+	if startTime < 1325347200 {
+		log.Println("时间错误", startTime)
+	}
+	defer util.Catch()
+	var wg = sync.WaitGroup{}
+	//startTime := int64(1325347200) //2012-01-01
+	ps := 3
+	pool := make(chan *task, ps)
+	day := 0
+	endChan := make(chan bool, 1)
+	go func() {
+		now := time.Now().Unix()
+		bComplete := false
+		for {
+			if startTime > now || bComplete {
+				log.Println("任务结束", startTime)
+				endChan <- true
+				break
+			}
+			endTime := startTime + 86400
+			q := map[string]interface{}{
+				"publishtime": map[string]interface{}{
+					"$gt":  startTime,
+					"$lte": endTime,
+				},
+			}
+
+			//数据正序处理
+			sess := MQFW.GetMgoConn()
+			var result []map[string]interface{}
+			sess.DB(MQFW.DbName).C(extractColl).Find(q).All(&result)
+			MQFW.DestoryMongoConn(sess)
+			pool <- &task{result}
+			wg.Add(1)
+			startTime = endTime
+			day++
+			log.Println("day====", day)
+			if day > 0 && day%ps == 0 {
+				wg.Wait()
+				MQFW.Destory()
+				MQFW = mongodb.MongodbSim{
+					MongodbAddr: Sysconfig["mongodbServers"].(string),
+					Size:        2 * ps,
+					DbName:      Sysconfig["mongodbName"].(string),
+				}
+				MQFW.InitPool()
+			}
+
+		}
+	}()
+
+	for {
+		select {
+		case t := <-pool:
+			t.query()
+			t.result = nil
+			t = nil
+			wg.Done()
+		case <-endChan:
+			return
+		}
+	}
+
+}
+
+type task struct {
+	result []map[string]interface{}
+}
+
+func (t *task) query() {
+	index := 0
+	wg := &sync.WaitGroup{}
+	for _, tmp := range t.result {
+		if index%10000 == 0 {
+			log.Println(index, tmp["_id"])
+		}
+		index++
+		if util.IntAll(tmp["repeat"]) == 1 {
+			continue
+		}
+		pt := util.Int64All(tmp["publishtime"])
+		if pt > currentMegerTime {
+			currentMegerTime = pt
+		}
+		currentMegerCount++
+		if currentMegerCount > 300000 {
+			log.Println("执行清理", currentMegerTime)
+			clearPKey()
+			currentMegerCount = 0
+		}
+		wg.Add(1)
+		MultiThread <- true
+		go func(tmp map[string]interface{}) {
+			defer func() {
+				<-MultiThread
+				wg.Done()
+			}()
+			thisid := util.BsonIdToSId(tmp["_id"])
+			info := PreThisInfo(tmp)
+			if info != nil {
+				lockPNCBMap(info)
+				storeLock(info)
+				startProjectMerge(info, tmp)
+				redis.Put(INFOID, thisid, 1, INFOTIMEOUT)
+				currentMegerTime = info.Publishtime
+				unlockPNCBMap(info)
+			}
+		}(tmp)
+	}
+	wg.Wait()
+	FullCount += index
+
+	log.Println("currentFull", FullCount)
+
+}

+ 150 - 18
udpprojectset/src/main.go

@@ -39,6 +39,9 @@ var (
 	//三组lock,对应的(PNKey)key为项目名称,值对应的是此项目名称对应的项目id数组
 	PNKey, PCKey, PBKey          = NewKeyMap(), NewKeyMap(), NewKeyMap()
 	PNKeyMap, PCKeyMap, PBKeyMap = sync.Map{}, sync.Map{}, sync.Map{}
+
+	currentMegerTime  int64 //合并项目的时间位置,用来清理几个月之前的项目
+	currentMegerCount int   //合并项目的计数,用来定时清理
 )
 
 type MegerFields struct {
@@ -143,6 +146,16 @@ func main() {
 	log.Println("load data from redis finished.", n)
 	//清理redis
 	//clearedis()
+
+	if taskstock, ok := Sysconfig["taskstock"].(map[string]interface{}); ok { //跑存量数据
+		if b, _ := taskstock["open"].(bool); b {
+			RunFullData(util.Int64All(taskstock["startTime"]))
+			//			startdate, _ := taskstock["startdate"].(string)
+			//			endate, _ := taskstock["endate"].(string)
+			//			taskStock(startdate, endate)
+		}
+
+	}
 	updport := Sysconfig["udpport"].(string)
 	udpclient = mu.UdpClient{Local: updport, BufSize: 1024}
 	udpclient.Listen(processUdpMsg)
@@ -165,7 +178,7 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 			}
 			go udpclient.WriteUdp([]byte(key), mu.OP_NOOP, ra)
 			SingleThread <- true
-			go task(data, mapInfo)
+			go taskInc(mapInfo)
 		}
 	case mu.OP_NOOP: //下个节点回应
 		ok := string(data)
@@ -176,7 +189,7 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 	}
 }
 
-func task(data []byte, mapInfo map[string]interface{}) {
+func taskInc(mapInfo map[string]interface{}) {
 	defer func() {
 		<-SingleThread
 	}()
@@ -193,11 +206,11 @@ func task(data []byte, mapInfo map[string]interface{}) {
 	sess := MQFW.GetMgoConn()
 	defer MQFW.DestoryMongoConn(sess)
 	//数据正序处理
-	it := sess.DB(MQFW.DbName).C(extractColl).Find(&q).Iter() //.Sort("publishtime")
+	it := sess.DB(MQFW.DbName).C(extractColl).Find(map[string]interface{}{}).Sort("publishtime").Iter()
 	count, index := 0, 0
 	pici := time.Now().Unix()
 	wg := &sync.WaitGroup{}
-	idmap := &sync.Map{}
+	//idmap := &sync.Map{}
 	for tmp := make(map[string]interface{}); it.Next(tmp); {
 		if index%10000 == 0 {
 			log.Println(index, tmp["_id"])
@@ -207,7 +220,17 @@ func task(data []byte, mapInfo map[string]interface{}) {
 			tmp = make(map[string]interface{})
 			continue
 		}
+		pt := util.Int64All(tmp["publishtime"])
+		if pt > currentMegerTime {
+			currentMegerTime = pt
+		}
 		count++
+
+		currentMegerCount++
+		if currentMegerCount > 300000 {
+			time.Sleep(100 * time.Millisecond)
+			clearPKey()
+		}
 		thisid := util.BsonIdToSId(tmp["_id"])
 		b, err := redis.Exists(INFOID, thisid)
 		if err != nil {
@@ -215,19 +238,21 @@ func task(data []byte, mapInfo map[string]interface{}) {
 		}
 		if !b {
 			wg.Add(1)
-			idmap.Store(tmp["_id"], true) //增加判重逻辑,重复id不再生成
+			//idmap.Store(tmp["_id"], true) //增加判重逻辑,重复id不再生成
 			MultiThread <- true
 			go func(tmp map[string]interface{}, thisid string) {
 				defer func() {
 					<-MultiThread
 					wg.Done()
-					idmap.Delete(tmp["_id"])
+					//idmap.Delete(tmp["_id"])
 				}()
 				info := PreThisInfo(tmp)
 				if info != nil {
 					lockPNCBMap(info)
+					storeLock(info)
 					startProjectMerge(info, tmp)
 					redis.Put(INFOID, thisid, 1, INFOTIMEOUT)
+					currentMegerTime = info.Publishtime
 					unlockPNCBMap(info)
 				}
 			}(tmp, thisid)
@@ -237,18 +262,18 @@ func task(data []byte, mapInfo map[string]interface{}) {
 		}
 		tmp = make(map[string]interface{})
 	}
-	for {
-		time.Sleep(5 * time.Second)
-		n := 0
-		idmap.Range(func(key interface{}, v interface{}) bool {
-			n++
-			log.Println(key, v)
-			return true
-		})
-		if n < 1 {
-			break
-		}
-	}
+	//	for {
+	//		time.Sleep(5 * time.Second)
+	//		n := 0
+	//		idmap.Range(func(key interface{}, v interface{}) bool {
+	//			n++
+	//			log.Println(key, v)
+	//			return true
+	//		})
+	//		if n < 1 {
+	//			break
+	//		}
+	//	}
 	wg.Wait()
 	log.Println("task over...", index, count)
 	//发送udp,调用生成项目索引
@@ -268,6 +293,113 @@ func task(data []byte, mapInfo map[string]interface{}) {
 	}
 }
 
+func taskStock(startDate, endDate string) {
+	defer func() {
+		<-SingleThread
+	}()
+	defer util.Catch()
+	publishtimes := []map[string]interface{}{}
+	start, _ := time.ParseInLocation(util.Date_Short_Layout, startDate, time.Local)
+	end, _ := time.ParseInLocation(util.Date_Short_Layout, endDate, time.Local)
+	for {
+		publishtime := map[string]interface{}{
+			"date":  start.Format(util.Date_Short_Layout),
+			"stime": start.Unix(),
+			"etime": start.Add(24 * time.Hour).Unix(),
+		}
+		publishtimes = append(publishtimes, publishtime)
+		start = start.Add(24 * time.Hour)
+		if start.Unix() > end.Unix() {
+			break
+		}
+	}
+	sess := MQFW.GetMgoConn()
+	defer MQFW.DestoryMongoConn(sess)
+	wg := &sync.WaitGroup{}
+	idmap := &sync.Map{}
+	count, index := 0, 0
+	for _, v := range publishtimes {
+		q := map[string]interface{}{
+			"publishtime": map[string]interface{}{
+				"$gt":  util.Int64All(v["stime"]),
+				"$lte": util.Int64All(v["etime"]),
+			},
+		}
+		log.Println(q)
+		//数据正序处理
+		it := sess.DB(MQFW.DbName).C(extractColl).Find(&q).Sort("publishtime").Iter()
+		datenum := 0
+		for tmp := make(map[string]interface{}); it.Next(tmp); {
+			if index%10000 == 0 {
+				log.Println(index, tmp["_id"])
+			}
+			index++
+			datenum++
+			if util.IntAll(tmp["repeat"]) == 1 {
+				tmp = make(map[string]interface{})
+				continue
+			}
+			pt := util.Int64All(tmp["publishtime"])
+			if pt > currentMegerTime {
+				currentMegerTime = pt
+			}
+			count++
+			currentMegerCount++
+			if currentMegerCount > 300000 {
+				log.Println("执行清理", currentMegerTime)
+				time.Sleep(1 * time.Second)
+				clearPKey()
+				currentMegerCount = 0
+			}
+			thisid := util.BsonIdToSId(tmp["_id"])
+			b, err := redis.Exists(INFOID, thisid)
+			if err != nil {
+				log.Println("checkid err", err.Error())
+			}
+			if !b {
+				wg.Add(1)
+				idmap.Store(tmp["_id"], true) //增加判重逻辑,重复id不再生成
+				MultiThread <- true
+				go func(tmp map[string]interface{}, thisid string) {
+					defer func() {
+						<-MultiThread
+						wg.Done()
+						idmap.Delete(tmp["_id"])
+					}()
+					info := PreThisInfo(tmp)
+					if info != nil {
+						lockPNCBMap(info)
+						storeLock(info)
+						startProjectMerge(info, tmp)
+						redis.Put(INFOID, thisid, 1, INFOTIMEOUT)
+						currentMegerTime = info.Publishtime
+						unlockPNCBMap(info)
+					}
+				}(tmp, thisid)
+			}
+			if count%1000 == 0 {
+				log.Println("count:", count)
+			}
+			tmp = make(map[string]interface{})
+		}
+		log.Println(v["date"], datenum)
+	}
+	for {
+		time.Sleep(5 * time.Second)
+		n := 0
+		idmap.Range(func(key interface{}, v interface{}) bool {
+			n++
+			log.Println(key, v)
+			return true
+		})
+		if n < 1 {
+			break
+		}
+	}
+	wg.Wait()
+	log.Println("taskStock over...", index, count)
+}
+
 func NewPushInfo(tmp map[string]interface{}) bson.M {
 	return bson.M{
 		"comeintime":  tmp["comeintime"],

+ 42 - 34
udpprojectset/src/projectmeger.go

@@ -65,7 +65,7 @@ func startProjectMerge(thisinfo *Info, tmp map[string]interface{}) {
 			bNormalScore = true
 		} else {
 			extInfoTag("invalid", qu.BsonIdToSId(tmp["_id"])) //无效信息,打标记
-			go IS.Add("invalid")                              //数据统计使用
+			//go IS.Add("invalid")                              //数据统计使用
 			return
 		}
 	} else {
@@ -73,9 +73,6 @@ func startProjectMerge(thisinfo *Info, tmp map[string]interface{}) {
 	}
 	//合并流程
 	if bNormalScore {
-		PNKeyMap.Store(thisinfo.PNKey, true)
-		PBKeyMap.Store(thisinfo.PBKey, true)
-		PCKeyMap.Store(thisinfo.PCKey, true)
 		if pcbv.Buyer { //有采购单位
 			hasBuyer(pcbv, thisinfo, tmp)
 		} else { //无采购单位
@@ -190,7 +187,7 @@ func noBuyer(p PCBV, thisinfo *Info, tmp map[string]interface{}) {
 		}
 	}
 	extInfoTag(sflag, thisinfo.Id)
-	go IS.Add(sflag) //数据统计使用
+	//go IS.Add(sflag) //数据统计使用
 }
 
 //3选2打分
@@ -375,30 +372,28 @@ func getComeperProjects(p PCBV, thisinfo *Info) (res []interface{}, pncb []*Comp
 		pncb = append(pncb, pb)
 	}
 	repeatId := map[string]bool{}
-	IdLock.Lock() //此处加id锁,会引进多线程的死锁,对比三个大map数组,找到key相同的项目id数组,并去重
+	//IdLock.Lock() //此处加id锁,会引进多线程的死锁,对比三个大map数组,找到key相同的项目id数组,并去重
 	for _, pv := range pncb {
-		if pv != nil {
-			pv.KeyMap.Lock.Lock()
-			K := pv.KeyMap.Map[pv.Key]
-			if K == nil {
-				K = &Key{&[]string{}, &sync.Mutex{}}
-				pv.KeyMap.Map[pv.Key] = K
-			}
-			pv.K = K
-			pv.K.Lock.Lock()
-			pv.KeyMap.Lock.Unlock()
-			defer pv.K.Lock.Unlock()
-			newarr := []string{}
-			for _, id := range *K.Arr {
-				if !repeatId[id] {
-					newarr = append(newarr, id)
-					repeatId[id] = true
-				}
+		pv.KeyMap.Lock.Lock()
+		K := pv.KeyMap.Map[pv.Key]
+		if K == nil {
+			K = &Key{&[]string{}, &sync.Mutex{}}
+			pv.KeyMap.Map[pv.Key] = K
+		}
+		pv.K = K
+		pv.K.Lock.Lock()
+		pv.KeyMap.Lock.Unlock()
+		defer pv.K.Lock.Unlock()
+		newarr := []string{}
+		for _, id := range *K.Arr {
+			if !repeatId[id] {
+				newarr = append(newarr, id)
+				repeatId[id] = true
 			}
-			pv.IdArr = newarr
 		}
+		pv.IdArr = newarr
 	}
-	IdLock.Unlock()
+	//IdLock.Unlock()
 	for _, pv := range pncb {
 		if len(pv.IdArr) > 0 {
 			res = append(res, redis.Mget(REDISIDS, pv.IdArr))
@@ -580,19 +575,32 @@ func lockPNCBMap(thisinfo *Info) {
 		}
 		if ok {
 			break
+		} else {
+			//log.Println("has key store")
+			time.Sleep(100 * time.Millisecond)
 		}
 	}
 }
 
 //pncbMap解锁
 func unlockPNCBMap(thisinfo *Info) {
-	if len(thisinfo.PNKey) > 3 {
-		PNKeyMap.Delete(thisinfo.PNKey)
-	}
-	if len(thisinfo.PCKey) > 3 {
-		PCKeyMap.Delete(thisinfo.PCKey)
-	}
-	if len(thisinfo.PBKey) > 3 {
-		PBKeyMap.Delete(thisinfo.PBKey)
-	}
+	//log.Println("del key store", thisinfo.PNKey)
+	//if len(thisinfo.PNKey) > 3 {
+	PNKeyMap.Delete(thisinfo.PNKey)
+	//}
+	//if len(thisinfo.PCKey) > 3 {
+	PCKeyMap.Delete(thisinfo.PCKey)
+	//}
+	//if len(thisinfo.PBKey) > 3 {
+	PBKeyMap.Delete(thisinfo.PBKey)
+	//}
+}
+
+//store lock
+func storeLock(thisinfo *Info) {
+	PncbMayLock.Lock()
+	PNKeyMap.Store(thisinfo.PNKey, true)
+	PBKeyMap.Store(thisinfo.PBKey, true)
+	PCKeyMap.Store(thisinfo.PCKey, true)
+	PncbMayLock.Unlock()
 }

Vissa filer visades inte eftersom för många filer har ändrats