Разбор ссылок с JTidy
В настоящее время я использую JTidy для анализа HTML-документа и получения коллекции всех тегов привязки в данном HTML-документе. Затем я извлекаю значение атрибута href каждого тега, чтобы создать коллекцию ссылок на странице.
К сожалению, эти ссылки могут быть выражены несколькими различными способами: некоторые абсолютные (http://www.example.com/page.html
), некоторый родственник (/page.html
, page.html
, или же ../page.html
). Более того, некоторые могут просто быть якорями (#paragraphA
). Когда я захожу на свою страницу в браузере, он автоматически знает, как обрабатывать эти различные значения href, если я нажму на ссылку, однако, если я буду следовать одной из этих ссылок, полученных из JTidy с использованием HTTPClient программно, мне сначала нужно предоставить действительный URL-адрес (например, сначала мне нужно преобразовать /page.html, page.html и http://www.example.com/page.html в http://www.example.com/page.html).,
Есть ли какая-то встроенная функциональность, будь то в JTidy или где-либо еще, которая может достичь этого для меня? Или мне нужно будет создать свои собственные правила для преобразования этих разных URL в абсолютные URL?
2 ответа
Класс vanilla URL может помочь вам в этом, если вы сможете решить, какой контекст использовать. Вот некоторые примеры:
package grimbo.url;
import java.net.MalformedURLException;
import java.net.URL;
public class TestURL {
public static void main(String[] args) {
// context1
URL c1 = u(null, "http://www.example.com/page.html");
u(c1, "http://www.example.com/page.html");
u(c1, "/page.html");
u(c1, "page.html");
u(c1, "../page.html");
u(c1, "#paragraphA");
System.out.println();
// context2
URL c2 = u(null, "http://www.example.com/path/to/page.html");
u(c2, "http://www.example.com/page.html");
u(c2, "/page.html");
u(c2, "page.html");
u(c2, "../page.html");
u(c2, "#paragraphA");
}
public static URL u(URL context, String url) {
try {
URL u = null != context ? new URL(context, url) : new URL(url);
System.out.println(u);
return u;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
}
Результаты в:
http://www.example.com/page.html
http://www.example.com/page.html
http://www.example.com/page.html
http://www.example.com/page.html
http://www.example.com/../page.html
http://www.example.com/page.html#paragraphA
http://www.example.com/path/to/page.html
http://www.example.com/page.html
http://www.example.com/page.html
http://www.example.com/path/to/page.html
http://www.example.com/path/page.html
http://www.example.com/path/to/page.html#paragraphA
Как видите, есть некоторые результаты, которые не соответствуют вашим ожиданиям. Поэтому, возможно, вы попытаетесь разобрать URL с помощью new URL(value)
во-первых, и если это приводит к MalformedURLException
Вы можете попробовать относительно контекстного URL.
Лучше всего лучше всего следовать тому же процессу разрешения, что и в браузерах, как описано в спецификации HTML:
Пользовательские агенты должны вычислять базовый URI в соответствии со следующими приоритетами (самый высокий приоритет - самый низкий):
- Базовый URI устанавливается элементом BASE.
- Базовый URI задается метаданными, обнаруженными во время взаимодействия по протоколу, такими как заголовок HTTP (см. [RFC2616]).
- По умолчанию базовый URI соответствует текущему документу. Не все HTML-документы имеют базовый URI (например, действительный HTML-документ может появиться в электронном письме и не может быть обозначен URI). Такие документы HTML считаются ошибочными, если они содержат относительные URI и полагаются на базовый URI по умолчанию.
На практике вы, вероятно, больше всего обеспокоены числами 1 и 2 (т.е. проверьте <base href="..."
и используйте либо это (если оно существует), либо URI текущего документа).