1. Обзор
Иногда нам нужно удалить все теги HTML и извлечь текст из строки документа HTML.
Проблема выглядит довольно просто. Однако, в зависимости от требований, он может иметь разные варианты.
В этом уроке мы обсудим, как это сделать с помощью Java.
2. Использование регулярных выражений
Поскольку у нас уже есть HTML в виде строковой
переменной, нам нужно выполнить своего рода манипуляцию с текстом.
При возникновении проблем с манипулированием текстом регулярные выражения (Regex) могут быть первой идеей, которая может прийти в голову.
Удаление HTML-тегов из строки не составит труда для Regex, поскольку независимо от того, какие HTML-элементы начинаются или заканчиваются, они следуют шаблону «<…>».
Если мы переведем его в регулярное выражение, это будет «<[^>]*>»
или «<.*?>»
.
Следует отметить, что Regex по умолчанию выполняет жадное сопоставление . То есть регулярное выражение «<.*>»
не будет работать для нашей проблемы, так как мы хотим сопоставить от ' <
' до следующего ' >
' вместо последнего ' >
' в строке.
Теперь давайте проверим, может ли он удалять теги из источника HTML.
2.1. Удаление тегов из example1.html
Прежде чем мы протестируем удаление тегов HTML, сначала давайте создадим пример HTML, скажем, example1.html
:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>This is the page title</title>
</head>
<body>
<p>
If the application X doesn't start, the possible causes could be:<br/>
1. <a href="maven.com">Maven</a> is not installed.<br/>
2. Not enough disk space.<br/>
3. Not enough memory.
</p>
</body>
</html>
Теперь давайте напишем тест и используем String.replaceAll()
для удаления тегов HTML:
String html = ... // load example1.html
String result = html.replaceAll("<[^>]*>", "");
System.out.println(result);
Если мы запустим тестовый метод, мы увидим результат:
This is the page title
If the application X doesn't start, the possible causes could be:
1. Maven is not installed.
2. Not enough disk space.
3. Not enough memory.
Выход выглядит довольно хорошо. Это связано с тем, что все теги HTML были удалены.
Он сохраняет пробелы из очищенного HTML. Но мы можем легко удалить или пропустить эти пустые строки или пробелы при обработке извлеченного текста. Все идет нормально.
2.2. Удаление тегов из example2.html
Как мы только что видели, использовать Regex для удаления HTML-тегов довольно просто. Однако у этого подхода могут быть проблемы, поскольку мы не можем предсказать, какой исходный код HTML мы получим .
Например, HTML-документ может иметь теги <script>
или <style>
, и мы можем не захотеть, чтобы их содержимое отображалось в результате.
Кроме того, текст в тегах <script>
, <style>
или даже <body>
может содержать символы « <
» или « > ».
Если это так, наш подход Regex может потерпеть неудачу.
Теперь давайте посмотрим на другой пример HTML, скажем, example2.html
:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>This is the page title</title>
</head>
<script>
// some interesting script functions
</script>
<body>
<p>
If the application X doesn't start, the possible causes could be:<br/>
1. <a
id="link"
href="http://maven.apache.org/">
Maven
</a> is not installed.<br/>
2. Not enough (<1G) disk space.<br/>
3. Not enough (<64MB) memory.<br/>
</p>
</body>
</html>
На этот раз у нас есть тег <script>
и символы « < » в
теге <body>
.
Если мы используем тот же метод для example2.html
, мы получим (пустые строки были удалены):
This is the page title
// some interesting script functions
If the application X doesn't start, the possible causes could be:
1.
Maven
is not installed.
2. Not enough (
3. Not enough (
Видимо, мы потеряли часть текста из-за символов «<».
Таким образом, использование Regex для обработки XML или HTML является ненадежным . Вместо этого мы можем выбрать синтаксический анализатор HTML для выполнения этой работы.
Далее мы рассмотрим несколько простых в использовании библиотек HTML для извлечения текста.
3. Использование Jsoup
Jsoup — популярный парсер HTML. Чтобы извлечь текст из документа HTML, мы можем просто вызвать Jsoup.parse(htmlString).text()
.
Во-первых, нам нужно добавить библиотеку Jsoup в путь к классам. Например, предположим, что мы используем Maven для управления зависимостями проекта:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.3</version>
</dependency>
Теперь давайте проверим это с нашим example2.html
:
String html = ... // load example2.html
System.out.println(Jsoup.parse(html).text());
Если мы запустим метод, он напечатает:
This is the page title If the application X doesn't start, the possible causes could be: 1. Maven is not installed. 2. Not enough (<1G) disk space. 3. Not enough (<64MB) memory.
Как видно из вывода, Jsoup успешно извлек текст из документа HTML. Кроме того, текст в элементе <script>
был проигнорирован.
Кроме того, по умолчанию Jsoup удалит все форматирование текста и пробелы, например разрывы строк .
Однако, если это необходимо, мы также можем попросить Jsoup сохранить разрывы строк .
4. Использование HTMLCleaner
HTMLCleaner — еще один парсер HTML. Его цель — сделать «неправильный и грязный» HTML из Интернета пригодным для дальнейшей обработки.
Во-первых, давайте добавим зависимость HTMLCleaner в наш pom.xml
:
<dependency>
<groupId>net.sourceforge.htmlcleaner</groupId>
<artifactId>htmlcleaner</artifactId>
<version>2.25</version>
</dependency>
Мы можем установить различные параметры для управления поведением синтаксического анализа HTMLCleaner.
Здесь, в качестве примера, скажем HTMLCleaner пропускать элемент <script>
при разборе example2.html
:
String html = ... // load example2.html
CleanerProperties props = new CleanerProperties();
props.setPruneTags("script");
String result = new HtmlCleaner(props).clean(html).getText().toString();
System.out.println(result);
HTMLCleaner выдаст этот вывод, если мы запустим тест:
This is the page title
If the application X doesn't start, the possible causes could be:
1.
Maven
is not installed.
2. Not enough (<1G) disk space.
3. Not enough (<64MB) memory.
Как мы видим, содержимое элемента <script>
было проигнорировано.
Кроме того, он преобразует теги <br/>
в разрывы строк в извлеченном тексте . Это может быть полезно, если формат важен.
С другой стороны, HTMLCleaner сохраняет пробелы в очищенном исходном коде HTML . Так, например, текст « 1. Maven не установлен
» разбит на три строки.
5. Использование Иерихона
Наконец-то мы увидим еще один HTML-парсер — Jericho . У него есть приятная функция: рендеринг HTML-разметки с простым форматированием текста. Мы увидим его в действии позже.
Как обычно, сначала добавим зависимость Jericho в pom.xml
:
<dependency>
<groupId>net.htmlparser.jericho</groupId>
<artifactId>jericho-html</artifactId>
<version>3.4</version>
</dependency>
В нашем примере2.html
у нас есть гиперссылка « Maven (http://maven.apache.org/)
». Теперь предположим, что мы хотели бы получить как URL-адрес ссылки, так и текст ссылки в результате.
Для этого мы можем создать объект Renderer
и использовать опцию includeHyperlinkURLs
:
String html = ... // load example2.html
Source htmlSource = new Source(html);
Segment segment = new Segment(htmlSource, 0, htmlSource.length());
Renderer htmlRender = new Renderer(segment).setIncludeHyperlinkURLs(true);
System.out.println(htmlRender);
Далее давайте выполним тест и проверим вывод:
If the application X doesn't start, the possible causes could be:
1. Maven <http://maven.apache.org/> is not installed.
2. Not enough (<1G) disk space.
3. Not enough (<64MB) memory.
Как видно из приведенного выше результата, текст был красиво отформатирован. Кроме того, текст в элементе <title>
по умолчанию игнорируется .
URL-адрес ссылки также включен. Помимо рендеринга ссылок ( <a>
), Jericho поддерживает рендеринг других тегов HTML , например, <hr/>, <br/>,
маркированный список ( <ul>
и <li>
) и так далее .
6. Заключение
В этой статье мы рассмотрели различные способы удаления тегов HTML и извлечения текста HTML.
Следует отметить, что не рекомендуется использовать Regex для обработки XML/HTML .
Как всегда, полный исходный код этой статьи можно найти на GitHub .