zoukankan      html  css  js  c++  java
  • 基于HSharp 使用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。

  • 相关阅读:
    数据挖掘实践(23):实战-- 建筑能源得分预测报告(一)
    返回闭包
    函数指针
    Rust 中的 Closure
    Moves, copies and clones in Rust
    Rust的闭包类型(Fn, FnMut, FnOne的区别)
    Clone VS Copy
    rust socket
    A simple UNIX socket listener in Rust
    【firecracker】系统启动与epoll事件循环
  • 原文地址:https://www.cnblogs.com/mma2017/p/MMA.html
Copyright © 2011-2022 走看看