Извлечение тега привязки из HTML с использованием Java - PullRequest
0 голосов
/ 11 июля 2011

У меня есть несколько тегов привязки в тексте,

Входные данные: <a href="http://stackoverflow.com" >Take me to StackOverflow</a>

Выходные данные: http://stackoverflow.com

Как найти все эти входные строки и преобразоватьэто к выходной строке в Java, без использования стороннего API ???

Ответы [ 5 ]

6 голосов
/ 11 июля 2011

В базовом API есть классы, которые можно использовать для получения всех атрибутов href из тегов привязки (если они есть!):

import java.io.*;
import java.util.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;

public class HtmlParseDemo {
   public static void main(String [] args) throws Exception {

       String html =
           "<a href=\"http://stackoverflow.com\" >Take me to StackOverflow</a> " +
           "<!--                                                               " +
           "<a href=\"http://ignoreme.com\" >...</a>                           " +
           "-->                                                                " +
           "<a href=\"http://www.google.com\" >Take me to Google</a>           " +
           "<a>NOOOoooo!</a>                                                   ";

       Reader reader = new StringReader(html);
       HTMLEditorKit.Parser parser = new ParserDelegator();
       final List<String> links = new ArrayList<String>();

       parser.parse(reader, new HTMLEditorKit.ParserCallback(){
           public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
               if(t == HTML.Tag.A) {
                   Object link = a.getAttribute(HTML.Attribute.HREF);
                   if(link != null) {
                       links.add(String.valueOf(link));
                   }
               }
           }
       }, true);

       reader.close();
       System.out.println(links);
   }
}

, которые будут печатать:

[http://stackoverflow.com, http://www.google.com]
4 голосов
/ 11 июля 2011
public static void main(String[] args) {
    String test = "qazwsx<a href=\"http://stackoverflow.com\">Take me to StackOverflow</a>fdgfdhgfd"
            + "<a href=\"http://stackoverflow2.com\">Take me to StackOverflow2</a>dcgdf";

    String regex = "<a href=(\"[^\"]*\")[^<]*</a>";

    Pattern p = Pattern.compile(regex);

    Matcher m = p.matcher(test);
    System.out.println(m.replaceAll("$1"));
}

ПРИМЕЧАНИЕ: Все точки Анджея Дойла действительны, и если у вас есть более чем простой <a href="X">Y</a> во входных данных, и вы уверены, что это HTML-код с возможностью анализа,Вы лучше разбираетесь в HTML-парсере.

Подводя итог:

  1. Регулярное выражение, которое я разместил, не будет работать, если у вас <a> в комментарии.(вы можете рассматривать это как особый случай)
  2. Не работает, если у вас есть другие атрибуты в теге <a>.(опять же, вы можете рассматривать его как особый случай)
  3. Есть много других случаев, когда регулярное выражение не работает, и вы не можете охватить все их регулярным выражением, поскольку HTML не является обычным языком.

Однако, если ваш запрос всегда заменяет <a href="X">Y</a> на "X" без учета контекста, то код, который я разместил, будет работать.

3 голосов
/ 11 июля 2011

Вы можете использовать JSoup

String html = "<p>An <a href=\"http://stackoverflow.com\" >Take me to StackOverflow</a> link.</p>";
Document doc = Jsoup.parse(html);
Element link = doc.select("a").first();

String linkHref = link.attr("href"); // "http://stackoverflow.com"

См. Также

2 голосов
/ 27 августа 2012

Пример выше работает отлично; если вы хотите проанализировать HTML-документ, скажем, вместо объединенных строк, напишите что-то вроде этого, чтобы дополнить код выше.

Существующий код выше ~ изменен, чтобы показать: HtmlParser.java (HtmlParseDemo.java) выше дополняющий код с HtmlPage.java ниже. Содержимое файла HtmlPage.properties находится внизу этой страницы.

Свойство main.url в файле HtmlPage.properties: main.url = http://www.whatever.com/

Таким образом, вы можете просто проанализировать URL, который у вас после. :-) Удачного кодирования: -D

import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;

public class HtmlParser
{
    public static void main(String[] args) throws Exception
    {
        String html = HtmlPage.getPage();

        Reader reader = new StringReader(html);
        HTMLEditorKit.Parser parser = new ParserDelegator();
        final List<String> links = new ArrayList<String>();

        parser.parse(reader, new HTMLEditorKit.ParserCallback()
        {
            public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
            {
                if (t == HTML.Tag.A)
                {
                    Object link = a.getAttribute(HTML.Attribute.HREF);
                    if (link != null)
                    {
                        links.add(String.valueOf(link));
                    }
                }
            }
        }, true);

        reader.close();

        // create the header
        System.out.println("<html>\n<head>\n   <title>Link City</title>\n</head>\n<body>");

        // spit out the links and create href
        for (String l : links)
        {
            System.out.print("   <a href=\"" + l + "\">" + l + "</a>\n");
        }

        // create footer
        System.out.println("</body>\n</html>");
    }
}

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ResourceBundle;

public class HtmlPage
{
    public static String getPage()
    {
        StringWriter sw = new StringWriter();
        ResourceBundle bundle = ResourceBundle.getBundle(HtmlPage.class.getName().toString());

        try
        {
            URL url = new URL(bundle.getString("main.url"));

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);

            InputStream content = (InputStream) connection.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(content));

            String line;

            while ((line = in.readLine()) != null)
            {
                sw.append(line).append("\n");
            }

        } catch (Exception e)
        {
            e.printStackTrace();
        }

        return sw.getBuffer().toString();
    }
}

Например, при выводе в браузере будут выводиться ссылки с http://ebay.com.au/. Это подмножество, так как ссылок много

    
    
       Link City
    
    
       #mainContent
       <a href="http://realestate.ebay.com.au/" rel="nofollow">http://realestate.ebay.com.au/</a>
     

    
0 голосов
/ 11 июля 2011

Самый надежный способ (как уже было предложено) - это использовать регулярные выражения (java.util.regexp), если вам необходимо создать это без использования сторонних библиотек.

Альтернативой является синтаксический анализ html как XML, либо с использованием синтаксического анализатора SAX для захвата и обработки каждого экземпляра элемента «a», либо в качестве документа DOM, а затем поиск по нему с использованием XPATH (см. http://download.oracle.com/javase/6/docs/api/javax/xml/parsers/package-summary.html). Это Хотя это проблематично, поскольку для разметки требуется, чтобы HTML-страница полностью соответствовала XML, это очень опасное предположение, а не подход, который я бы рекомендовал, поскольку большинство «настоящих» html-страниц не соответствуют XML.

Тем не менее, я бы порекомендовал также взглянуть на существующие фреймворки, созданные для этой цели (например, JSoup, также упомянутый выше). Не нужно изобретать велосипед.

...