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

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 = ;//开始页数
    int end = ;//结束页数
    Console.WriteLine("请输入开始和结束页数例如1-100,默认为1-10");
    string index = Console.ReadLine();//获取用户输入的页数 if(index != "")
    {
    //分割页数
    string[] stt = index.Split('-');
    start = Int32.Parse(stt[]);
    end = Int32.Parse(stt[]);
    }
    //循环抓取
    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[].InnerText;//将内容添加到对象中
    //获取规格
    string GuigePath = "//span[@class='w2']/a[1]";
    DomNode = node.SelectNodes(GuigePath);
    //product
    Price.Guige = DomNode[].InnerText;
    //获取市场名称
    string adsPath = "//span[@class='w9']";
    DomNode = node.SelectNodes(adsPath);
    Price.Shichang = DomNode[].InnerText;
    //获取最新价格
    string pricePath = "//span[@class='w3']";
    DomNode = node.SelectNodes(pricePath);
    Price.Price = decimal.Parse(DomNode[].InnerText);
    //获取走势
    string zoushiPath = "//span[@class='w4']";
    DomNode = node.SelectNodes(zoushiPath);
    Price.Zoushi = DomNode[].InnerText;
    //获取周涨跌
    string zhouzdPath = "//span[@class='w5']/em[1]";
    DomNode = node.SelectNodes(zhouzdPath);
    Price.Zhouzd = decimal.Parse(GetZD(DomNode[].InnerText));
    //获取月涨跌
    string yuezdPath = "//span[@class='w6']/em[1]";
    DomNode = node.SelectNodes(yuezdPath);
    Price.Yuezd = decimal.Parse(GetZD(DomNode[].InnerText));
    //获取年涨跌
    string nianzdPath = "//span[@class='w7']/em[1]";
    DomNode = node.SelectNodes(nianzdPath);
    Price.Nianzd = decimal.Parse(GetZD(DomNode[].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 = ;
    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(, , , , , , );
    return Convert.ToInt64(ts.TotalSeconds).ToString();
    }
    /// <summary>
    /// 去除字符串中的百分比
    /// </summary>
    /// <param name="str">处理的字符串</param>
    /// <returns></returns>
    public static string GetZD(string str)
    {
    string st = str.Substring(, str.Length - );
    return st;
    } }
    }
  • 以上代码主要是存到数据库,下面说下怎么存到本地。
  • 4、存储到本地

  存储到本地只需要把test方法里的Price对象改为Product类型,然后再add到ProductList集合里,再把注释的//写入json并存到本地//方法取消注释就好了。

  • 5、连接到mysql

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

最新文章

  1. [LeetCode] Palindrome Partitioning 拆分回文串
  2. NodeJs 创建 Web 服务器
  3. ESXi 6.0 配置
  4. div动态显示iframe内容
  5. apr 内存管理
  6. Cordova调用Activity
  7. 统计Crash工具—Crashlytics
  8. jQuery实现跨域访问
  9. 【转】MegaSAS RAID卡 BBU Learn Cycle周期的影响
  10. EasyPR--开发详解
  11. Java中的流程控制(一)
  12. ASI简单实现网络编程
  13. 解决无法打开myeclipse--&gt;“The default workspace&#39;D: /myeclipse spaceis in use or cannot be created. Please choose a different one”
  14. JavaSE_List&amp;Array_Java1.7
  15. rgb &amp; rgba convert
  16. BZOJ1068 [SCOI2007]压缩 区间动态规划 字符串
  17. Swift Assert 断言
  18. LOJ#6118 鬼牌
  19. 函数嵌套&gt;作用域&gt;闭包函数
  20. @JVM垃圾收集器种类

热门文章

  1. NSBundle 的理解和 mainBundle
  2. &lt;欧奈尔制胜法则—如何在股市中赚钱&gt;读书笔记
  3. 用Jquery load text文本到網頁遇到的問題
  4. C语言函数可变长度参数剖析
  5. Redrain个人维护并使用的DuiLib和UiLib库源代码下载地址
  6. WEB系统启动时加载Log4j的配置文件
  7. STL容器删除元素的陷阱
  8. ORACLE自定义顺序排序-转
  9. CENTOS 下 编译安装 tesseract-ocr 3.0.4 识别文字
  10. java实例练习