Разбор ссылок с 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 в соответствии со следующими приоритетами (самый высокий приоритет - самый низкий):

  1. Базовый URI устанавливается элементом BASE.
  2. Базовый URI задается метаданными, обнаруженными во время взаимодействия по протоколу, такими как заголовок HTTP (см. [RFC2616]).
  3. По умолчанию базовый URI соответствует текущему документу. Не все HTML-документы имеют базовый URI (например, действительный HTML-документ может появиться в электронном письме и не может быть обозначен URI). Такие документы HTML считаются ошибочными, если они содержат относительные URI и полагаются на базовый URI по умолчанию.

На практике вы, вероятно, больше всего обеспокоены числами 1 и 2 (т.е. проверьте <base href="..." и используйте либо это (если оно существует), либо URI текущего документа).

Другие вопросы по тегам