C# преобразование относительно абсолютных ссылок в строке HTML

Я зеркально отображаю некоторые внутренние веб-сайты для резервного копирования. На данный момент я в основном использую этот код c#:

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

Это просто в основном загружает html и в массив байтов. Это то, чего я хочу. Проблема, однако, в том, что ссылки в html большую часть времени относительны, а не абсолютны.

Я в основном хочу добавить все, что угодноhttp://domain.is перед относительной ссылкой Как преобразовать ее в абсолютную ссылку, которая будет перенаправление на исходный контент. Я в основном просто обеспокоен href= и src=. Есть ли регулярное выражение, которое будет охватывать некоторые из основных дел?

Edit [Моя Попытка]:

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

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

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

10 ответов


самым надежным решением было бы использовать HTMLAgilityPack как предлагали другие. Однако разумное решение с использованием регулярных выражений возможно с помощью заменить перегрузка, которая принимает 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, содержащих значения с двойными кавычками, начиная с косой черты. Для каждого спички, static Uri.TryCreate метод используется для определения, является ли значение допустимым относительным uri.

обратите внимание, что это решение не обрабатывает значения атрибутов с одиночными кавычками и, конечно же, не работает на плохо сформированном HTML с неквотируемыми значениями.


вы должны использовать пакет HtmlAgility для загрузки HTML, доступа ко всем hrefs с его помощью, а затем использовать класс Uri для преобразования из относительного в абсолютный по мере необходимости.

см., например http://blog.abodit.com/2010/03/a-simple-web-crawler-in-c-using-htmlagilitypack/


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подход is наверное (непроверенный) отображение на:

        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 здесь, но применить трюк Uri к некоторому коду с помощью DOM, возможно XmlDocument (если xhtml) или HTML Agility Pack (в противном случае), глядя на все //@src или //@href атрибуты.


хотя это может быть не самым надежным решением, оно должно выполнить работу.

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

можно использовать HTMLAgilityPack выполнить это. Вы бы сделали что-то по этим (не проверенным) линиям:

  • загрузить url
  • выбрать все ссылки
  • загрузите ссылку в Uri и проверьте, является ли он относительным, если он относительный преобразовать его в абсолют
  • обновите значение ссылки с помощью нового Ури
  • сохраните файл

вот несколько примеры:

относительно абсолютных путей в 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/


Я думаю, что url имеет тип string. Используйте 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);

просто используйте эту функцию

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

простая функция

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

}

Я знаю, что это более старый вопрос, но я понял, как это сделать с довольно простым регулярным выражением. Это хорошо работает для меня. Он обрабатывает 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);

это то, что вы ищете, этот фрагмент кода может преобразовать все относительные 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