【问题标题】:Parsing the html meta tag with jsoup library使用 jsoup 库解析 html 元标记
【发布时间】:2016-10-02 04:20:01
【问题描述】:

刚开始探索 Jsoup 库,因为我将在我的一个项目中使用它。我尝试使用谷歌搜索,但找不到可以帮助我的确切答案。这是我的问题,我有一个带有如下元标记的 html 文件

<meta content="this is the title value" name="d.title">
<meta content="this is the description value" name="d.description">
<meta content="language is french" name="d.language">

还有一个像这样的java pojo,

public class Example {
    private String title;
    private String description;
    private String language;

    public Example() {}

    // setters and getters go here
} 

现在我想解析 html 文件并提取 d.title 内容值并存储在“内容”的 Example.title 和 d.description 值中并存储在 Example.description 中等等。

我通过阅读 jsoup 食谱所做的事情有点像,

Document doc = Jsoup.parse("test.html");
Elements metaTags = doc.getElementsByTag("meta");

for (Element metaTag : metaTags) {
    String content = metaTag.attr("content");
    String content = metaTag.attr("name");
}

这将做的是遍历所有元标记获取其“内容”和“名称”属性的值,但我想要的是获取“名称”属性为“d”的“内容”属性的值.title" 这样我就可以将它存储在 Example.title 中

更新: @P.J.Meisch 下面的答案实际上解决了这个问题,但我喜欢的代码太多(试图避免做完全相同的事情)。我的意思是我在想有可能做类似的事情

字符串标题 = metaTags.getContent("d.title")

其中 d.title 是“名称”属性的值 这样它会减少代码行,我还没有找到这样的方法,但也许那是因为我还是 jsoup 的新手,这就是我问的原因。但是如果不存在这样的方法(如果它确实会很好,因为它会让生活更轻松)我会选择 P.J.Meisch 说的。

【问题讨论】:

    标签: java html html-parsing jsoup


    【解决方案1】:

    您将两个属性的值分配给同一个名为 content 的变量。将 name 属性分配给 namevariable 并将其与您想要的 'd.title' 值进行比较。

    【讨论】:

    • 我怎么知道 d.title 的期望值。 html文件不是我制作的,所以我事先不知道'd.title'的值
    【解决方案2】:

    好的,所有代码:

    Document doc = Jsoup.parse("test.html");
    Elements metaTags = doc.getElementsByTag("meta");
    
    Example ex = new Example();
    
    for (Element metaTag : metaTags) {
      String content = metaTag.attr("content");
      String name = metaTag.attr("name");
    
      if("d.title".equals(name)) {
        ex.setTitle(content);
      }
      if("d.description".equals(name)) {
        ex.setDescription(content);
      }
      if("d.language".equals(name)) {
        ex.setLanguage(content);
      }
    }
    

    【讨论】:

    • 好的,我现在明白你的回答了。谢谢。但我希望我不会诉诸这样的事情。我会更新我的问题以反映我真正想要的。 :)
    • 更新了我的问题,你能看看我想要的是否可行?
    • 我首先批准了您使用地图的其他答案,但我意识到,它不能很好地工作,因为正在处理的 html 文件具有多次出现的名称属性(如 d.contributor可以出现多次),如果我使用地图来存储它们,地图将只存储最后一个,因为它不能有相同的键来引用不同的对象。所以我就同意了
    • 地图只有元标签的名称属性作为键,而不是其他具有名称元素的标签,所以应该可以工作
    • 我在说一些名称属性具有相同的值,就像一个名称可以有多个 d.contributor。并且地图将名称属性存储为键,在这种情况下是“d.contributor”,它出现了 3 次,因此地图将只存储最后一个
    【解决方案3】:

    回答您更新的问题:jsoup 无法做到这一点,因为 jsoup 文档仅反映了 html 文档的 xml/dom 结构。您将不得不对元数据进行迭代,但您可以执行以下操作:

    Document doc = Jsoup.parse("test.html");
    
    Map<String, String> metas = new HashMap<>();
    Elements metaTags = doc.getElementsByTag("meta");
    
    for (Element metaTag : metaTags) {
      String content = metaTag.attr("content");
      String name = metaTag.attr("name");
      metas.put(name, content);
    }
    
    Example ex = new Example();
    ex.setTitle(metas.get("d.title"));
    ex.setDescription(metas.get("d.description"));
    ex.setLanguage(metas.get("d.language"));
    

    【讨论】:

    • 谢谢。这是最接近我想要的。但是如果 jsoup 有这个功能那就太好了,因为它是开源的,我会尝试看看我是否可以得到它:)
    【解决方案4】:

    使用正确的特定库可以简化一切

    查看我的库以解析元标记内容

    poshjosh/bcmetaselector

    package com.bc.meta.selector;
    
    import com.bc.meta.selector.htmlparser.AttributeContextHtmlparser;
    import com.bc.meta.selector.util.SampleConfigPaths;
    import com.bc.meta.ArticleMetaNames;
    import com.bc.meta.impl.ArticleMetaNameIsMultiValue;
    import java.util.Map;
    import java.util.Iterator;
    import java.util.function.BiFunction;
    import org.json.simple.JSONValue;
    import org.htmlparser.Parser;
    import org.htmlparser.Node;
    import org.htmlparser.Tag;
    
    public class ReadMe {
    
        public static void main(String... args) throws Exception {
    
            final BiFunction<String, Node, String> nodeContentExtractor =
                    (prop, node) -> node instanceof Tag ? ((Tag)node).getAttributeValue("content") : null;
    
            final SelectorBuilder<Node, String, Object> builder = Selector.builder();
    
            final Selector<Node> selector = builder.filter()
                    .attributeContext(new AttributeContextHtmlparser(false))
                    .configFilePaths(SampleConfigPaths.APP_ARTICLE_LIST)
                    .jsonParser((reader) -> (Map)JSONValue.parse(reader))
                    .propertyNames(ArticleMetaNames.values())
                    .back()
                    .multipleValueTest(new ArticleMetaNameIsMultiValue())
                    .nodeConverter(nodeContentExtractor)
                    .build();
    
            final Parser parser = new Parser();
    
            final String url = "https://edition.cnn.com/2018/06/21/africa/noura-hussein-asequals-intl/index.html";
    
            parser.setURL(url);
    
            Iterator<Node> nodes = parser.elements().iterator();
    
            final Map map = selector.selectAsMap(nodes, ArticleMetaNames.values());
    
            System.out.println("Printing meta tags data for: " + url + "\n" + map);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-18
      • 2014-05-20
      • 2014-04-25
      • 2012-11-06
      • 1970-01-01
      • 1970-01-01
      • 2015-01-03
      • 2012-10-01
      相关资源
      最近更新 更多