从字符串中提取所有URL

时间:2010-03-20 01:14:43

标签: asp.net url

我有一个包含html的文本字符串,我需要提取每个url(最有可能是img或标签)来创建字符串对象的通用列表。我只想要来自html标签内的网址,而不是文本中的网址。有没有一种简单的方法可以做到这一点,还是我必须诉诸正则表达式?

如果我不得不诉诸正则表达式,你还介意帮我解决这个问题吗? :)

更新 要回答Seph,输入将是标准的html。

<p>This is some html text.  my favourite website is <a href="http://www.google.com">google</a> and my favourite help site is <a href="http://www.stackoverflow.com">stackoverflow</a> and i check my email at <a href="http://www.gmail.com">gmail</a>.  the url to my site is http://www.mysite.com.   <img src="http://www.someserver.com/someimage.jpg" alt=""/></p>

我想要

最终结果应该是任何html标签中的所有网址,忽略那些是“纯文本”

UPPERDATE 虽然他删除了答案,但我要感谢Jerry Bullard引起我的注意 Regex Buddy(http://www.regexbuddy)。我想提出你的答案,但它已经消失了。把它带回来你就得票了!

3 个答案:

答案 0 :(得分:1)

这样的事情应该会有所帮助:

    private List<string> GetUrlStrings(string text)
    {
        List<string> listURL = new List<string>();
        Regex regex = new Regex("href\\s*=\\s*(?:(?:\\\"(?<url>[^\\\"]*)\\\")|(?<url>[^\\s]* ))");
        MatchCollection mathColl = regex.Matches(text);

        foreach (Match match in mathColl)
        {
            foreach (Group group in match.Groups)
            {
                if (!group.Value.StartsWith("href")) // workaround regex issue
                {
                    listURL.Add(group.Value);
                }
            }
        }
        return listURL;
    }

答案 1 :(得分:1)

以下是使用LINQ to XML和regex的两种方法。虽然有些人对使用正则表达式解析HTML感到不满,但这种特殊情况并没有嵌套元素,所以这是一个合理的解决方案。 LINQ to XML仅在HTML格式正确时才有效。否则,请查看HTML Agility Pack

样本Elements()

编辑与LINQ to XML一起使用。但是,如果您有许多嵌套的HTML标记,那么您可能希望使用Descendants()来覆盖所有需要的标记。

string input = @"<p>This is some html text.  my favourite website is <a href=""http://www.google.com"">google</a> and my favourite help site is <a href=""http://www.stackoverflow.com"">stackoverflow</a> and i check my email at <a href=""http://www.gmail.com"">gmail</a>.  the url to my site is http://www.mysite.com.   <img src=""http://www.someserver.com/someimage.jpg"" alt=""""/></p>";
var xml = XElement.Parse(input);
var result = xml.Elements()
                .Where(e => e.Name == "img" || e.Name == "a")
                .Select(e => e.Name == "img" ?
                            e.Attribute("src").Value : e.Attribute("href").Value);
foreach (string item in result)
{
    Console.WriteLine(item);
}

string pattern = @"<(?:a|img).+?(?:href|src)=""(?<Url>.+?)"".*?>";
foreach (Match m in Regex.Matches(input, pattern))
{
    Console.WriteLine(m.Groups["Url"].Value);
}

编辑#2:为了回应您关于RegexBuddy的更新,我想指出我使用的工具。 Expresso是一个很好的免费工具(仅限电子邮件注册,但它是免费的)。作者还写了The 30 Minute Regex Tutorial,您可以使用它来跟随它,并包含在Expresso的帮助文件中。

答案 2 :(得分:-1)

此代码可能有所帮助:)取自http://www.vogella.de/articles/JavaRegularExpressions/article.html

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LinkGetter {
    private Pattern htmltag;
    private Pattern link;
    private final String root;

    public LinkGetter(String root) {
        this.root = root;
        htmltag = Pattern.compile("<a\\b[^>]*href=\"[^>]*>(.*?)</a>");
        link = Pattern.compile("href=\"[^>]*\">");
    }

    public List<String> getLinks(String url) {
        List<String> links = new ArrayList<String>();
        try {
            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(new URL(url).openStream()));
            String s;
            StringBuilder builder = new StringBuilder();
            while ((s = bufferedReader.readLine()) != null) {
                builder.append(s);
            }

            Matcher tagmatch = htmltag.matcher(builder.toString());
            while (tagmatch.find()) {
                Matcher matcher = link.matcher(tagmatch.group());
                matcher.find();
                String link = matcher.group().replaceFirst("href=\"", "")
                        .replaceFirst("\">", "");
                if (valid(link)) {
                    links.add(makeAbsolute(url, link));
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return links;
    }

    private boolean valid(String s) {
        if (s.matches("javascript:.*|mailto:.*")) {
            return false;
        }
        return true;
    }

    private String makeAbsolute(String url, String link) {
        if (link.matches("http://.*")) {
            return link;
        }
        if (link.matches("/.*") && url.matches(".*$[^/]")) {
            return url + "/" + link;
        }
        if (link.matches("[^/].*") && url.matches(".*[^/]")) {
            return url + "/" + link;
        }
        if (link.matches("/.*") && url.matches(".*[/]")) {
            return url + link;
        }
        if (link.matches("/.*") && url.matches(".*[^/]")) {
            return url + link;
        }
        throw new RuntimeException("Cannot make the link absolute. Url: " + url
                + " Link " + link);
    }
}