2、蘇寧百萬級商品爬取 思路講解 類別頁數爬取

通過上述章節內容,我們得到了類別的數據,現在我們需要對每個類別進行商品的爬取。點擊移動電源,進行商品總頁數抓取,這個模塊相對簡單,正好適合用來練手。 我們可以從“列表頁.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個類別,多線程的意義就沒有辦法體現出來,這一點在之後的編碼中我進行了修改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章