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