Вопрос о том, как извлечь текст из HTML с помощью Java, просматривался и дублировался миллион раз: Извлечение текста из HTML Java
Благодаря ответам, найденным в Stackoverflow, мое текущее положение дел таково, что я использую JSoup
<!-- Jsoup maven dependency -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.3</version>
</dependency>
и этот кусок или код:
// parse the html from the givne string
Document doc = Jsoup.parse(html);
// loop over children elements of the body tag
for (Element el:doc.select("body").select("*")) {
// loop over all textnodes of these children
for (TextNode textNode:el.textNodes()) {
// make sure there is some text other than whitespace
if (textNode.text().trim().length()>0) {
// show:
// the original node name
// the name of the subnode witht the text
// the text
System.out.println(el.nodeName()+"."+textNode.nodeName()+":"+textNode.text());
}
}
}
Теперь я также хотел бы показать номер строки и исходный исходный код html, из которого был получен данный textNode. Я сомневаюсь, что JSoup может это сделать (например, см.)
и пробуя работать, например:
int pos = html.indexOf(textNode.outerHtml());
не может надежно найти исходный HTML. Поэтому я предполагаю, что мне, возможно, придется переключиться на другую библиотеку или подход. Jericho-html: Можно ли извлечь текст со ссылкой на позиции в исходном файле? есть ответ, в котором говорится: «Иерихон может это сделать», на что также указывает ссылка выше. Но указатель на реальный рабочий код отсутствует.
С Иерихоном я дошел до:
Source htmlSource=new Source(html);
boolean bodyFound=false;
// loop over all elements
for (net.htmlparser.jericho.Element el:htmlSource.getAllElements()) {
if (el.getName().equals("body")) {
bodyFound=true;
}
if (bodyFound) {
TagType tagType = el.getStartTag().getTagType();
if (tagType==StartTagType.NORMAL) {
String text=el.getTextExtractor().toString();
if (!text.trim().equals("")) {
int cpos = el.getBegin();
System.out.println(el.getName()+"("+tagType.toString()+") line "+ htmlSource.getRow(cpos)+":"+text);
}
} // if
} // if
} // for
Что уже довольно хорошо, так как это даст вам следующий результат:
body(normal) line 91: Some Header. Some Text
div(normal) line 93: Some Header
div(normal) line 95: Some Text
но теперь проблема заключается в том, что TextExtractor рекурсивно выводит весь текст всех подузлов, так что текст появляется несколько раз.
Каким будет рабочее решение, которое фильтрует так же, как указанное выше решение JSoup (обратите внимание на правильный порядок текстовых элементов), но показывает исходные строки, как это делает приведенный выше фрагмент кода Jericho?