• 使用HtmlAgilityPack爬取网站信息并存储到mysql


    前言:打算做一个药材价格查询的功能,但刚开始一点数据都没有靠自己找信息录入的话很麻烦的,所以只有先到其它网站抓取存到数据库再开始做这个了。

    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

      待续。。。。。。。。。。

  • 相关阅读:
    API测试之Postman使用完全指南(Postman教程,这篇文章就够了)
    asp.net的webservice
    表和索引的结构(笔记)
    基于Nginx+PHP+Redis的短URL系统的实现 新风宇宙
    数据结构与算法(php版) 新风宇宙
    discuz7.2 昵称替换用户名 新风宇宙
    gVim7.3(Vim7.3)文本编辑器详细配置文件和配色方案 新风宇宙
    Discuz的Memcache缓存实现 新风宇宙
    GitHub使用(二) 从代码库下载代码到本地 新风宇宙
    PHPredis中文文档 新风宇宙
  • 原文地址:https://www.cnblogs.com/ashidamana/p/6140637.html
Copyright © 2020-2023  润新知