使用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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...