2、苏宁百万级商品爬取 思路讲解 类别页数爬取

通过上述章节内容,我们得到了类别的数据,现在我们需要对每个类别进行商品的爬取。点击移动电源,进行商品总页数抓取,这个模块相对简单,正好适合用来练手。
我们可以从“列表页.png”的图片中看到,当前移动电源的页数为右上角所显示 1/100,即100页.
xpath的获取如第三张图所示,结果为
//*[@id="second-filter"]/div[2]/div/span

img_cd33f0b17565a030edc64b1b4e4eabd9.png
类别.png

img_d8d674f7173db56c34d14d06240814e8.png
列表页.png
img_3456325df80beeced01b281935ae7bf7.png
xpath.png

分析出了如果获取页数,我们现在要考虑的问题是,如果更新所有的类别。
其实思路非常简单,从数据库中取出对应的等级为3的类别(最底层类别),对这些类别进行循环,参数就是当前行的url,然后执行网页爬取代码,得到页数,更新数据。


img_693e118fd4d29cd506798b51c469ff0b.png
数据库类别数据.png

根据Sql语句,得到等级为3的类别一共有4197个。这个时候就存在问题了,如果同步执行(循环一个一个执行),那么我的效率就很低,为了验证自己的写法。我以50个类别为例做了一个小demo测试性能。

     //获取符合条件的列表
     var urlList = _categoryService.GetListByLevel(3).Select(u => u.Url).ToList();

CategoryPageAnalysis.GetData(string url) 方法为获取类别个数方法

同步

循环执行,耗时18233毫秒

            var dics = new Dictionary<string, int>();
            foreach (var url in urlList)
            {
                dics.Add(url, CategoryPageAnalysis.GetData(url));
            }
异步方法

6163毫秒 3倍的效率差
异步方法体的说明如下:
首先因为存在4197个类别,需要对这些类别进行分类。
4197/2000 约等于20. 即开20个线程,每个线程执行200条数据

            int pageNum = 200;
            int pageCount = urlList.Count % pageNum == 0 ? urlList.Count / pageNum : urlList.Count / pageNum + 1;
            var pageListCollection = new List<List<string>>();
            for (int i = 0; i < pageCount; i++)
            {
                var pageList = urlList.Skip(i * pageNum).Take(pageNum).ToList();
                pageListCollection.Add(pageList);
            }
            Console.WriteLine(pageCount);

            //异步 6163毫秒 3倍的效率差
            int pageIndex = 1;
            List<Task> taskList = new List<Task>();
            foreach (var pageList in pageListCollection)
            {
                try
                {
                    Task task = Task.Factory.StartNew(() =>
                    {
                        var dics = new Dictionary<string, int>();
                        foreach (var url in pageList)
                        {
                            dics.Add(url, CategoryPageAnalysis.GetData(url));
                        }

                        lock (lock_obj)
                        {
                            _categoryService.BatchUpdatePage(dics);
                        }
                    });
                    taskList.Add(task);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"button3_Click 异步{ex.Message}");
                }
            }
存在的问题:

这种方法是为了单独解决这个问题而使用的,很笨拙,因为如果只有200个类别,多线程的意义就没有办法体现出来,这一点在之后的编码中我进行了修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值