2010-10-01 55 views
8

我正在镜像一些内部网站用于备份目的。截至目前,我基本上使用这个C#代码:C#将相对值转换为HTML字符串中的绝对链接

System.Net.WebClient client = new System.Net.WebClient(); 
byte[] dl = client.DownloadData(url); 

这只是基本上下载的HTML和一个字节数组。这就是我要的。然而,问题在于html中的链接大部分时间都是相对的,而不是绝对的。

我基本上想要在相关链接之前追加完整的http://domain.is以将其转换为将重定向到原始内容的绝对链接。我基本上只关心href =和src =。是否有一个正则表达式可以涵盖一些基本的情况?

编辑[我的尝试]:

public static string RelativeToAbsoluteURLS(string text, string absoluteUrl) 
{ 
    if (String.IsNullOrEmpty(text)) 
    { 
     return text; 
    } 

    String value = Regex.Replace(
     text, 
     "<(.*?)(src|href)=\"(?!http)(.*?)\"(.*?)>", 
     "<$1$2=\"" + absoluteUrl + "$3\"$4>", 
     RegexOptions.IgnoreCase | RegexOptions.Multiline); 

    return value.Replace(absoluteUrl + "/", absoluteUrl); 
} 
+0

http://stackoverflow.com/questions/3836644的重复/ c-convert-relative-to-absolute-links-in-html-string/3836790#3836790你今天早些时候问过的! – 2010-10-01 08:34:05

回答

8

最强大的解决方案是使用HTMLAgilityPack如其他人所说。但是合理的解决方案使用正则表达式是可能使用Replace过载,需要一个MatchEvaluator委托,如下所示:

var baseUri = new Uri("http://test.com"); 
var pattern = @"(?<name>src|href)=""(?<value>/[^""]*)"""; 
var matchEvaluator = new MatchEvaluator(
    match => 
    { 
     var value = match.Groups["value"].Value; 
     Uri uri; 

     if (Uri.TryCreate(baseUri, value, out uri)) 
     { 
      var name = match.Groups["name"].Value; 
      return string.Format("{0}=\"{1}\"", name, uri.AbsoluteUri); 
     } 

     return null; 
    }); 
var adjustedHtml = Regex.Replace(originalHtml, pattern, matchEvaluator); 

将上述样品搜索命名的属性src和HREF包含开始以正斜杠双引号值。对于每个匹配,使用静态Uri.TryCreate方法来确定该值是否是有效的相对uri。

请注意,此解决方案不处理单引号属性值,当然不适用于格式不完整的HTML和未引用的值。

+1

我添加了一个编辑,至少在我的少数测试用例中起作用。看看正则表达式的东西,它看起来很相似,但是你的代码看起来要复杂得多。我老实说从未使用过MatchEvaluator和代表的东西;你的代码更好吗? – Gary 2010-10-01 06:12:52

+0

使用MatchEvaluator可以极大地简化正则表达式模式,并使用更稳健的Uri.TryCreate方法。匹配所有可能的URI的正则表达式将非常复杂。 – 2010-10-01 06:19:47

+0

性能如何?并感谢您的答案! – Gary 2010-10-01 06:23:28

0

我觉得URL字符串类型的。使用URI以代替基本URI指向您的域:

Uri baseUri = new Uri("http://domain.is"); 
Uri myUri = new Uri(baseUri, url); 

System.Net.WebClient client = new System.Net.WebClient(); 
byte[] dl = client.DownloadData(myUri); 
+0

这是否改变了myUri中html相对于绝对的链接,还是使用WebClient更好? – Gary 2010-10-01 05:31:44

1

虽然这可能不是最强大的解决方案,应该把工作做好的。

var host = "http://domain.is"; 
var someHtml = @" 
<a href=""/some/relative"">Relative</a> 
<img src=""/some/relative"" /> 
<a href=""http://domain.is/some/absolute"">Absolute</a> 
<img src=""http://domain.is/some/absolute"" /> 
"; 


someHtml = someHtml.Replace("src=\"" + host,"src=\""); 
someHtml = someHtml.Replace("href=\"" + host,"src=\""); 
someHtml = someHtml.Replace("src=\"","src=\"" + host); 
someHtml = someHtml.Replace("href=\"","src=\"" + host); 
5

您应该使用HtmlAgility包加载HTML,访问使用它所有的HREFs,然后使用URI类从相对转换为绝对必要的。

见例如http://blog.abodit.com/2010/03/a-simple-web-crawler-in-c-using-htmlagilitypack/

+0

我尝试过你的例子,但似乎有一个错误。如果我有一个baseUrl作为'http:// ww.baseurl.com/somedir',并且我尝试创建一个使用你的方法添加'/ login.php'的绝对路径,我会得到'http://ww.baseurl.com/login.php'而不是'http:// ww.baseurl.com/somedir/login.php' – Smith 2012-11-17 21:59:47

1

您可以使用HTMLAgilityPack做到这一点。你会做沿着这些东西(未测试)线:

  • 载入网址
  • 选择所有链接
  • 加载链接到Uri,并测试它是否是相对的。如果它 相对其转换为绝对
  • 更新与新 URI
  • 链接值保存文件

这里有几个例子:

Relative to absolute paths in HTML (asp.net)

http://htmlagilitypack.codeplex.com/wikipage?title=Examples&referringTitle=Home

http://blog.abodit.com/2010/03/a-simple-web-crawler-in-c-using-htmlagilitypack/

5
Uri WebsiteImAt = new Uri(
     "http://www.w3schools.com/media/media_mimeref.asp?q=1&s=2,2#a"); 
string href = new Uri(WebsiteImAt, "/something/somethingelse/filename.asp") 
     .AbsoluteUri; 
string href2 = new Uri(WebsiteImAt, "something.asp").AbsoluteUri; 
string href3 = new Uri(WebsiteImAt, "something").AbsoluteUri; 

Regex为基础的方法可能(未经测试)可映射到:

 String value = Regex.Replace(text, "<(.*?)(src|href)=\"(?!http)(.*?)\"(.*?)>", match => 
      "<" + match.Groups[1].Value + match.Groups[2].Value + "=\"" 
       + new Uri(WebsiteImAt, match.Groups[3].Value).AbsoluteUri + "\"" 
       + match.Groups[4].Value + ">",RegexOptions.IgnoreCase | RegexOptions.Multiline); 

我也应该提醒在这里使用Regex,但应用乌里欺骗一些使用DOM的代码,或许是XmlDocument(如果是xhtml)或HTML Agility Pack(否则),查看所有//@src//@href属性。

0

只要使用此功能

'# converts relative URL ro Absolute URI 
    Function RelativeToAbsoluteUrl(ByVal baseURI As Uri, ByVal RelativeUrl As String) As Uri 
     ' get action tags, relative or absolute 
     Dim uriReturn As Uri = New Uri(RelativeUrl, UriKind.RelativeOrAbsolute) 
     ' Make it absolute if it's relative 
     If Not uriReturn.IsAbsoluteUri Then 
      Dim baseUrl As Uri = baseURI 
      uriReturn = New Uri(baseUrl, uriReturn) 
     End If 
     Return uriReturn 
    End Function 
0

简单的功能

public string ConvertRelativeUrlToAbsoluteUrl(string relativeUrl) 
{ 

if (Request.IsSecureConnection) 
    return string.Format("https://{0}{1}", Request.Url.Host, Page.ResolveUrl(relativeUrl)); 
else 
    return string.Format("http://{0}{1}", Request.Url.Host, Page.ResolveUrl(relativeUrl)); 

} 
0

我知道这是一个老问题,但我想通了如何与一个相当简单的正则表达式做到这一点。这对我来说很有用。它处理http/https以及相对根目录和当前相对目录。

var host = "http://www.google.com/"; 
var baseUrl = host + "images/"; 
var html = "<html><head></head><body><img src=\"/images/srpr/logo3w.png\" /><br /><img src=\"srpr/logo3w.png\" /></body></html>"; 
var regex = "(?<=(?:href|src)=\")(?!https?://)(?<url>[^\"]+)"; 
html = Regex.Replace(
    html, 
    regex, 
    match => match.Groups["url"].Value.StartsWith("/") 
     ? host + match.Groups["url"].Value.Substring(1) 
     : baseUrl + match.Groups["url"].Value); 
0

这是你在找什么,这个代码片断都可以在相对URL绝对转换任何HTML代码中:

Private Function ConvertALLrelativeLinksToAbsoluteUri(ByVal html As String, ByVal PageURL As String) 
    Dim result As String = Nothing 
    ' Getting all Href 
    Dim opt As New RegexOptions 
    Dim XpHref As New Regex("(href="".*?"")", RegexOptions.IgnoreCase) 
    Dim i As Integer 
    Dim NewSTR As String = html 
    For i = 0 To XpHref.Matches(html).Count - 1 
     Application.DoEvents() 
     Dim Oldurl As String = Nothing 
     Dim OldHREF As String = Nothing 
     Dim MainURL As New Uri(PageURL) 
     OldHREF = XpHref.Matches(html).Item(i).Value 
     Oldurl = OldHREF.Replace("href=", "").Replace("HREF=", "").Replace("""", "") 
     Dim NEWURL As New Uri(MainURL, Oldurl) 
     Dim NewHREF As String = "href=""" & NEWURL.AbsoluteUri & """" 
     NewSTR = NewSTR.Replace(OldHREF, NewHREF) 
    Next 
    html = NewSTR 
    Dim XpSRC As New Regex("(src="".*?"")", RegexOptions.IgnoreCase) 
    For i = 0 To XpSRC.Matches(html).Count - 1 
     Application.DoEvents() 
     Dim Oldurl As String = Nothing 
     Dim OldHREF As String = Nothing 
     Dim MainURL As New Uri(PageURL) 
     OldHREF = XpSRC.Matches(html).Item(i).Value 
     Oldurl = OldHREF.Replace("src=", "").Replace("src=", "").Replace("""", "") 
     Dim NEWURL As New Uri(MainURL, Oldurl) 
     Dim NewHREF As String = "src=""" & NEWURL.AbsoluteUri & """" 
     NewSTR = NewSTR.Replace(OldHREF, NewHREF) 
    Next 
    Return NewSTR 
End Function