2010-03-20 2 views
2

У меня есть строка текста, содержащая html, и мне нужно извлечь каждый url (скорее всего, в img или теги), чтобы создать общий список строковых объектов. Мне нужны только URL-адреса из тегов html, а не в тексте. Есть ли простой способ сделать это или мне придется прибегать к регулярным выражениям?извлечь все url из строки

Если мне приходится прибегать к регулярным выражениям, не могли бы вы также помочь мне в этом? :)

ОБНОВЛЕНИЕ: Чтобы ответить 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> 

И я хочу

конечный результат должен быть Все URL в любом HTML Тег, игнорируя те являются «простой текст»

UPPERDATE Хотя он удалил свой ответ, я хочу поблагодарить Джерри Буллард за то, чтобы мое внимание Regex друзей (http://www.regexbuddy). Я хотел поддержать свой ответ, но его ушло. Верните его, и вы получите голосование!

+0

Некоторый текст будет полезен вместе с точным желаемым выходом. – Seph

+0

спасибо, см. Выше – 2010-03-20 01:24:57

+0

@ codemonkey12: см. Мое обновление на основе вашего комментария RegexBuddy. –

ответ

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

Этот код может быть полезен :) Снято с 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); 
    } 
} 
1

Вот 2 подхода с помощью LINQ к XML и регулярных выражений. Хотя некоторые люди недовольны анализом HTML с регулярным выражением, этот конкретный случай не имеет вложенных элементов, поэтому это разумное решение. LINQ to XML будет работать только в том случае, если ваш HTML хорошо сформирован. В противном случае взгляните на HTML Agility Pack.

EDIT: для вашего образца 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); 
} 

EDIT # 2: в ответ на ваше обновление о RegexBuddy, я хотел бы отметить инструмент я использую. Expresso - хороший бесплатный инструмент (только для регистрации по электронной почте, но он бесплатный). Автор также написал The 30 Minute Regex Tutorial, который вы можете использовать для продолжения и включен в файл справки Expresso.

Смежные вопросы