美文网首页爬虫程序员dotNET
2、苏宁百万级商品爬取 思路讲解 类别页数爬取

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

作者: HapplyFox | 来源:发表于2018-07-10 15:24 被阅读3次

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

    类别.png
    列表页.png xpath.png

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


    数据库类别数据.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个类别,多线程的意义就没有办法体现出来,这一点在之后的编码中我进行了修改。

    相关文章

      网友评论

        本文标题:2、苏宁百万级商品爬取 思路讲解 类别页数爬取

        本文链接:https://www.haomeiwen.com/subject/diqxpftx.html