2010-10-01 14 views
8

Estoy duplicando algunos sitios web internos con fines de copia de seguridad. A partir de ahora, básicamente, utilizo este código C#:C# Convert Relative to Absolute Links en HTML String

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

Esto, básicamente, sólo descarga el html y en una matriz de bytes. Esto es lo que quiero. Sin embargo, el problema es que los enlaces dentro del html son la mayoría de las veces relativos, no absolutos.

Básicamente quiero agregar lo que sea completo http://domain.is antes del enlace relativo como para convertirlo a un enlace absoluto que redireccionará al contenido original. Básicamente estoy preocupado con href = y src =. ¿Hay alguna expresión de expresiones regulares que cubra algunos de los casos básicos?

Editar [mi intento]:

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

duplicados de http://stackoverflow.com/questions/3836644/c-convert-relative-to-absolute-links-in-html-string/3836790 # 3836790 que preguntaste hoy! –

Respuesta

8

La solución más robusta sería utilizar el HTMLAgilityPack como han sugerido otros. Sin embargo, una solución razonable el uso de expresiones regulares es posible utilizando la sobrecarga de Replace que tiene un delegado MatchEvaluator, de la siguiente manera:

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); 

Los ejemplos de búsquedas anteriores de atributos denominados src y href que contiene los valores entre comillas dobles que comienzan con una barra inclinada. Para cada coincidencia, se utiliza el método estático Uri.TryCreate para determinar si el valor es un valor relativo relativo válido.

Tenga en cuenta que esta solución no maneja los valores de atributos entre comillas simples y ciertamente no funciona en HTML mal formado con valores sin comillas.

+1

Agregué una edición que funciona al menos en mis pocos casos de prueba. En cuanto a las expresiones regulares, parece bastante similar, pero su código parece mucho más complicado. Honestamente, nunca he usado MatchEvaluator y las cosas para delegados; es tu código mejor? – Gary

+0

El uso de MatchEvaluator le permite simplificar enormemente el patrón de expresiones regulares y, en su lugar, utilizar el método Uri.TryCreate, mucho más robusto. Una expresión regular que coincida con todos los posibles URI sería extremadamente compleja. –

+0

¿Qué tal el rendimiento? Y gracias por la respuesta! – Gary

0

creo url es de tipo cadena. Uri utilizar en su lugar con un URI de base que apuntan a su dominio:

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

¿Esto cambia los enlaces dentro del html en myUri de relativo a absoluto, o es esta una mejor práctica para usar el WebClient? – Gary

1

Si bien esto puede no ser el más robusto de soluciones que debe hacer el trabajo.

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

Debe utilizar el paquete HtmlAgility para cargar el código HTML, acceder a todos los hrefs usarlo, y luego utilizar la clase Uri convertir de relativa a absoluta como sea necesario.

Véase, por ejemplo http://blog.abodit.com/2010/03/a-simple-web-crawler-in-c-using-htmlagilitypack/

+0

intenté con tu ejemplo, pero parece que hay un error. si tengo una baseUrl como 'http: // ww.baseurl.com/somedir' y trato de crear una ruta de acceso absoluta agregando'/login.php' usando su método, obtengo 'http://ww.baseurl.com/login.php' en lugar de 'http: // ww.baseurl.com/somedir/login.php' – Smith

1

Se podría utilizar el HTMLAgilityPack lograr esto. Se podría hacer algo a lo largo de estos (no probado) líneas:

  • cargar la URL
  • Seleccionar todos los enlaces
  • Cargar el enlace en una Uri y comprobar si es relativa Si convertido relativa a absoluta
  • actualizar el valor de los enlaces con la nueva uri
  • guardar el archivo

Éstos son algunos ejemplos:

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; 

cuales con su Regex enfoque basado es probablemente (no probado) asignables a:

 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); 

También aconsejaría no utilizar Regex aquí, pero para aplicar el Uri truco a algún código usando un DOM, quizás XmlDocument (si xhtml) o HTML Agility Pack (de lo contrario), mirando todos los atributos //@src o //@href.

0

sólo tiene que utilizar esta función

'# 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

función simple

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

Sé que esto es una cuestión más viejo, pero me di cuenta de cómo hacerlo con una bastante simple expresión regular. Funciona bien para mí Maneja http/https y también el relativo a la raíz y el relativo al directorio actual.

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

esto es lo que está buscando, este fragmento de código puede convertir todos los URL relativos a absoluta dentro de cualquier código 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