[开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [四] JSON数据解析

[DotnetSpider 系列目录]

场景模拟

接上一篇, JD SKU对应的店铺信息是异步加载的,因此无法使用上一篇的爬虫直接解决。这时我们需要重新完全采集所有的SKU数据吗?补爬的话历史数据就用不了了。因此,去京东页面上找看是否有提供相关的接口。

查找API请求接口

  1. 安装 Fiddler, 并打开

  2. 在谷歌浏览器中访问: http://list.jd.com/list.html?cat=1315,1343,9719

  3. 在Fiddler查找一条条的访问记录,找到我们想要的接口

    image

编写爬虫

  1. 分析返回的数据结果,我们可以先写出数据对象的定义(观察Expression的值已经是JsonPath查询表达式了,同时Type必须设置为Type = SelectorType.JsonPath)。另外需要注意的是,这次的爬虫是更新型爬虫,就是说采集到的数据补充回原表,那么就一定要设置主键是什么,即在数据类上添加主键的定义

    复制代码
            [EntityTable("test", "jd_sku", EntityTable.Monday, Primary = "Sku", UpdateColumns = new[] { "ShopId" })]
            [EntitySelector(Expression = "$.[*]", Type = SelectorType.JsonPath)]
            class ProductUpdater : SpiderEntity
            {
                [PropertyDefine(Expression = "$.pid", Type = SelectorType.JsonPath, Length = 25)]
                public string Sku { get; set; }
    
                [PropertyDefine(Expression = "$.shopId", Type = SelectorType.JsonPath)]
                public int ShopId { get; set; }
            }
    复制代码

     

  2. 由于返回的数据中还有一个json()这样的pagging,所以需要先做一个截取操作,框架提供了PageHandler接口,并且我们实现了许多常用的Handler,用于HTML的解析前的一些处理操作。PrepareStartUrls 接口是用来从数据源来获取起始URL,而不需要把URL直接写在代码里。完整的代码如下

    复制代码
        public class JdShopDetailSpider : EntitySpider
        {
            public JdShopDetailSpider() : base("JdShopDetailSpider", new Site())
            {
            }
    
            protected override void MyInit(params string[] arguments)
            {
                Identity = Identity ?? Guid.NewGuid().ToString();
                Downloader.AddAfterDownloadCompleteHandler(new SubContentHandler
                {
                    StartPart = "json(",
                    EndPart = ");",
                    StartOffset = 5,
                    EndOffset = 0
                });
    
                AddStartUrlBuilder(new DbStartUrlBuilder(Database.MySql,
                    "Database='mysql';Data Source=localhost;User ID=root;Password=;Port=3306;SslMode=None;",
                    $"SELECT * FROM test.jd_sku_{DateTimeUtils.MondayOfCurrentWeek.ToString("yyyy_MM_dd")} WHERE ShopName is null or ShopId is null or ShopId = 0 order by sku", new[] { "sku" },
                    "http://chat1.jd.com/api/checkChat?my=list&pidList={0}&callback=json"));
                AddPipeline(new MySqlEntityPipeline("Database='mysql';Data Source=localhost;User ID=root;Password=;Port=3306;SslMode=None;"));
                AddEntityType(typeof(ProductUpdater));
            }
    
            [EntityTable("test", "jd_sku", EntityTable.Monday, Primary = "Sku", UpdateColumns = new[] { "ShopId" })]
            [EntitySelector(Expression = "$.[*]", Type = SelectorType.JsonPath)]
            class ProductUpdater : SpiderEntity
            {
                [PropertyDefine(Expression = "$.pid", Type = SelectorType.JsonPath, Length = 25)]
                public string Sku { get; set; }
    
                [PropertyDefine(Expression = "$.shopId", Type = SelectorType.JsonPath)]
                public int ShopId { get; set; }
            }
        }
    复制代码

     

代码地址

https://github.com/zlzforever/DotnetSpider 望各位大佬加星 😃

 

参与开发或有疑问

博文写得比较早, 框架修改有时会来不及更新博文中的代码, 请查看DotnetSpider.Sample项目中的样例爬虫

QQ群: 477731655

邮箱: zlzforever@163.com

posted on   Lewis.Zou  阅读(6539)  评论(12编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示