C# 爬蟲練習

好幾個月前,因為要練習網站開發,就練習寫了一支,爬某知名網站的爬蟲程式,並將資料寫入資料庫,本篇筆記便於日後方便查詢

開始時,先新增一個主控台應用程式

在專案下加入一個名為 Model 的資料夾

並新增 ADO.NET 實體資料模型

並選擇 "來自資料庫的 Code First"

進入" 新增連接 "

選擇所要連接的資料庫,並測試連接

點選所要的 table,並完成

在 Model 資料夾內確認,匯入的實體資料模型

新增一個類別

class Class1
{
   public FDDB db = new FDDB();
}

因為Entity的關係,這裡採用ViewModel的方式來去接值,所以新增一個名為 ProductViewModel 的資料夾,並在此資料夾內加入一個類別,並加入欄位名稱

class ProductViewModel
{
   public int Product_Id { get; set; }
   public string Product_Name { get; set; }
   public int Product_Star { get; set; }
   public int Product_Price { get; set; }
   public string Product_Img { get; set; }
   public string Product_Brand { get; set; }
   public string Product_Specification { get; set; }
}

回到主程式部分,先宣告五個字串變數 ( 廠牌、品名、規格、圖片、價格 ),並為空字串

string Product_Brand = "";
string Product_Name = "";
string Product_Specification = "";
string Product_Img = "";
String Product_price = "";

並安裝 HTML Agility Pack 套件

加入要 load 的網址

HtmlWeb webClient = new HtmlWeb();
HtmlDocument doc = webClient.Load("https://www.ikea.com/tw/zh/catalog/categories/departments/bedroom/19037/");

然後去取得該網頁的 Xpath,那什麼是 Xpath ?

Xpath(XML Path Language,XML 路徑語言),是用於確定 XML 文檔中某節點位置的語言。

如何取得 ?

開啟開發人員工具 -> 選到這個 DOM Element -> 右鍵選擇 Copy -> Copy XPath

加入取得的 XPath,並跑 for 迴圈

// 開始撈每一筆資料
// i => 設定此頁要抓的商品數量
for (int i = 1; i <= 60; i++)
{
   for (int j = 1; j <= 4; j++)
   {
    // 品名
    HtmlNodeCollection item = doc.DocumentNode.SelectNodes($"//*[@id='productLists']/div[{i}]/div[{j}]/div[2]/a/h3/span[2]");
    // 廠牌
    HtmlNodeCollection brand = doc.DocumentNode.SelectNodes($"//*[@id='productLists']/div[{i}]/div[{j}]/div[2]/a/h3/span[1]");
    // 規格
    HtmlNodeCollection info = doc.DocumentNode.SelectNodes($"//*[@id='productLists']/div[{i}]/div[{j}]/div[2]/div/span[1]");
    // 圖片
    HtmlNodeCollection img = doc.DocumentNode.SelectNodes($"//*[@id='productLists']/div[{i}]/div[{j}]/div[1]/a/img");
    // 價格
    HtmlNodeCollection price = doc.DocumentNode.SelectNodes($"//*[@id='productLists']/div[{i}]/div[{j}]/div[2]/a/span[1]/span[1]");
   }
}

為防止漏撈時產生錯誤,導致程式停止,所以在迴圈內加上 try .. catch

try
{
   if (item != null && brand != null && info != null && img != null)
   {
       // 將取得的資料,轉型成字串,並用Replace方法取代掉不要的字串
       Product_price = price[0].InnerText.ToString().Replace("\r\n","").Replace("\t","").Replace("每單位價格","").Replace("$","").Replace(",","");
       Product_Brand = brand[0].InnerText.ToString();
       Product_Name = item[0].InnerText.ToString();
       Product_Specification = info[0].InnerText.Replace("\r\n", "").Replace("\t", "").ToString();

       String imgurl = "https://www.ikea.com/" + img[0].Attributes["src"].Value;

       // 將圖片轉為 Base64
       Bitmap bitmap = DownlandImg(imgurl);
       if (bitmap != null)
       {
           Product_Img = ChangeBase64(bitmap);

           Console.WriteLine(Product_Img);
       }

       Console.WriteLine("廠牌: {0} 品名:{1} 規格:{2} \r\n https://www.ikea.com/{3} 價格{4}", brand[0].InnerText, item[0].InnerText, info[0].InnerText.Replace("\r\n", "").Replace("\t", ""), img[0].Attributes["src"].Value, price[0].InnerText);

       // 將資料新增進資料庫
       Furniture pro = new Furniture();
       pro.Furniture_Name = Product_Name;
       pro.Furniture_Brand = Product_Brand;
       pro.Furniture_Info = Product_Specification;
       pro.Furniture_Img = Product_Img;
       pro.Furniture_Price = Int32.Parse(Product_price);
       pro.Furniture_Star = random.Next(1, 6);
       pro.Type_Id = 7;

       class1.db.Furniture.Add(pro);
       int result = class1.db.SaveChanges();
       if (result == 1)
       {
         Console.WriteLine("新增成功");
       }
       else
       {
         Console.WriteLine("新增失敗");
       }
    }
}
catch (Exception ex)
{
   // 繼續執行
   continue;
}

確認執行的結果

 

 

新人發文,文章敘述如有錯誤及觀念不正確,請不吝嗇指教,感謝~