【问题标题】:Jsoup: Selecting HTML Between Different ClassesJsoup:在不同类之间选择 HTML
【发布时间】:2011-09-09 16:23:03
【问题描述】:

我正在尝试做类似的事情:Jsoup: How to get all html between 2 header tags

但是,我的代码似乎避免使用纯文本。 我正在解析的网站有这样的代码设置:

div class= "引用消息" 回复。可以包含图片、文字等。 div class= "引用消息" 对另一条引用消息的另一条回应

用于处理实际消息的代码片段:

Element quote = msg.select(".quoted-message").first();
Boolean hasQuote = false;
Elements siblings = null;
siblings = quote.siblingElements();
createQuotePost(quote);
List<Element> elementsBetween = new ArrayList<Element>();
    for (int i = 1; i < siblings.size(); i++) {
        Element sibling = siblings.get(i);
        if (! "div.quoted-message".equals(sibling.tagName())) {
            elementsBetween.add(sibling);
            }

        else {
            Log.v("location", "Clear and Process");
            processElementsBetween(elementsBetween);
            elementsBetween.clear();
        }
    }
    if (! elementsBetween.isEmpty())
        processElementsBetween(elementsBetween);

然而,这似乎并不如我所愿。对代码的响应没有任何特殊格式(即:位于 p 标签中)。使用一些日志记录,我可以看到它们没有被放入 Elements 兄弟姐妹中。 Siblings 似乎只包含换行符等。

注意:我只在小帖子(简单的一个衬里)上对此进行了测试,以节省筛选长页打印输出的时间。

有什么建议吗?

编辑: 这是 2 个引用消息 div 之间的 HTML 代码 sn-p:

    MESSAGE TO BE QUOTED
    </div>
    <br />
    <br />
    Hello quoted message
    <br />
    I am a response
    <br />
    <br />
    <div class="quoted-message">

【问题讨论】:

    标签: java android jsoup


    【解决方案1】:

    认为问题之一是您要求的是元素而不是节点。文本节点是节点而不是元素。

    试试这个:

    package grimbo.test;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.nodes.Node;
    import org.jsoup.select.Elements;
    
    public class StackOverflow {
        public static void main(String[] args) {
            String html = "<div class=quoted-message>message-1</div>\n    <br />\n    <br />\n    Hello quoted message\n    <br />\n    I am a response\n    <br />\n    <br />\n";
            html += "<div class=quoted-message>message-2</div>\n    <br />\n    <br />\n    Hello quoted message\n    <br />\n    I am a response\n    <br />\n    <br />\n";
            Document doc = Jsoup.parse(html);
            handleQuotedMessages(doc.select(".quoted-message"));
        }
    
        private static void handleQuotedMessages(Elements quotedMessages) {
            Element firstQuotedMessage = quotedMessages.first();
            List<Node> siblings = firstQuotedMessage.siblingNodes();
            List<Node> elementsBetween = new ArrayList<Node>();
            Element currentQuotedMessage = firstQuotedMessage;
            for (int i = 1; i < siblings.size(); i++) {
                Node sibling = siblings.get(i);
    
                // see if this Node is a quoted message
                if (!isQuotedMessage(sibling)) {
                    elementsBetween.add(sibling);
                } else {
                    createQuotePost(currentQuotedMessage, elementsBetween);
                    currentQuotedMessage = (Element) sibling;
                    elementsBetween.clear();
                }
            }
            if (!elementsBetween.isEmpty()) {
                createQuotePost(currentQuotedMessage, elementsBetween);
            }
        }
    
        private static boolean isQuotedMessage(Node node) {
            if (node instanceof Element) {
                Element el = (Element) node;
                return "div".equals(el.tagName()) && el.hasClass("quoted-message");
            }
            return false;
        }
    
        private static List<Element> filterElements(String tagName, List<Node> nodes) {
            List<Element> els = new ArrayList<Element>();
            for (Iterator<Node> it = nodes.iterator(); it.hasNext();) {
                Node n = it.next();
                if (n instanceof Element) {
                    Element el = (Element) n;
                    if (el.tagName().equals(tagName)) {
                        els.add(el);
                    }
                }
            }
            return els;
        }
    
        private static void createQuotePost(Element quote, List<Node> elementsBetween) {
            System.out.println("createQuotePost: " + quote);
            System.out.println("createQuotePost: " + elementsBetween);
            List<Element> imgs = filterElements("img", elementsBetween);
            // handle imgs
        }
    }
    

    【讨论】:

    • 效果很好,但是,有没有一种简单的方法可以将节点作为元素放回原处?它有时会包含图像/链接,我已经设置了一个方法来解析它们并且不想重新编码。
    • 所以您只想在elementsBetween 列表中保留原始文本节点?
    • 嗯,我有一个需要元素的方法(我们称之为 CreateMessage)。在该方法中,我使用 .select("img") 将所有图像的 url 拉到一个数组中。然后在显示消息时,它使用该列表将图像放回原处。网址等也是如此。如果它很痛苦,我可以重新编码它以获取一个字符串并解决它。
    • 我想我明白了。如果&lt;img&gt;s 是特殊的,那么在createQuotePost 方法中,您可以迭代elementsBetween 列表并专门处理&lt;img&gt;s。使用.select("img") 的问题在于&lt;img&gt;s 不是引用消息&lt;div&gt; 的后代,因此您必须做其他事情。就个人而言,elementsBetween 的简单循环就足够了(我已将其添加到答案中)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    相关资源
    最近更新 更多