您的位置:首页 > 数据库 > MySQL

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

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

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

  待续。。。。。。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: