使用HtmlAgilityPack爬取網站信息並存儲到mysql

来源:http://www.cnblogs.com/ashidamana/archive/2016/12/07/6140637.html
-Advertisement-
Play Games

前言:打算做一個藥材價格查詢的功能,但剛開始一點數據都沒有靠自己找信息錄入的話很麻煩的,所以只有先到其它網站抓取存到資料庫再開始做這個了。 HtmlAgilityPack在c#里應該很多人用吧,簡單又強大。之前也用它做過幾個爬取信息的小工具。不過很久了源代碼都沒有了,都忘了怎麼用了,這次也是一點一點 ...


前言:打算做一個藥材價格查詢的功能,但剛開始一點數據都沒有靠自己找信息錄入的話很麻煩的,所以只有先到其它網站抓取存到資料庫再開始做這個了。

HtmlAgilityPack在c#里應該很多人用吧,簡單又強大。之前也用它做過幾個爬取信息的小工具。不過很久了源代碼都沒有了,都忘了怎麼用了,這次也是一點一點找資料慢慢做出來的!

(不過最麻煩的是將數據存到mysql,.net資料庫我一直用的都是mssql,所以第一次做連接mysql遇到了好多問題。)

1、使用HtmlAgilityPack

  • 下載HtmlAgilityPack類庫,並引用到你的項目

  我這裡使用的控制台項目

項目添加引用

代碼里添加引用


 

2、分析網頁

  • 網頁地址:http://www.zyctd.com/jiage/1-0-0-0.html

    首先看每一頁的url變化,觀察後發現這個很簡單:

    第一頁就是:1-0-0或者1-0-0-1表示第一頁

    第二頁就是:1-0-0-2一次類推

  • 然後再分析他的源代碼

很明顯這一頁的數據都放在了ul標簽里了,而且還有類名:<ul class="priceTableRows">,

然後再看下ul下的li標簽,li標簽里的html寫的也都相同,然後就可以開始寫代碼抓取了。

3、抓取信息

  • 首先新建一個類文件,來存儲抓取的信息。因為我是直接存到資料庫用的是ado.net實體數據模型生成的文件。
  • 下麵是ado.net實體數據模型生成的文件:

 

//------------------------------------------------------------------------------
// <auto-generated>
//     此代碼已從模板生成。
//
//     手動更改此文件可能導致應用程式出現意外的行為。
//     如果重新生成代碼,將覆蓋對此文件的手動更改。
// </auto-generated>
//------------------------------------------------------------------------------

namespace 測試項目1
{
    using System;
    using System.Collections.Generic;
    
    public partial class C33hao_price
    {
        public long ID { get; set; }
        public string Name { get; set; }
        public string Guige { get; set; }
        public string Shichang { get; set; }
        public decimal Price { get; set; }
        public string Zoushi { get; set; }
        public decimal Zhouzd { get; set; }
        public decimal Yuezd { get; set; }
        public decimal Nianzd { get; set; }
        public int editDate { get; set; }
        public string other { get; set; }
    }
}

 

  • 下麵這個是剛開始測試存到本地時寫的類:
  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 測試項目1
    {
        public class Product
        {
            /// <summary>
            /// 品名
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// 規格
            /// </summary>
            public string Guige { get; set; }
            /// <summary>
            /// 市場
            /// </summary>
            public string Shichang { get; set; }
            /// <summary>
            /// 最新價格
            /// </summary>
            public string Price { get; set; }
            /// <summary>
            /// 走勢
            /// </summary>
            public string Zoushi { get; set; }
            /// <summary>
            /// 周漲跌
            /// </summary>
            public string Zhouzd { get; set; }
            /// <summary>
            /// 月漲跌
            /// </summary>
            public string Yuezd { get; set; }
            /// <summary>
            /// 年漲跌
            /// </summary>
            public string Nianzt { get; set; }
    
        }
    }

    下麵是主要的處理代碼

  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using HtmlAgilityPack;
    using System.IO;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;
    
    namespace 測試項目1
    {
        public class Program
        {
            /// <summary>
            /// 本地測試信息類
            /// </summary>
            static List<Product> ProductList = new List<Product>();
            /// <summary>
            /// 資料庫生成的信息類
            /// </summary>
            static List<C33hao_price> PriceList = new List<C33hao_price>();
            public static void Main(string[] args)
            {
                
                int start = 1;//開始頁數
                int end = 10;//結束頁數
                Console.WriteLine("請輸入開始和結束頁數例如1-100,預設為1-10");
                string index = Console.ReadLine();//獲取用戶輸入的頁數
                
                if(index != "")
                {
                    //分割頁數
                    string[] stt = index.Split('-');
                    start = Int32.Parse(stt[0]);
                    end = Int32.Parse(stt[1]);
                }
                //迴圈抓取
                for(int i = start; i<= end; i++)
                {
                    string url = string.Format("http://www.zyctd.com/jiage/1-0-0-{0}.html", i);
    
    
                HtmlWeb web = new HtmlWeb();
                HtmlDocument doc = web.Load(url);//獲取網頁
                    
                HtmlNode node = doc.DocumentNode;
                string xpathstring = "//ul[@class='priceTableRows']/li";//路徑  
                HtmlNodeCollection aa = node.SelectNodes(xpathstring);//獲取每一頁ul下的所有li標簽里的html
                    if (aa == null)
                    {
                        Console.WriteLine("出錯:當前頁為{0}", i.ToString());
                        continue;
                    }
                foreach(var item in aa)
                {
                    //處理li標簽信息添加到集合
                    string cc = item.InnerHtml;
                    test(cc);
                    
                }
                }
                //寫入json並存到本地
                //string path = "json/test.json";
                //using(StreamWriter sw = new StreamWriter(path))
                //{
                //    try
                //    {
                //        JsonSerializer serializer = new JsonSerializer();
                //        serializer.Converters.Add(new JavaScriptDateTimeConverter());
                //        serializer.NullValueHandling = NullValueHandling.Ignore;
                //        //構建Json.net的寫入流
                //        JsonWriter writer = new JsonTextWriter(sw);
                //        //把模型數據序列化並寫入Json.net的JsonWriter流中  
                //        serializer.Serialize(writer,ProductList);
                //        //ser.Serialize(writer, ht);  
                //        writer.Close();
                //        sw.Close();
                //    }
                //    catch (Exception ex)
                //    {
                //        string error = ex.Message.ToString();
                //        Console.WriteLine(error);
                //    }
                //}
                int count = PriceList.Count();//抓取到的信息條數
                Console.WriteLine("獲取信息{0}條", count);
                Console.WriteLine("開始添加到資料庫");
                Insert();//插入到資料庫
                Console.WriteLine("數據添加完畢");
                Console.ReadLine();
            }
            /// <summary>
            /// 處理信息並添加到集合中
            /// </summary>
            /// <param name="str">li標簽的html內容</param>
            static void test(string str)
            {
                //Product product = new Product();
                C33hao_price Price = new C33hao_price();
    
                HtmlDocument doc = new HtmlDocument();
                doc.LoadHtml(str);
                HtmlNode node = doc.DocumentNode;
                //獲取藥材名稱
                string namepath = "//span[@class='w1']/a[1]";//名稱路徑
                HtmlNodeCollection DomNode = node.SelectNodes(namepath);//根據路徑獲取內容
                //product.Name = DomNode[0].InnerText;
                Price.Name = DomNode[0].InnerText;//將內容添加到對象中
                //獲取規格
                string GuigePath = "//span[@class='w2']/a[1]";
                DomNode = node.SelectNodes(GuigePath);
                //product
                Price.Guige = DomNode[0].InnerText;
                //獲取市場名稱
                string adsPath = "//span[@class='w9']";
                DomNode = node.SelectNodes(adsPath);
                Price.Shichang = DomNode[0].InnerText;
                //獲取最新價格
                string pricePath = "//span[@class='w3']";
                DomNode = node.SelectNodes(pricePath);
                Price.Price = decimal.Parse(DomNode[0].InnerText);
                //獲取走勢
                string zoushiPath = "//span[@class='w4']";
                DomNode = node.SelectNodes(zoushiPath);
                Price.Zoushi = DomNode[0].InnerText;
                //獲取周漲跌
                string zhouzdPath = "//span[@class='w5']/em[1]";
                DomNode = node.SelectNodes(zhouzdPath);
                Price.Zhouzd = decimal.Parse(GetZD(DomNode[0].InnerText));
                //獲取月漲跌
                string yuezdPath = "//span[@class='w6']/em[1]";
                DomNode = node.SelectNodes(yuezdPath);
                Price.Yuezd = decimal.Parse(GetZD(DomNode[0].InnerText));
                //獲取年漲跌
                string nianzdPath = "//span[@class='w7']/em[1]";
                DomNode = node.SelectNodes(nianzdPath);
                Price.Nianzd = decimal.Parse(GetZD(DomNode[0].InnerText));
                //添加時間
                Price.editDate = Int32.Parse(GetTimeStamp());//轉換為時間戳格式,方便php使用
                //ProductList.Add(product);
                PriceList.Add(Price);//添加到對象集合
            }
    
            //查詢
            static void Query()
            {
                var context = new mallEntities();
                var member = from e in context.member select e;
                foreach(var u in member)
                {
                    Console.WriteLine(u.member_name);
                    Console.WriteLine(u.member_mobile);
                }
                Console.ReadLine();
            }
            //插入
            static void Insert()
            {
                var context = new mallEntities();
                C33hao_price Price = new C33hao_price();
                int i = 0;
                foreach (C33hao_price item in PriceList)
                {
                    context.C33hao_price.Add(item);
                    context.SaveChanges();
                    i++;
                    Console.WriteLine("{0}/{1}", i, PriceList.Count);
                }
            }
            /// <summary>  
            /// 獲取時間戳  
            /// </summary>  
            /// <returns></returns>  
            public static string GetTimeStamp()
            {
                TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                return Convert.ToInt64(ts.TotalSeconds).ToString();
            }
            /// <summary>
            /// 去除字元串中的百分比
            /// </summary>
            /// <param name="str">處理的字元串</param>
            /// <returns></returns>
            public static string GetZD(string str)
            {
                string st = str.Substring(0, str.Length - 1);
                return st;
            }
    
        }
    }
  • 以上代碼主要是存到資料庫,下麵說下怎麼存到本地。
  • 4、存儲到本地

  存儲到本地只需要把test方法里的Price對象改為Product類型,然後再add到ProductList集合里,再把註釋的//寫入json並存到本地//方法取消註釋就好了。

  • 5、連接到mysql

  待續。。。。。。。。。。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、ORACLE的啟動和關閉 1、在單機環境下 要想啟動或關閉ORACLE系統必須首先切換到ORACLE用戶,如下 su - oracle a、啟動ORACLE系統 oracle>svrmgrl SVRMGR>connect internal SVRMGR>startup SVRMGR>quit b ...
  • -- 帶參輸出的存儲過程 --測試方法:--declare @return int--exec 測試用勿刪 1, @return out--print @return-- Create PROCEDURE [dbo].[測試用勿刪]@userid int, @return int outASbegi ...
  • 網上一直說的是先安裝SQL Server 2014,再安裝VS2015,軟體就不會出現問題。我這次在什麼都沒準備的情況下安裝了VS2015,安裝之後發覺VS2015自帶的SQL2014只有連接伺服器和管理資料庫的功能,能有操作資料庫的功能,不能進入到SQL Server 2014 Managemen ...
  • 從0開始搭建SQL Server AlwaysOn 第四篇(配置異地機房節點) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www.cnblogs.com/lyhabc/p/4682028.html第三篇http://www.cn ...
  • 安裝Oracle時出現環境變數Path的值大於1023的解決辦法 ...
  • 建庫 CREATE DATABASE 資料庫名 ON[PRIMARY] --預設屬於PRIMARY主文件組,可省略 ( NAME='', --主數據文件的邏輯名 名稱 FILEAME='', --主數據文件的物理名 路徑 .mdf 次資料庫為.ndf SIZE=5mb, --主數據文件初始大小 MA ...
  • 前言 很多時候資料庫的TempDB、日誌等文件的暴增可能導致磁碟空間被占滿,如果日常配置不到位,往往會導致資料庫故障,業務被迫中斷。 這種文件暴增很難排查,經驗不足的一些運維人員可能更是無法排查具體原因,導致問題不能徹底解決。 場景描述 客戶系統比較穩定,用了5台機器做了AlwaysOn高可用組,完 ...
  • MySQL 執行計劃 在SQL優化時,查看執行計劃,是一個有效的途徑。 1、Explain 語法 2、Explain 列說明 在mysql中,一個執行通常包括面的列: 下麵的列說明中,會使用這個例子進行說明。 2.1 id 通過Id,可以看到sql的執行順序。 預設情況下,一個簡單的select的i ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...