Explorar o código

!1586 原统计局页面失效,换源重写同步逻辑
Merge pull request !1586 from 喵你个汪/next

zuohuaijun hai 1 ano
pai
achega
8f752d0de6
Modificáronse 1 ficheiros con 181 adicións e 97 borrados
  1. 181 97
      Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs

+ 181 - 97
Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs

@@ -4,8 +4,8 @@
 //
 // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
 
-using AngleSharp;
-using AngleSharp.Html.Dom;
+using NewLife.Http;
+using NewLife.Serialization;
 
 namespace Admin.NET.Core.Service;
 
@@ -145,119 +145,203 @@ public class SysRegionService : IDynamicApiController, ITransient
     {
         var syncLevel = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysRegionSyncLevel);
         if (syncLevel is < 1 or > 5) syncLevel = 3;//默认区县级
-        var context = BrowsingContext.New(AngleSharp.Configuration.Default.WithDefaultLoader());
-        var dom = await context.OpenAsync(_url);
-
-        // 省级
-        var itemList = dom.QuerySelectorAll("table.provincetable tr.provincetr td a");
-        if (itemList.Length == 0) throw Oops.Oh(ErrorCodeEnum.R2005);
-
+        
         await _sysRegionRep.DeleteAsync(u => u.Id > 0);
+        
+        await SyncByMap(syncLevel);
+        
+        // var context = BrowsingContext.New(AngleSharp.Configuration.Default.WithDefaultLoader());
+        // var dom = await context.OpenAsync(_url);
+        //
+        // // 省级列表
+        // var itemList = dom.QuerySelectorAll("table.provincetable tr.provincetr td a");
+        // if (itemList.Length == 0) throw Oops.Oh(ErrorCodeEnum.R2005);
+        //
+        // await _sysRegionRep.DeleteAsync(u => u.Id > 0);
+        //
+        // foreach (var element in itemList)
+        // {
+        //     var item = (IHtmlAnchorElement)element;
+        //     var list = new List<SysRegion>();
+        //
+        //     var region = new SysRegion
+        //     {
+        //         Id = YitIdHelper.NextId(),
+        //         Pid = 0,
+        //         Name = item.TextContent,
+        //         Remark = item.Href,
+        //         Level = 1,
+        //     };
+        //     list.Add(region);
+        //
+        //     // 市级
+        //     if (!string.IsNullOrEmpty(item.Href))
+        //     {
+        //         var dom1 = await context.OpenAsync(item.Href);
+        //         var itemList1 = dom1.QuerySelectorAll("table.citytable tr.citytr td a");
+        //         for (var i1 = 0; i1 < itemList1.Length; i1 += 2)
+        //         {
+        //             var item1 = (IHtmlAnchorElement)itemList1[i1 + 1];
+        //             var region1 = new SysRegion
+        //             {
+        //                 Id = YitIdHelper.NextId(),
+        //                 Pid = region.Id,
+        //                 Name = item1.TextContent,
+        //                 Code = itemList1[i1].TextContent,
+        //                 Remark = item1.Href,
+        //                 Level = 2,
+        //             };
+        //
+        //             // 若URL中查询的一级行政区域缺少Code则通过二级区域填充
+        //             if (list.Count == 1 && !string.IsNullOrEmpty(region1.Code))
+        //                 region.Code = region1.Code.Substring(0, 2).PadRight(region1.Code.Length, '0');
+        //
+        //             // 同步层级为“1-省级”退出
+        //             if (syncLevel < 2) break;
+        //
+        //             list.Add(region1);
+        //
+        //             // 区县级
+        //             if (string.IsNullOrEmpty(item1.Href) || syncLevel <= 2) continue;
+        //
+        //             var dom2 = await context.OpenAsync(item1.Href);
+        //             var itemList2 = dom2.QuerySelectorAll("table.countytable tr.countytr td a");
+        //             for (var i2 = 0; i2 < itemList2.Length; i2 += 2)
+        //             {
+        //                 var item2 = (IHtmlAnchorElement)itemList2[i2 + 1];
+        //                 var region2 = new SysRegion
+        //                 {
+        //                     Id = YitIdHelper.NextId(),
+        //                     Pid = region1.Id,
+        //                     Name = item2.TextContent,
+        //                     Code = itemList2[i2].TextContent,
+        //                     Remark = item2.Href,
+        //                     Level = 3,
+        //                 };
+        //                 list.Add(region2);
+        //
+        //                 // 街道级
+        //                 if (string.IsNullOrEmpty(item2.Href) || syncLevel <= 3) continue;
+        //
+        //                 var dom3 = await context.OpenAsync(item2.Href);
+        //                 var itemList3 = dom3.QuerySelectorAll("table.towntable tr.towntr td a");
+        //                 for (var i3 = 0; i3 < itemList3.Length; i3 += 2)
+        //                 {
+        //                     var item3 = (IHtmlAnchorElement)itemList3[i3 + 1];
+        //                     var region3 = new SysRegion
+        //                     {
+        //                         Id = YitIdHelper.NextId(),
+        //                         Pid = region2.Id,
+        //                         Name = item3.TextContent,
+        //                         Code = itemList3[i3].TextContent,
+        //                         Remark = item3.Href,
+        //                         Level = 4,
+        //                     };
+        //                     list.Add(region3);
+        //
+        //                     // 村级
+        //                     if (string.IsNullOrEmpty(item3.Href) || syncLevel <= 4) continue;
+        //
+        //                     var dom4 = await context.OpenAsync(item3.Href);
+        //                     var itemList4 = dom4.QuerySelectorAll("table.villagetable tr.villagetr td");
+        //                     for (var i4 = 0; i4 < itemList4.Length; i4 += 3)
+        //                     {
+        //                         list.Add(new SysRegion
+        //                         {
+        //                             Id = YitIdHelper.NextId(),
+        //                             Pid = region3.Id,
+        //                             Name = itemList4[i4 + 2].TextContent,
+        //                             Code = itemList4[i4].TextContent,
+        //                             CityCode = itemList4[i4 + 1].TextContent,
+        //                             Level = 5,
+        //                         });
+        //                     }
+        //                 }
+        //             }
+        //         }
+        //     }
+        //
+        //     //按省份同步快速写入提升同步效率,全部一次性写入容易出现从统计局获取数据失败
+        //     await _sysRegionRep.Context.Fastest<SysRegion>().BulkCopyAsync(list);
+        // }
+    }
+    
+    /// <summary>
+    /// 从统计局地图页面同步
+    /// </summary>
+    /// <param name="syncLevel"></param>
+    private async Task SyncByMap(int syncLevel)
+    {
+        var client = new HttpClient();
+        client.DefaultRequestHeaders.Add("Referer", "http://xzqh.mca.gov.cn/map");
+        var html = await client.GetStringAsync("http://xzqh.mca.gov.cn/map");
 
-        foreach (var element in itemList)
+        var municipalityList = new List<string> { "北京", "天津", "上海", "重庆" };
+        var provList = Regex.Match(html, @"(?<=var json = )(\[\{.*?\}\])(?=;)").Value.ToJsonEntity<List<Dictionary<string, string>>>();
+        foreach (var dict1 in provList)
         {
-            var item = (IHtmlAnchorElement)element;
             var list = new List<SysRegion>();
-
-            var region = new SysRegion
+            var provName = dict1.GetValueOrDefault("shengji");
+            var province = new SysRegion
             {
                 Id = YitIdHelper.NextId(),
-                Pid = 0,
-                Name = item.TextContent,
-                Remark = item.Href,
+                Name = Regex.Replace(provName, "[((].*?[))]", ""),
+                Code = dict1.GetValueOrDefault("quHuaDaiMa"),
+                CityCode = dict1.GetValueOrDefault("quhao"),
                 Level = 1,
+                Pid = 0,
             };
-            list.Add(region);
+            if (municipalityList.Any(m => province.Name.StartsWith(m))) province.Name +=  "(省)";
+            list.Add(province);
 
-            // 市级
-            if (!string.IsNullOrEmpty(item.Href))
+            if (syncLevel <= 1) continue;
+            
+            var prefList = await GetSelectList(provName);
+            foreach (var dict2 in prefList)
             {
-                var dom1 = await context.OpenAsync(item.Href);
-                var itemList1 = dom1.QuerySelectorAll("table.citytable tr.citytr td a");
-                for (var i1 = 0; i1 < itemList1.Length; i1 += 2)
+                var prefName = dict2.GetValueOrDefault("diji");
+                var city = new SysRegion
                 {
-                    var item1 = (IHtmlAnchorElement)itemList1[i1 + 1];
-                    var region1 = new SysRegion
+                    Id = YitIdHelper.NextId(),
+                    Code = dict2.GetValueOrDefault("quHuaDaiMa"),
+                    CityCode = dict2.GetValueOrDefault("quhao"),
+                    Pid = province.Id,
+                    Name = prefName,
+                    Level = 2
+                };
+                if (municipalityList.Any(m => city.Name.StartsWith(m))) city.Name +=  "(地)";
+                list.Add(city);
+                
+                if (syncLevel <= 2) continue;
+                
+                var countyList = await GetSelectList(provName, prefName);
+                foreach (var dict3 in countyList)
+                {
+                    var countyName = dict3.GetValueOrDefault("xianji");
+                    var county = new SysRegion
                     {
                         Id = YitIdHelper.NextId(),
-                        Pid = region.Id,
-                        Name = item1.TextContent,
-                        Code = itemList1[i1].TextContent,
-                        Remark = item1.Href,
-                        Level = 2,
+                        Code = dict3.GetValueOrDefault("quHuaDaiMa"),
+                        CityCode = dict3.GetValueOrDefault("quhao"),
+                        Name = countyName,
+                        Pid = city.Id,
+                        Level = 3
                     };
-
-                    // 若URL中查询的一级行政区域缺少Code则通过二级区域填充
-                    if (list.Count == 1 && !string.IsNullOrEmpty(region1.Code))
-                        region.Code = region1.Code.Substring(0, 2).PadRight(region1.Code.Length, '0');
-
-                    // 同步层级为“1-省级”退出
-                    if (syncLevel < 2) break;
-
-                    list.Add(region1);
-
-                    // 区县级
-                    if (string.IsNullOrEmpty(item1.Href) || syncLevel <= 2) continue;
-
-                    var dom2 = await context.OpenAsync(item1.Href);
-                    var itemList2 = dom2.QuerySelectorAll("table.countytable tr.countytr td a");
-                    for (var i2 = 0; i2 < itemList2.Length; i2 += 2)
-                    {
-                        var item2 = (IHtmlAnchorElement)itemList2[i2 + 1];
-                        var region2 = new SysRegion
-                        {
-                            Id = YitIdHelper.NextId(),
-                            Pid = region1.Id,
-                            Name = item2.TextContent,
-                            Code = itemList2[i2].TextContent,
-                            Remark = item2.Href,
-                            Level = 3,
-                        };
-                        list.Add(region2);
-
-                        // 街道级
-                        if (string.IsNullOrEmpty(item2.Href) || syncLevel <= 3) continue;
-
-                        var dom3 = await context.OpenAsync(item2.Href);
-                        var itemList3 = dom3.QuerySelectorAll("table.towntable tr.towntr td a");
-                        for (var i3 = 0; i3 < itemList3.Length; i3 += 2)
-                        {
-                            var item3 = (IHtmlAnchorElement)itemList3[i3 + 1];
-                            var region3 = new SysRegion
-                            {
-                                Id = YitIdHelper.NextId(),
-                                Pid = region2.Id,
-                                Name = item3.TextContent,
-                                Code = itemList3[i3].TextContent,
-                                Remark = item3.Href,
-                                Level = 4,
-                            };
-                            list.Add(region3);
-
-                            // 村级
-                            if (string.IsNullOrEmpty(item3.Href) || syncLevel <= 4) continue;
-
-                            var dom4 = await context.OpenAsync(item3.Href);
-                            var itemList4 = dom4.QuerySelectorAll("table.villagetable tr.villagetr td");
-                            for (var i4 = 0; i4 < itemList4.Length; i4 += 3)
-                            {
-                                list.Add(new SysRegion
-                                {
-                                    Id = YitIdHelper.NextId(),
-                                    Pid = region3.Id,
-                                    Name = itemList4[i4 + 2].TextContent,
-                                    Code = itemList4[i4].TextContent,
-                                    CityCode = itemList4[i4 + 1].TextContent,
-                                    Level = 5,
-                                });
-                            }
-                        }
-                    }
+                    list.Add(county);
                 }
             }
-
             //按省份同步快速写入提升同步效率,全部一次性写入容易出现从统计局获取数据失败
             await _sysRegionRep.Context.Fastest<SysRegion>().BulkCopyAsync(list);
         }
+
+        // 获取选择数据
+        async Task<List<Dictionary<string, string>>> GetSelectList(string prov, string prefecture=null)
+        {
+            var data = "";
+            if (!string.IsNullOrWhiteSpace(prov)) data += $"shengji={prov}";
+            if (!string.IsNullOrWhiteSpace(prefecture)) data += $"&diji={prefecture}";
+            var json = await client.PostFormAsync("http://xzqh.mca.gov.cn/selectJson", data);
+            return json.ToJsonEntity<List<Dictionary<string, string>>>();
+        }
     }
 }