作者: 乔克斯
查看: 2748|回复: 1
打印 上一主题 下一主题

[教程] 【解析HTML各节点】C#解析HTML

[复制链接]
跳转到指定楼层
楼主
乔克斯 发表于 2014-9-20 01:00:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
查看: 2748|回复: 1
【解析HTML各节点】C#解析HTML

前言:

在搜索引擎的开发中,我们需要对网页的Html内容进行检索,难免的就需要对Html进行解析。
拆分每一个节点并且获取节点间的内容。此文介绍两种C#解析Html的方法。

效果截图:


第一种方法:

用System.Net.WebClient下载Web Page存到本地文件或者String中,用正则表达式来分析。
这个方法可以用在Web Crawler等需要分析很多Web Page的应用中。
估计这也是大家最直接,最容易想到的一个方法。
转自网上的一个实例:所有的href都抽取出来:
[C#] 纯文本查看 复制代码
using System;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
namespace HttpGet
{
    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            System.Net.WebClient client = new WebClient();
            byte[] page = client.DownloadData("http://www.google.com");
            string content = System.Text.Encoding.UTF8.GetString(page);
            string regex = "href=[\\\"\\\'](http:\\/\\/|\\.\\/|\\/)?\\w+(\\.\\w+)*(\\/\\w+(\\.\\w+)?)*(\\/|\\?\\w*=\\w*(&\\w*=\\w*)*)?[\\\"\\\']";
            Regex re = new Regex(regex);
            MatchCollection matches = re.Matches(content);

            System.Collections.IEnumerator enu = matches.GetEnumerator();
            while (enu.MoveNext() && enu.Current != null)
            {
                Match match = (Match)(enu.Current);
                Console.Write(match.Value + "\r\n");
            }
        }
    }
}

一些爬虫的HTML解析中也是用的类似的方法。

第二种方法:

利用Winista.Htmlparser.Net 解析Html。
这是.NET平台下解析Html的开源代码,网上有源码下载,百度一下就能搜到,这里就不提供了。
并且有英文的帮助文档。找不到的留下邮箱。
个人认为这是.net平台下解析html不错的解决方案,基本上能够满足我们对html的解析工作。

自己做了个实例:
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Winista.Text.HtmlParser;
using Winista.Text.HtmlParser.Lex;
using Winista.Text.HtmlParser.Util;
using Winista.Text.HtmlParser.Tags;
using Winista.Text.HtmlParser.Filters;

namespace HTMLParser
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            AddUrl();
        }

        private void btnParser_Click(object sender, EventArgs e)
        {
            #region 获得网页的html
            try
            {

                txtHtmlWhole.Text = "";
                string url = CBUrl.SelectedItem.ToString().Trim();
                System.Net.WebClient aWebClient = new System.Net.WebClient();
                aWebClient.Encoding = System.Text.Encoding.Default;
                string html = aWebClient.DownloadString(url);
                txtHtmlWhole.Text = html;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            #endregion

            #region 分析网页html节点
            Lexer lexer = new Lexer(this.txtHtmlWhole.Text);
            Parser parser = new Parser(lexer);
            NodeList htmlNodes = parser.Parse(null);
            this.treeView1.Nodes.Clear();
            this.treeView1.Nodes.Add("root");
            TreeNode treeRoot = this.treeView1.Nodes[0];
            for (int i = 0; i < htmlNodes.Count; i++)
             {
                 this.RecursionHtmlNode(treeRoot, htmlNodes, false);
             }
             #endregion
         }
         private void RecursionHtmlNode(TreeNode treeNode, INode htmlNode, bool siblingRequired)
         {
             if (htmlNode == null || treeNode == null) return;
             TreeNode current = treeNode;
             TreeNode content ;
             //current node
             if (htmlNode is ITag)
             {
                 ITag tag = (htmlNode as ITag);
                 if (!tag.IsEndTag())
                 {
                     string nodeString = tag.TagName;
                     if (tag.Attributes != null && tag.Attributes.Count > 0)
                    {
                        if (tag.Attributes["ID"] != null)
                        {
                            nodeString = nodeString + " { id=\"" + tag.Attributes["ID"].ToString() + "\" }";
                        }
                        if (tag.Attributes["HREF"] != null)
                        {
                            nodeString = nodeString + " { href=\"" + tag.Attributes["HREF"].ToString() + "\" }";
                        }
                    }

                    current = new TreeNode(nodeString);
                    treeNode.Nodes.Add(current);
                }
            }

            //获取节点间的内容
            if (htmlNode.Children != null && htmlNode.Children.Count > 0)
            {
                this.RecursionHtmlNode(current, htmlNode.FirstChild, true);
                content = new TreeNode(htmlNode.FirstChild.GetText());
                treeNode.Nodes.Add(content);
            }

            //the sibling nodes
            if (siblingRequired)
            {
                INode sibling = htmlNode.NextSibling;
                while (sibling != null)
                {
                    this.RecursionHtmlNode(treeNode, sibling, false);
                    sibling = sibling.NextSibling;
                }
            }
        }
        private void AddUrl()
        {
            CBUrl.Items.Add("http://www.hao123.com");
            CBUrl.Items.Add("http://www.sina.com");
            CBUrl.Items.Add("http://www.heuet.edu.cn");
        }

    }
}


小结:
实现取来很容易,结合Winista.Htmlparser源码很快就可以实现想要的效果。简单介绍了两种解析Html的方法,大家有什么其他好的方法还望指教。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏8 转播转播
回复 论坛版权

使用道具 举报

沙发
jefferic 发表于 2014-9-26 14:41:39 | 只看该作者
本帖最后由 jefferic 于 2014-9-26 20:43 编辑

使用 HTML Agility Pack 搭配 ScrapySharp 会更便捷
类似jquery筛选器的写法
[C#] 纯文本查看 复制代码
Uri uri = new Uri("http://www.baidu.com");
ScrapingBrowser browser1 = new ScrapingBrowser();
String htmlStr = browser1.DownloadString(uri);
HtmlAgilityPack.HtmlDocument htmlDocument = new HtmlAgilityPack.HtmlDocument();
htmlDocument.LoadHtml(htmlStr);

HtmlNode html = htmlDocument.DocumentNode;
IEnumerable<HtmlNode> nodes = html.CssSelect("div");  //all div elements
//nodes = html.CssSelect("div.content"); //all div elements with css class ‘content’
//nodes = html.CssSelect("div.widget.monthlist"); //all div elements with the both css class
//nodes = html.CssSelect("#postPaging"); //all HTML elements with the id postPaging
//nodes = html.CssSelect("div#postPaging.testClass"); // all HTML elements with the id postPaging and css class testClass 
//nodes = html.CssSelect("div.content > p.para"); //p elements who are direct children of div elements with css class ‘content’ 
//nodes = html.CssSelect("input[type=text].login"); // textbox with css class login 
//nodes = html.CssSelect("p.para").CssSelectAncestors("div.content > div.widget");


dll.zip

71.05 KB, 下载次数: 46, 下载积分: 金钱 -1

Dll:HtmlAgilityPack.dll + ScrapySharp.dll

评分

参与人数 1金钱 +1 收起 理由
乔克斯 + 1 很给力!

查看全部评分

您需要登录后才可以回帖 登录 | 加入CSkin博客

本版积分规则

QQ|申请友链|小黑屋|手机版|Archiver|CSkin ( 粤ICP备13070794号

Powered by Discuz! X3.2  © 2001-2013 Comsenz Inc.  Designed by ARTERY.cn
GMT+8, 2024-11-24 14:15, Processed in 0.536346 second(s), 34 queries , Gzip On.

快速回复 返回顶部 返回列表