XPath教程

在本教程中,将对`XPath <https://en.wikipedia.org/wiki/XPath>`_进行简要介绍,这是一种查询语言,在cllibre中可用于选择`HTML<https://en.wikipedia.org/wiki/HTML>`_文档的任意部分。 XPath是一种广泛使用的标准,并且对其进行谷歌搜索将产生大量信息。 但是,本教程重点介绍如何将XPath用于与电子书相关的任务,例如在非结构化HTML文档中查找章节标题。

按标记名选取

最简单的选择形式是按名称选择 标记。例如,假设您要选择文档中的所有``<h2>``标签。针对此的XPath查询简单地为:

//h:h2        (Selects all <h2> tags)

前缀`//` 表示“在文档的任何级别搜索”。现在假设您要搜索``<a>``标记内的``<span>`` 标记。这可以通过以下方式实现:

//h:a/h:span    (Selects <span> tags inside <a> tags)

如果要搜索文档中特定级别的 标记,请更改前缀:

/h:body/h:div/h:p (Selects <p> tags that are children of <div> tags that are
             children of the <body> tag)

这将仅与"样本_电子书"中的“<p>A非常简短的电子书来演示XPath。</p>的使用”匹配,而不与其他任何“<p>” 标记匹配。上面示例中的“h:”前缀需要匹配XHTML标签。这是因为在内部,Calibre将所有内容表示为XHTML。在XHTML标签中,有一个*命名空间*,而且“h:”是HTML标签的命名空间前缀。

现在假设您要同时选择“<h1>”和“<h2>” 标记。为此,我们需要一个称为*谓词*的XPath结构。A:“谓词”只是一个用于选择标签的测试。测试可以是任意强大的,随着本教程的进行,您将看到更强大的示例。谓词是通过将测试表达式括在方括号中创建的:

//*[name()='h1' or name()='h2']

此XPath表达式中有几个新功能。第一个是通配符“*”的使用。它的意思是*匹配任何标签*。现在看一下测试表达式“name()='h1'或name()='h2'”。“名称()”是一个*内置函数*的例子。 它只是评估标签的名称。 因此通过使用它,我们可以选择名称为“h1”或“h2”的标签。注意:“名称()”函数忽略命名空间,因此不需要“h:”前缀。XPath有几个有用的内置函数。本教程还将介绍更多内容。

按属性选择

要根据属性选择标签,需要使用谓词:

//*[@style]              (Select all tags that have a style attribute)
//*[@class="chapter"]    (Select all tags that have class="chapter")
//h:h1[@class="bookTitle"] (Select all h1 tags that have class="bookTitle")

这里的“@”操作符指的是标签的属性。 您可以使用某些“XPath内置函数”_对属性值执行更复杂的匹配。

备注

When XPath expressions are used for conversion options such as chapter detection or the start reading at position, they are evaluated against the input document, before calibre flattens the CSS. CSS flattening rewrites class names, so the class names you see in the converted output (things like calibre1) do not exist yet when your expression runs. Copy class names from the input document, not from the converted book. If in doubt, match on tag names and text content instead, as these are not changed by the conversion.

按标签内容选择

使用XPath,您甚至可以根据标签中包含的文本选择标签。 最好的方法是通过内置函数“re:test()”使用*正则表达式*的功能:

//h:h2[re:test(., 'chapter|section', 'i')] (Selects <h2> tags that contain the words chapter or
                                          section)

这里的``.``运算符指代标签的内容,就像``@``运算符指代标签的属性一样。

电子书样本

<html>
    <head>
        <title>A very short e-book</title>
        <meta name="charset" value="utf-8" />
    </head>
    <body>
        <h1 class="bookTitle">A very short e-book</h1>
        <p style="text-align:right">Written by Kovid Goyal</p>
        <div class="introduction">
            <p>A very short e-book to demonstrate the use of XPath.</p>
        </div>

        <h2 class="chapter">Chapter One</h2>
        <p>This is a truly fascinating chapter.</p>

        <h2 class="chapter">Chapter Two</h2>
        <p>A worthy continuation of a fine tradition.</p>
    </body>
</html>

XPath内置函数

名称()

当前标记的名称。

包含()

如果s1包含s2,contains(s1, s2) 返回 true

re:test()

如果字符串`src`与正则表达式`pattern`匹配,则``re:test(src, pattern, flags)``返回true。一个特别有用的标志是``i``,它使匹配不区分大小写。有关正则表达式语法的入门知识,请参见“正则表达式语法<https://docs.python.org/library/re.html>”_。