从网页中提取链接

24

使用Java,我如何从给定的网页中提取所有链接?


你是在寻找锚点标签、带引号的URL还是任何出现在纯文本中的URL? - Sam Barnum
6个回答

22

下载Java文件,以纯文本/HTML格式传递,通过JsoupHTML Cleaner进行处理,两者都类似,并且可以用于解析不合规的HTML 4.0语法,然后您可以使用流行的HTML DOM解析方法,例如getElementsByName(“a”),在jsoup中这甚至更酷,您可以简单地使用

File input = new File("/tmp/input.html");
 Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Elements links = doc.select("a[href]"); // a with href
Elements pngs = doc.select("img[src$=.png]");
// img with src ending .png

Element masthead = doc.select("div.masthead").first();

查找所有链接,然后使用特定方法获取详细信息

String linkhref=links.attr("href");

来自http://jsoup.org/cookbook/extracting-data/selector-syntax

如果您熟悉jQuery的函数链式调用,那么选择器语法与其相同,您一定会喜欢它。

编辑:如果您需要更多教程,可以尝试这个由mkyong制作的教程。

http://www.mkyong.com/java/jsoup-html-parser-hello-world-examples/


7

您可以使用正则表达式和适当的类,或者使用HTML解析器。您想要使用哪种取决于您是想处理整个网络还是只是一些特定页面,您知道它们的布局并且可以进行测试。

一个简单的正则表达式可以匹配99%的页面:

// The HTML page as a String
String HTMLPage;
Pattern linkPattern = Pattern.compile("(<a[^>]+>.+?<\/a>)",  Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
Matcher pageMatcher = linkPattern.matcher(HTMLPage);
ArrayList<String> links = new ArrayList<String>();
while(pageMatcher.find()){
    links.add(pageMatcher.group());
}
// links ArrayList now contains all links in the page as a HTML tag
// i.e. <a att1="val1" ...>Text inside tag</a>

您可以编辑它以匹配更多内容,更符合标准等,但在这种情况下,您需要一个真正的解析器。 如果您只对 href="" 和文本之间的内容感兴趣,您也可以使用此正则表达式:

Pattern linkPattern = Pattern.compile("<a[^>]+href=[\"']?([\"'>]+)[\"']?[^>]*>(.+?)<\/a>",  Pattern.CASE_INSENSITIVE|Pattern.DOTALL);

使用.group(1)访问链接部分,使用.group(2)访问文本部分。


2
我认为你想表达的是 '...href=["']?([^"']+)...'。但是,如果 href="blablalba/Mc'Chicken" 呢?字符串不会在遇到单引号时被截断吗? - Mihai Bişog
如果URL中不包含<a href>标签,那么我认为它将无法跟踪该URL。 - RobinHood

4
你可以使用HTML解析器库来实现这个功能:

您可以使用HTML解析器库来实现此功能:

public static List<String> getLinksOnPage(final String url) {
    final Parser htmlParser = new Parser(url);
    final List<String> result = new LinkedList<String>();

    try {
        final NodeList tagNodeList = htmlParser.extractAllNodesThatMatch(new NodeClassFilter(LinkTag.class));
        for (int j = 0; j < tagNodeList.size(); j++) {
            final LinkTag loopLink = (LinkTag) tagNodeList.elementAt(j);
            final String loopLinkStr = loopLink.getLink();
            result.add(loopLinkStr);
        }
    } catch (ParserException e) {
        e.printStackTrace(); // TODO handle error
    }

    return result;
}

这真的很好。你可以在这里获取解析器:http://htmlparser.sourceforge.net - Ashok Goli
@shams:如果URL中有特殊字符,例如(www.google-gmail.com),会出现异常“org.htmlparser.util.EncodingChangeException: character mismatch (new: ? [0xfeff] != old: [0xefï]) for encoding change from ISO-8859-1 to UTF-8 at character offset 0”,该如何解决? - Prabu

3
这个简单的例子似乎有效,使用了来自这里的正则表达式。
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public ArrayList<String> extractUrlsFromString(String content)
{
    ArrayList<String> result = new ArrayList<String>();

    String regex = "(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";

    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(content);
    while (m.find())
    {
        result.add(m.group());
    }

    return result;
}

如果您需要,这似乎也可以用于获取URL的HTML,如果无法抓取则返回null。它也可以很好地处理https URL。

import org.apache.commons.io.IOUtils;

public String getUrlContentsAsString(String urlAsString)
{
    try
    {
        URL url = new URL(urlAsString);
        String result = IOUtils.toString(url);
        return result;
    }
    catch (Exception e)
    {
        return null;
    }
}

有没有办法将其限制为具有指定id值的表格中的所有链接? - Martin Erlic
@santafebound - 这个不能真正做到这一点 - 我认为你需要使用类似jsoup的工具来实现。[https://jsoup.org/cookbook/extracting-data/selector-syntax] - Brad Parks
1
点赞,因为没有省略导入语句:对于那些刚接触Java正则表达式的人来说,这很重要。 - Leonardo Maffei

2
import java.io.*;
import java.net.*;

public class NameOfProgram {
    public static void main(String[] args) {
        URL url;
        InputStream is = null;
        BufferedReader br;
        String line;

        try {
            url = new URL("http://www.stackoverflow.com");
            is = url.openStream();  // throws an IOException
            br = new BufferedReader(new InputStreamReader(is));

            while ((line = br.readLine()) != null) {
                if(line.contains("href="))
                    System.out.println(line.trim());
            }
        } catch (MalformedURLException mue) {
             mue.printStackTrace();
        } catch (IOException ioe) {
             ioe.printStackTrace();
        } finally {
            try {
                if (is != null) is.close();
            } catch (IOException ioe) {
                //exception
            }
        }
    }
}

添加所需的导入(如果使用终端并不知道导入): import java.io.; import java.net.; - Eagle

1
你可能需要在 HTML 链接标签 <a href=></a> 上使用正则表达式。

3
任何想要追求这条路的人应该阅读这篇文章:https://dev59.com/unRB5IYBdhLWcg3wiHz7。 - jok3rnaut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接