HTML XPath:提取混合了多个级别和复杂标签的文本?

时间:2017-03-01 02:41:30

标签: html xpath scrapy html-content-extraction

之前的相关问题:

HTML XPath: Extracting text mixed in with multiple tags?

HTML XPath: Selectively avoiding tags when extracting text

//抱歉我的英语不好

我是编写网络抓取工具的初学者,我试图通过xpath从网页(中文)中提取主要内容(虽然我已经了解到有传统和机器学习方法的算法提取Web主要内容),我在编写xpath规则时非常初学。

我面对的网页包含复杂标签中的文字,我总结如下,其中字符(例如A,A2)仅指文字,' ...&#39 ;意味着更多的标签甚至嵌套没有文字。我想得到" AA2BB2CDEFGHIJKLMNOP"

...
<div id="artibody" class="art_context">
    <div align="center">...</div>
    <div align="center"><font>A</font>A2</div>
    <div align="left"><br><br><strong>B</strong>B2</div>
    <div align="left">
        <p>C<a>D</a>E</p>
        <p>F<a>G</a>H<a>I</a>J</p>K
    </div>
    <div align="center">...</div>
    <div align="center"><font>L</font></div>
    <p>M</p><!--M contains only text luckly-->
    <p>N</p>
    <p>O</p>
    <p>P<span>...</span><div class="shareBox">...</div>
    </p>
    <span id="arctTailMark"></span>
    <script>
        var page_navigation = document.getElementById('page_navigation');
        ...
    </script>
    <div style="padding:10px 0 30px 0">...</div>
</div>

感谢以前的问题,我写了一条规则

  

&#39;串(// DIV [@class = \&#34; art_context \&#34;])&#39;

我得到的所有内容都是我想要的纯文本,但没有标签,但<script>中的js代码也被提取出来。我尝试了以下内容,但似乎没有用。还有js代码。< / p>

  

&#39; string(// div [@class = \&#34; art_context \&#34;而不是(self :: script)])&#39;

以下是&#34; \ r \ n&#34;仅

  

&#39; // DIV [@class = \&#34; art_context \&#34;而不是(self :: script)] / text()&#39;

以下是我的问题:

1.如何编写xpath规则以满足我的需要:在div [@id =&#34; artibody&#34;]中提取内容,<script>

中的代码除外

2.问题1的规则简单而有力吗?也许我会用div [@id =&#34; artibody&#34;]来满足更多页面,但是后代节点却完全不同。

3.对我的任务有进一步的建议吗?从一个网站提取Web内容,但主要内容位于<div>中,具有不同的id,class和后代节点结构。我在我的笔记本电脑上运行蜘蛛(Intel corei5 3225,8G RAM),而使用机器学习算法可能会显着降低爬行速度。同时编写许多xpath规则似乎很烦人。

如果你能就这个问题(以及我的英语)给我任何建议,我会很感激。

1 个答案:

答案 0 :(得分:1)

要获取除script内容之外的所有后代文本节点,您可以使用:

//div[@class="art_context"]//*[not(self::script)]/text()

使用自然语言:“从不是div[@class="art_context"]元素的所有script元素的后代中获取所有文本节点。”

//需要div[@class="art_context"]来选择后代,而不仅仅是孩子。

相比之下,问题中的//div[@class="art_context" and not(self::script)]/text()表达式显示了“div[@class="art_context"]元素的所有script元素的所有文本节点。 “

因此,问题中表达式中的and not(self::script)部分是多余的,因为所有表达式都在做,只是选择//div[@class="art_context"],然后/text()部分只选择文本-node直接指向div的子节点,这只是换行符。

此外,如果不是使用XPath来获取文本节点集,而是希望使用XPath将结果作为单个字符串获取,则可以使用函数string-join(…)normalize-space(…)

normalize-space(string-join(//div[@class="art_context"]//*[not(self::script)]/text(), ""))