• 网页采集(通过HtmlAgilityPack+XPath)


    有HtmlAgilityPack这个类库可以更方便地对HTML内容进行分析和提取。因此今天特别学习和实践了一下HtmlAgilityPack和XPath,并作下笔记。

    1.下载HtmlAgilityPack.dll并将其添加引用到项目中,然后在代码中声明引用。

    下载地址:http://www.codeplex.com/htmlagilitypack

    引用:

    using HtmlAgilityPack;

    2.下载获取HTML页面的步骤和我上篇文章里介绍的差不多,都是先用WebClient或者WebRequest类来下载HTML页面然后处理成字符串。

    3.与上次不同的是,这里分析和抓取HTML节点中的数据不再是之前那种STRING字符串操作的方式,而是封装成一个HtmlDocument对象,通过HtmlDocument中的方法来索引你需要抓取HTML节点,进而取出节点中的值。

    4.若需要抓取的节点有ID,类似“<div id='post_list'>value</div>”这种,那很简单只需调用GetElementbyId方法根据节点ID即可获取所需节点。从而通过HtmlNode中的InnerText或Attribute属性来获取你想要的值。

    CODE:

    复制代码

    //实例化HtmlAgilityPack.HtmlDocument对象
    HtmlDocument doc = new HtmlDocument();
    //载入HTML
    doc.LoadHtml(mainData);
    //根据HTML节点NODE的ID获取节点
    HtmlNode navNode = doc.GetElementbyId("post_list");

    复制代码

    5.但很多情况下HTML节点是没有ID的,那就需要通过XPATH语言来查找匹配所需节点(XPath教程)。以抓取博客园首页文章为例,通过查看博客园HTML可以发现博客园首页里的文章列表都是放在一个ID为"post_list"的"<div>"节点中的。

    这样的话就可以通过调用GetElementbyId方法来定位到这个节点了。

    6.在获取到"post_list"节点后,接下来就可以调用SelectSingleNode方法通过XPATH表达式来索引出需要抓取的节点,从而抓取到文章的标题和链接地址。

    (PS:在博客园首页"post_list"节点里,平均每4个DIV就是一篇新的文章可以利用这一规律遍历出首页所有文章)

    CODE:

    复制代码

    //实例化HtmlAgilityPack.HtmlDocument对象
    HtmlDocument doc = new HtmlDocument();
    //载入HTML
    doc.LoadHtml(mainData);
    //根据HTML节点NODE的ID获取节点
    HtmlNode navNode = doc.GetElementbyId("post_list");
    //根据XPATH来索引节点

    //div[2]表示文章链接a位于post_list里面第3个div节点中
    HtmlNode navNode2 = navNode.SelectSingleNode("//div[2]/h3/a");
    //获取文章链接地址
    string articleTitle = navNode2.Attributes["href"].Value.ToString();
    //获取文章标题
    string articleName = navNode2.InnerText;

    复制代码

    对比一下之前使用string截取字符串的方法:

    复制代码

    //以"<a class="titlelnk" href=""作为抓取点开始采集
    mainData=mainData.Substring(mainData.IndexOf("<a class="titlelnk" href="") + 26);
    //获取文章页面的链接地址
    string articleAddr = mainData.Substring(0,mainData.IndexOf("""));
    //获取文章标题
    string articleTitle = mainData.Substring(mainData.IndexOf("target="_blank">") + 16,
                                                   mainData.IndexOf("</a>") - mainData.IndexOf("target="_blank">") - 16);

    复制代码

    可见与之前相比,使用HtmlAgilityPack.HtmlDocument类来实现前台HTML的分析和采集在页面编码和数据分析上面处理更加合理、优化,代码也更加简洁。

     

     

     

    xpath路径表达式笔记

    作者: 阮一峰

    日期: 2009年7月 6日

    简单说,xpath就是选择XML文件中节点的方法。

    所谓节点(node),就是XML文件的最小构成单位,一共分成7种。

    - element(元素节点)
    - attribute(属性节点)
    - text (文本节点)
    - namespace (名称空间节点)
    - processing-instruction (处理命令节点)
    - comment (注释节点)
    - root (根节点)

    xpath可以用来选择这7种节点。不过,下面的笔记只涉及最常用的第一种element(元素节点),因此可以将下文中的节点和元素视为同义词。

    一、xpath表达式的基本格式

    xpath通过“路径表达式”(Path Expression)来选择节点。在形式上,“路径表达式”与传统的文件系统非常类似。

    # 斜杠(/)作为路径内部的分割符。
    # 同一个节点有绝对路径和相对路径两种写法。
    # 绝对路径(absolute path)必须用“/”起首,后面紧跟根节点,比如/step/step/...。
    # 相对路径(relative path)则是除了绝对路径以外的其他写法,比如 step/step,也就是不使用“/”起首。
    # “.”表示当前节点。
    # “..”表示当前节点的父节点

    二、选择节点的基本规则

    - nodename(节点名称):表示选择该节点的所有子节点
    - “/”:表示选择根节点
    - “//”:表示选择任意位置的某个节点
    - “@”: 表示选择某个属性

    三、选择节点的实例

    先看一个XML实例文档。

    <?xml version="1.0" encoding="ISO-8859-1"?>

    <bookstore>

      <book>
        <title lang="eng">Harry Potter</title>
        <price>29.99</price>
      </book>

      <book>
        <title lang="eng">Learning XML</title>
        <price>39.95</price>
      </book>

    </bookstore>

    [例1]

    bookstore :选取 bookstore 元素的所有子节点。

    [例2]

    /bookstore :选取根节点bookstore,这是绝对路径写法。

    [例3]

    bookstore/book :选取所有属于 bookstore 的子元素的 book元素,这是相对路径写法。

    [例4]

    //book :选择所有 book 子元素,而不管它们在文档中的位置。

    [例5]

    bookstore//book :选择所有属于 bookstore 元素的后代的 book 元素,而不管它们位于 bookstore 之下的什么位置。

    [例6]

    //@lang :选取所有名为 lang 的属性。

    四、xpath的谓语条件(Predicate)

    所谓“谓语条件”,就是对路径表达式的附加条件。

    所有的条件,都写在方括号“[]”中,表示对节点进行进一步的筛选。

    [例7]

    /bookstore/book[1] :表示选择bookstore的第一个book子元素。

    [例8]

    /bookstore/book[last()] :表示选择bookstore的最后一个book子元素。

    [例9]

    /bookstore/book[last()-1] :表示选择bookstore的倒数第二个book子元素。

    [例10]

    /bookstore/book[position()<3] :表示选择bookstore的前两个book子元素。

    [例11]
    //title[@lang] :表示选择所有具有lang属性的title节点。

    [例12]

    //title[@lang='eng'] :表示选择所有lang属性的值等于“eng”的title节点。

    [例13]

    /bookstore/book[price] :表示选择bookstore的book子元素,且被选中的book元素必须带有price子元素。

    [例14]
    /bookstore/book[price>35.00] :表示选择bookstore的book子元素,且被选中的book元素的price子元素值必须大于35。

    [例15]

    /bookstore/book[price>35.00]/title :表示在例14结果集中,选择title子元素。

    [例16]

    /bookstore/book/price[.>35.00] :表示选择值大于35的“/bookstore/book”的price子元素。

    五、通配符

    # “*”表示匹配任何元素节点。

    # “@*”表示匹配任何属性值。
    # node()表示匹配任何类型的节点。

    [例17]

    //* :选择文档中的所有元素节点。

    [例18]

    /*/* :表示选择所有第二层的元素节点。
    [例19]

    /bookstore/* :表示选择bookstore的所有元素子节点。
    [例20]

    //title[@*] :表示选择所有带有属性的title元素。

    六、选择多个路径

    用“|”选择多个并列的路径。

    [例21]

    //book/title | //book/price :表示同时选择book元素的title子元素和price子元素。

    【相关文章】

    * CSS选择器笔记

    (完)

    文档信息
  • 相关阅读:
    _DataStructure_C_Impl:稀疏矩阵十字链表存储
    _DataStructure_C_Impl:稀疏矩阵三元组
    _DataStructure_C_Impl:Array
    _DataStructure_C_Impl:KMP模式匹配
    _DataStructure_C_Impl:链串
    _DataStructure_C_Impl:堆串
    _DataStructure_C_Impl:顺序串
    _DataStructure_C_Impl:双端队列
    _DataStructure_C_Impl:链式队列
    _DataStructure_C_Impl:只有队尾指针的链式循环队列
  • 原文地址:https://www.cnblogs.com/suizhikuo/p/3452766.html
Copyright © 2020-2023  润新知