无法弄清楚如何使用Html Agility Pack阅读网页的特定部分

时间:2012-01-28 16:52:38

标签: .net html-parsing web-crawler html-agility-pack

我正在尝试阅读具有相同价值的网站(www.joindota.com)的特定部分。我将用网站上的例子解释我想做什么:

以下HTML是我想从网站上阅读的内容的一部分:

<div id="matchticker_coverage_content_1761" style="display:none;">
    <a href="http://www.joindota.com/en/matches/16102-team-dignitas-dota-vs-sk-gaming-dota" class="item">
        <div class="sub" style="width: 18px; text-align: left;"><img src="http://www.gs-media.de/img/themes/joindota/ticker_9.png" border="0" alt="" /></div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/ro.gif" border="0" alt="ro" title="Romania" /> Digni</div>
        <div class="sub" style="width: 20px;">vs.</div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/dk.gif" border="0" alt="dk" title="Denmark" /> SK</div>
        <div class="sub" style="float: right; text-align: right;">
            <span title="Sun, 29.01.2012, 16:00 CET">tomorrow</span>
        </div>
        <div class="cl"></div>
    </a>
    <a href="http://www.joindota.com/en/matches/16101-world-elite-vs-mineski" class="item">
        <div class="sub" style="width: 18px; text-align: left;"><img src="http://www.gs-media.de/img/themes/joindota/ticker_9.png" border="0" alt="" /></div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/cn.gif" border="0" alt="cn" title="China" /> WE</div>
        <div class="sub" style="width: 20px;">vs.</div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/ph.gif" border="0" alt="ph" title="Philippines" /> Mski</div>
        <div class="sub" style="float: right; text-align: right;">
            <span title="Sun, 29.01.2012, 14:00 CET">tomorrow</span>
        </div>
        <div class="cl"></div>
    </a>
    ....
</div>

我想阅读<div id="matchticker_coverage_content_1761" >

中的所有内容

我只需要阅读我在那里提供的<div>标签内的所有值。例如,它会输出:

  • Digni vs. SK
  • WS vs. Mski
  • EG vs. Fnatic

该HTML中的所有div值都是相同的,我只需要知道如何在页面中专门“选择”<div id="matchticker_coverage_content_1761" >,并读取该div中的所有其他div,它们就是:

<div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/ro.gif" border="0" alt="ro" title="Romania" /> Digni</div>
div class="sub" style="width: 20px;">vs.</div>
                        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/dk.gif" border="0" alt="dk" title="Denmark" /> SK</div>

所有<div>值都是相同的,我感兴趣的是其中的文本,例如Digni和vs.与SK,例如。

我只需要阅读<div id="matchticker_coverage_content_1761" > </div>

中的所有值

原因是因为该网站有很多这些,但我只需要阅读一个特定的部分。这是同一页面上相同的另一部分,只有所有其他div所在的div不同。

示例:

<div id="matchticker_coverage_content_1596" style="display:none;">
    <a href="http://www.joindota.com/en/matches/16564-westernwolves-vs-panzer" class="item">
        <div class="sub" style="width: 18px; text-align: left;"><img src="http://www.gs-media.de/img/themes/joindota/ticker_9.png" border="0" alt="" /></div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/fr.gif" border="0" alt="fr" title="France" /> Wolves</div>
        <div class="sub" style="width: 20px;">vs.</div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/de.gif" border="0" alt="de" title="Germany" /> PANZER</div>
        <div class="sub" style="float: right; text-align: right;">
            <span title="Tue, 31.01.2012, 21:00 CET">31.01.</span>
        </div>
        <div class="cl"></div>
    </a>
    <a href="http://www.joindota.com/en/matches/16626-panzer-vs-just-4-the-tournament" class="item">
        <div class="sub" style="width: 18px; text-align: left;"><img src="http://www.gs-media.de/img/themes/joindota/ticker_9.png" border="0" alt="" /></div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/de.gif" border="0" alt="de" title="Germany" /> PANZER</div>
        <div class="sub" style="width: 20px;">vs.</div>
        <div class="sub" style="width: 103px;"><img src="http://www.gs-media.de/img/flags/de.gif" border="0" alt="de" title="Germany" /> J4T</div>
        <div class="sub" style="float: right; text-align: right;">
            <span title="Sun, 29.01.2012, 19:00 CET">tomorrow</span>
        </div>
        <div class="cl"></div>
    </a>
    ....
</div>

请注意所有<div>在开头<div>内的完全相同? <div>所有<div>所在的<div id="matchticker_coverage_content_1596" style="display:none;"> <div id="matchticker_coverage_content_1761" style="display:none;"><div>

页面的其他部分不同

我的最终问题是,如何选择包含另一个<div>的开头{{1}},并阅读我之前提到的具体内容?

1 个答案:

答案 0 :(得分:6)

对于特定数据点(与谷歌这样的一般相关性搜索相对),网页抓取/抓取,无论是否为semantic HTML,都是艺术而非科学。

您经常需要专门针对每个网站定制您的抓取工具,以便为了获取数据而获取相同来自每个站点的数据点,但每个站点以不同的方式表示

考虑到这一点,通常会发现一种模式,可以让您在某个站点内一致地识别数据点。

我冒昧chopping down your HTML samples, as well as formatting it来展示标签的层次结构;这不会影响页面的解析或显示方式,因为它是关于 in 标签的内容,而不是它们之外的内容。

通过重新排列,模式应该出现。

让我们首先识别容器<div>元素。唯一标识这些<div>元素的内容是id属性,它们都具有以下形式:

<div id="matchticker_coverage_content_**some number**" style="display:none;">

(注意:您可以查找具有<div>属性的任何style="display:none;"元素,但非常脆弱,并且不是唯一标识容器,该属性可以任何地方其他地方应用 no 语义含义)

不幸的是,id属性是一个问题,因为它似乎是一个数字,它是某种类型的id,并且在整个页面中不一致。如果你知道容器的id,你可以在Html Agility Pack中使用以下表达式:

\\div[id='matchticker_coverage_content_1596']

但我想你知道它。

您真正想要的是能够查找<div>属性id开始的所有matchticker_coverage_content_个元素。

Html Agility Pack不支持这种选择器语法。但是,jQuery does具有以下语法:

div[id^='matchticker_coverage_content_']

更好的是fizzler project support this selector。所以在这种情况下,我会使用fizzler来获取那个容器。

一旦你拥有容器,就需要查看它的子元素。同样,在编辑之后,显而易见的是,您正在寻找的每个匹配(具有相关的<div>元素)都包含在内部锚(即<a>)元素中。因此,一旦拥有容器<div>,您只需使用以下语法选择出锚元素的所有子元素:

/a

(如果使用fizzler,则只是容器节点上a的选择器)

一旦你拥有了它,你真的不需要检测vs.,你可以假设它在那里,你真的想要检测球员

这些更难,因为标签,类或ID没有任何语义。但是,有一个鉴别器。看一下播放器标签(我把它们中的一部分切掉了以便更清楚):

<div class="sub">
    <img src="http://www.gs-media.de/img/themes/joindota/ticker_9.png" 
        border="0" alt="" /></div>

<div class="sub">
    <img src="http://www.gs-media.de/img/flags/ro.gif" 
        border="0" alt="ro" title="Romania" /> Digni</div>

<div class="sub" style="width: 20px;">vs.</div>

<div class="sub" style="width: 103px;">
    <img src="http://www.gs-media.de/img/flags/dk.gif" 
        border="0" alt="dk" title="Denmark" /> SK</div>

您可以看到玩家所在的<div>标签中有<img>个标记,其中alt属性不为空(这很重要,因为您不希望处理第一个 <div>元素。

识别出这些<img>标记后,您只需获取父节点(<div>)并从节点中获取文本即可获取播放器。第一个是第一个玩家方,第二个是第二个玩家方。

另一种方法是识别包含“vs.”的<div>元素在其中的文字,然后看看兄弟姐妹,前一个是第一个玩家,而后一个是第二个玩家。

注意,最后一步是非常脆弱,并且总是是脆弱的,因为标签中没有语义指示符。您基本上依赖于实现细节(因为您别无选择)。

强烈建议你在某些页面上有测试用例来解析内容并验证数据;这样,如果页面结构发生变化,您将立即知道,并可以相应地更改您的抓取逻辑。