2010-10-01 47 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