如何在 stormcrawler 的 parsefilter.json 中添加更多的 XPATH

How to add more XPATH in parsefilter.json in stormcrawler

我正在使用 stormcrawler (v 1.16) 和 Elasticsearch(v 7.5.0) 从大约 5k 个新闻网站中提取数据。我在 parsefilter.json 中添加了一些用于提取作者姓名的 XPATH 模式。 Parsefilter.json如下图:

{

  "com.digitalpebble.stormcrawler.parse.ParseFilters": [
    {
      "class": "com.digitalpebble.stormcrawler.parse.filter.XPathFilter",
      "name": "XPathFilter",
      "params": {
        "canonical": "//*[@rel=\"canonical\"]/@href",
        "parse.description": [
            "//*[@name=\"description\"]/@content",
            "//*[@name=\"Description\"]/@content"
         ],
        "parse.title": [
            "//TITLE",
            "//META[@name=\"title\"]/@content"
         ],
         "parse.keywords": "//META[@name=\"keywords\"]/@content",
        "parse.datePublished": "//META[@itemprop=\"datePublished\"]/@content",
        "parse.author":[
        "//META[@itemprop=\"author\"]/@content",
        "//input[@id=\"authorname\"]/@value",
        "//META[@name=\"article:author\"]/@content",
        "//META[@name=\"author\"]/@content",
        "//META[@name=\"byline\"]/@content",
        "//META[@name=\"dc.creator\"]/@content",
        "//META[@name=\"byl\"]/@content",
        "//META[@itemprop=\"authorname\"]/@content",
        "//META[@itemprop=\"article:author\"]/@content",
        "//META[@itemprop=\"byline\"]/@content",
        "//META[@itemprop=\"dc.creator\"]/@content",
        "//META[@rel=\"authorname\"]/@content",
        "//META[@rel=\"article:author\"]/@content",
        "//META[@rel=\"byline\"]/@content",
        "//META[@rel=\"dc.creator\"]/@content",
        "//META[@rel=\"author\"]/@content",
        "//META[@id=\"authorname\"]/@content",
        "//META[@id=\"byline\"]/@content",
        "//META[@id=\"dc.creator\"]/@content",
        "//META[@id=\"author\"]/@content",
        "//META[@class=\"authorname\"]/@content",
        "//META[@class=\"article:author\"]/@content",
        "//META[@class=\"byline\"]/@content",
        "//META[@class=\"dc.creator\"]/@content",
        "//META[@class=\"author\"]/@content"
]



}
    },

爬虫里我也做了修改-conf.yaml如下图

    indexer.md.mapping:
    - parse.author=author
    metadata.persist:
    - author

我面临的问题是:我只得到“parse.author”的第一个模式(即“//META[@itemprop="author"]/@content”)的结果。我应该做哪些更改才能将所有模式作为输入。

What changes I should do so that all patterns can be taken as input.

我将此解读为 “我如何制作一个 XPath 表达式来尝试作者在文档中出现的所有不同方式?”

最简单的方法:使用 XPath 联合运算符将您已有的所有表达式合并为一个表达式 |:

input[...]|meta[...]|meta[...]|meta[...]

并且因为这个可能选择了多个节点,我们可以明确声明我们只关心第一个匹配项:

(input[...]|meta[...]|meta[...]|meta[...])[1]

这可能有效,但会很长且难以阅读。 XPath 可以做得更好。

你的表达式都非常重复,这是减少表达式大小的一个很好的起点。例如,这两个是相同的,除了属性值:

//meta[@class='author']/@content|//meta[@class='authorname']/@content

我们可以使用 or 并且它已经变短了:

//meta[@class='author' or @class='authorname']/@content

但是当你有 5 或 6 个潜在值时,它仍然很长。下次尝试,属性的谓词:

//meta[@class[.='author' or .='authorname']]/@content

稍微短一点,因为我们不需要一直输入 @class。但仍然很长,有 5 或 6 个潜在值。值列表和子字符串搜索怎么样(我使用 / 作为分隔符):

//meta[contains(
    '/author/authorname/',
    concat('/', @class, '/')
)]/@content

现在我们可以轻松扩展有效值列表,甚至可以查看不同的属性:

//meta[contains(
    '/author/authorname/article:author/',
    concat('/', @class|@id , '/')
)]/@content

并且由于我们要在多个可能的属性中寻找几乎相同的可能字符串,我们可以使用一个固定的值列表来检查所有可能的属性:

//meta[
    contains(
        '/author/article:author/authorname/dc.creator/byline/byl/',
        concat('/', @name|@itemprop|@rel|@id|@class, '/')
    )
]/@content

结合前两点,我们可以得到:

(
    //meta[
        contains(
            '/author/article:author/authorname/dc.creator/byline/byl/',
            concat('/', @name|@itemprop|@rel|@id|@class, '/')
        )
    ]/@content
    |
    //input[
        @id='authorname'
    ]/@value
)[1]

警告:只有当 <meta> 永远不会有 both 时,这才会按预期工作,例如@name@rel,或者如果它们至少具有相同的值。否则 concat('/', @name|@itemprop|@rel|@id|@class, '/') 可能会选错。这是一个经过计算的风险,我认为这种情况在 HTML 中发生并不常见。但是你需要决定,你是知道你输入数据的人。