使用C#反序列化HTML并获取HTML中的特定内容

最近有一个项目,要把别人网站上一些数据扒下来。(其实就是一个查课表)

通过HTTP GET得到网页HTML源码倒是不难……难点在于这个网页内容非常混乱,有的时候格式都会发生变化。

我最开始用Python做,可以直接把网页建立Dom。最简单的方法还是用jQuery,轻轻松松就可以把网站上的特定内容处理掉。

但这个项目是用ASP.Net结合C#语言做的。我找了很多方案,都很费劲。

下面这几个方案都是挺费劲的示例……告诉大家不要学啊

方案一:根据网站建立对应的类。然后过XML反序列化

这个方法很作死,首先建立对应的类就够建一整天的。坑爹在C#是强类型的语言。没法直接对着这个对象操作。只能先建立类。

好像有一些库可以让这个过程稍微舒服点。比如xpath。

方案二:自己用String的substring和正则表达式这些处理HTML

这样写确实可行。但我写的正则表达式和Substring实在太难维护了。代码丑陋不堪,效率低下,还经常神之Exception。

一个比较高效的方案

最后我还是找到了一个比较可行的方法。大概方法是用到了一个叫做HSharp的库。用来以一种弱类型语言的处理方式来应用在C#,处理HTML。

HSharp在Github上的主页:https://github.com/Obisoft2017/HSharp

看上去还是蛮不错的。开源免费,源码也很短。

类似的库也有HTMLagility。那个要复杂不少。C#自带一个Document,那个比较官方,但依赖WebBrowser对象,而且……速度慢的一笔。

我主要用它进行HTML“反序列化”了。

(严格意义上它的工作方式不是强类型的反序列化,而是把各个标签都塞进了字典里。起码这样还是可以查询了)

首先在VS的PM里执行命令:

1 Install-Package Obisoft.HSharp 

然后直接使用它的HtmlConvert.DeserializeHtml方法来反序列化HTML。官网的示例都挺清楚。

using Obisoft.HSharp.Models;
using System;

namespace Obisoft.HSharp
{
    class Example
    {
        public static void Main(string[] args)
        {
            var NewDocument = HtmlConvert.DeserializeHtml($@"
<html>
<head>
    <meta charset={"\"utf-8\""}>
    <meta name={"\"viewport\""}>
    <title>Example</title>
</head>
<body>
    Some Text
    <table>
        <tr>OneLine</tr>
        <tr>TwoLines</tr>
        <tr>ThreeLines</tr>
    </table>
    Other Text
</body>
</html>");
            Console.WriteLine(NewDocument["html"]["head"]["meta",0].Properties["charset"]);
            Console.WriteLine(NewDocument["html"]["head"]["meta",1].Properties["name"]);
            foreach (var Line in NewDocument["html"]["body"]["table"])
            {
                Console.WriteLine(Line.Son);
            }
    }
}

在上面代码中,反序列化了HTML,并对这段HTML的两个meta的charset和name属性值进行了打印。然后遍历了table的所有元素,打印了元素的内容。

输出结果:

utf-8
viewport
OneLine
TwoLines
ThreeLines

回到项目

我试了试反序列化一个真实的网站。这里拿Obisoft的主页举例子吧。他们的网站属于很复杂很复杂的了。

这里假想要获取他们网站中随意一个数值。这里我获取一下他页面上一个普通数字:

仔细检查他们代码后,这个数字出现在第5个section标签下面N重div的迭代里的一个span里。编写代码:

            var WebSiteResult = HtmlConvert.DeserializeHtml(new Uri("http://www.obisoft.com.cn/"));
            Console.WriteLine(NeuAaoResult["html"]["body"]["section", 5]["div"]["div"]["div"]["div"]["div"]["div", 2]["span"].Son);

果然,程序成功输出了10. 速度还是挺快的。

考虑到这个库确实挺好用而且足够强大。准备研究研究,去写一些接口。它好像还有挺多方法,应该也可以构建HTML。

时间: 2024-12-16 21:23:44

使用C#反序列化HTML并获取HTML中的特定内容的相关文章

Android中如何解析网页,获取网页中的元素内容

问题: 由于android的WebView等相关类没有提供解析html网页内容的接口,我们想要获取网页的内容并解析出我们想要的元素内容,用android的固有API是没办法了. 这里我提供两种解析html思路:第一种,使用第三方解析html库:第二种,使用JAVA与JS回调,通过JS解析html. 之前研究了一下htmlparser这个开源库,但是发现和android提供的库有冲突,但其在纯java应用程序下是可行的. htmlparser下载地址:http://htmlparser.sourc

小胖说事36----iOS通过js 获取webview中的html内容

1)设置UIWebView delegate 2)在 - (void)webViewDidFinishLoad:(UIWebView *)webView { }中 执行如下代码 : NSString *jsToGetHTMLSource = @"document.getElementsByTagName_r('html')[0].innerHTML"; NSString *HTMLSource = [self.webView stringByEvaluatingJavaScriptFr

SqlSever基础 MAX 查看一个表中具有特定内容的行中某一列的最大值

镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ 1 table 2 code 1 --创建一个数据库 2 create database helloworld1 3 4 use master 5 drop database helloworld1 6 7 --用helloworld1这个数据库 8 use helloworld1 9 10 --

SqlSever基础 MIN 查看一个表中具有特定内容的行中某一列的最小值

镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ 1 table 2 code 1 --创建一个数据库 2 create database helloworld1 3 4 use master 5 drop database helloworld1 6 7 --用helloworld1这个数据库 8 use helloworld1 9 10 --

使用selenium的方式获取网页中图片的链接和网页的链接,来判断是否是死链(二)

上一篇使用Java正则表达式来判断和获取图片的链接以及跳转的网址,这篇使用selenium的自带的API(getAttribute)来获取网页中指定的内容 实现内容:获取下面所有图片的链接地址以及跳转地址,使用get请求判断是否有死链 页面内容如图: 页面的源码,需要获取页面的href后的地址,以及src后的地址,: 代码实现可以看出图片都在一个div中,实现的思想为:获取控件集合,在获取每一个li下的元素,在获取,在取出数据下的属性名的属性值 public void new_classific

使用String获取java异常中的异常内容

因为Exception类是所有异常的父类,所以使用它可以读取到java产生的所有异常:     /**      * @category 获取try-catch中的异常内容      * @param e Exception      * @return  异常内容      */     public static String getException(Exception e) {         ByteArrayOutputStream out = new ByteArrayOutput

获取字符串中某一个字段的数据,GetValueFromStr

gps数据格式为:$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A* /********************************************************************** *版权所有 (C)2015, Wuyq. * *文件名称: GetValueFromStr.c *内容摘要:用于演示从gps数据字符串中获取相应的内容 *其它说明:无 *当前版本: V1.0 *作

设置和获取Android中各种音量

通过程序获取android系统手机的铃声和音量.同样,设置铃声和音量的方法也很简单!AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);//通话音量      int max = am.getStreamMaxVolume( AudioManager.STREAM_VOICE_CALL );      int current = am.getStreamVolume( AudioManager.STRE

如何获取url中的参数并传递给iframe中的报表

在使用报表软件时,用户系统左边一般有目录树,点击报表节点就会在右侧网页的iframe中显示出报表,同时点击的时候也会传递一些参数给网页,比如时间和用户信息等.如何使网页中的报表能够获取到传递过来的参数呢?以下用报表软件FineReport简单介绍一些. 具体实现过程 将报表生成页面时,给网页添加onload事件,首先获取url中的参数,然后嫁接到iframe的src上,或者通过获得的参数拼接处完整的报表url赋给iframe的src. <html> <head> <title