VB.net Получение InnerText href с использованием HtmlAgilityPack

Теперь я обновил свой код (спасибо Тиму за помощь в обучении), который уже работает, но не дает нужных мне ссылок.

Вот мой рабочий код:

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim webClient As New System.Net.WebClient
        Dim WebSource As String = webClient.DownloadString("http://www.google.com.ph/search?hl=en&as_q=test&as_epq=&as_oq=&as_eq=&as_nlo=&as_nhi=&lr=&cr=countryCA&as_qdr=all&as_sitesearch=&as_occt=any&safe=images&tbs=ctr%3AcountryCA&as_filetype=&as_rights=#as_qdr=all&cr=countryCA&fp=1&hl=en&lr=&q=test&start=20&tbs=ctr:countryCA")

    Dim doc = New HtmlAgilityPack.HtmlDocument()
        doc.LoadHtml(WebSource)
        Dim links = GetLinks(doc, "test")
        For Each Link In links
            ListBox1.Items.Add(Link.ToString())
        Next
    End Sub


   Public Class Link
        Public Sub New(Uri As Uri, Text As String)
            Me.Uri = Uri
            Me.Text = Text
        End Sub
        Public Property Text As String
        Public Property Uri As Uri

        Public Overrides Function ToString() As String
            Return String.Format(If(Uri Is Nothing, "", Uri.ToString()))
        End Function
    End Class


    Public Function GetLinks(doc As HtmlAgilityPack.HtmlDocument, linkContains As String) As List(Of Link)
        Dim uri As Uri = Nothing
        Dim linksOnPage = From link In doc.DocumentNode.Descendants()
                          Where link.Name = "a" _
                          AndAlso link.Attributes("href") IsNot Nothing _
                          Let text = link.InnerText.Trim()
                          Let url = link.Attributes("href").Value
                          Where url.IndexOf(linkContains, StringComparison.OrdinalIgnoreCase) >= 0 _
                          AndAlso uri.TryCreate(url, UriKind.Absolute, uri)

        Dim Uris As New List(Of Link)()
        For Each link In linksOnPage
            Uris.Add(New Link(New Uri(link.url, UriKind.Absolute), link.text))
        Next

        Return Uris
    End Function

В настоящее время я новичок в этом HtmlAgilityPack, я все еще учусь, пожалуйста, поддержите меня.

Моя основная цель:

Образец ссылки: http://www.google.com.ph/search?hl=en&as_q=test&as_epq=&as_oq=&as_eq=&as_nlo=&as_nhi=&lr=&cr=countryCA&as_qdr=all&as_sitesearch=&as_occt=any&safe=images&tbs=ctr%3AcountryCA&as_filetype=&as_rights=#as_qdr=all&cr=countryCA&fp=1&hl=en&lr=&q=test&start=20&tbs=ctr:countryCA

Мои ожидаемые выходные данные ссылки, содержащие слово «тест»:

www.copetest.com/‎
www.testofhumanity.com/
www3.algonquincollege.com/testcentre/‎
www.lpitest.ca/‎
testtube.nfb.ca/‎
www.ieltscanada.ca/testdates.jsp‎
https://www.awinfosys.com/eassessment/fsa_fieldtest.htm‎

person Marc Intes    schedule 22.08.2013    source источник


Ответы (1)


Вместо этого вы должны использовать атрибут href, также обратите внимание, что .NET по умолчанию чувствителен к регистру.

For Each link As HtmlNode In htmlDoc.DocumentNode.SelectNodes("//a[@href]")
   Dim href = link.Attributes("href").Value
   If href.IndexOf("test", StringComparison.OrdinalIgnoreCase) >= 0 Then
       ListBox1.Items.Add(href)
       ' or
       ListBox1.Items.Add(link.InnerText)
   End If
Next 

Вот метод, который должен возвращать все ссылки в документе как List(Of Link). Link — это пользовательский класс с двумя атрибутами, один для текста, а другой для Uri:

Public Class Link
    Public Sub New(Uri As Uri, Text As String)
        Me.Uri = Uri
        Me.Text = Text
    End Sub
    Public Property Text As String
    Public Property Uri As Uri

    Public Overrides Function ToString() As String
        Return String.Format("{0} [{1}]", Text, If(Uri Is Nothing, "", Uri.ToString()))
    End Function
End Class

Public Function GetLinks(doc As HtmlAgilityPack.HtmlDocument) As List(Of Link)
    Dim uri As Uri = Nothing
    Dim linksOnPage = From link In doc.DocumentNode.Descendants()
                      Where link.Name = "a" _
                      AndAlso link.Attributes("href") IsNot Nothing _
                      Let text = link.InnerText.Trim()
                      Let url = link.Attributes("href").Value
                      Where uri.TryCreate(url, UriKind.Absolute, uri)

    Dim Uris As New List(Of Link)()
    For Each link In linksOnPage
        Uris.Add(New Link(New Uri(link.url, UriKind.Absolute), link.text))
    Next

    Return Uris
End Function

Вот запрошенная перегрузка, которая проверяет, содержит ли URL заданный текст:

Public Function GetLinks(doc As HtmlAgilityPack.HtmlDocument, linkContains As String) As List(Of Link)
    Dim uri As Uri = Nothing
    Dim linksOnPage = From link In doc.DocumentNode.Descendants()
                      Where link.Name = "a" _
                      AndAlso link.Attributes("href") IsNot Nothing _
                      Let text = link.InnerText.Trim()
                      Let url = link.Attributes("href").Value
                      Where url.IndexOf(linkContains, StringComparison.OrdinalIgnoreCase) >= 0 _
                      AndAlso uri.TryCreate(url, UriKind.Absolute, uri)

    Dim Uris As New List(Of Link)()
    For Each link In linksOnPage
        Uris.Add(New Link(New Uri(link.url, UriKind.Absolute), link.text))
    Next

    Return Uris
End Function

Отредактировано теперь протестировано, работает, используйте его следующим образом:

Dim site = File.ReadAllText("C:\Temp\website_test.htm")
Dim doc = New HtmlAgilityPack.HtmlDocument()
doc.LoadHtml(site)
Dim links = GetLinks(doc)
For Each Link In links
    ListBox1.Items.Add(Link.ToString())
Next
person Tim Schmelter    schedule 22.08.2013
comment
что я буду называть для отображения ссылок? я пробовал link.InnerText, но все равно безрезультатно - person Marc Intes; 22.08.2013
comment
@MarcIntes: Почему не href или link.InnerText? Отредактировал мой ответ. - person Tim Schmelter; 22.08.2013
comment
Теперь программа отображает ссылки, но включает ненужные, начинающиеся с /search?, /url?. Я хочу отображать только ссылки, начинающиеся с http://, и на них все еще есть слово test. Это возможно? - person Marc Intes; 22.08.2013
comment
Я снова попробовал link.InnerText, но он не отображает ссылку. вместо этого он отображает такие слова, как «Изображения», «Карты», «Играть», «Youtube», «Перевести», «Книги». - person Marc Intes; 22.08.2013
comment
@MarcIntes: попробуйте мой добавленный метод для обнаружения всех ссылок, хотя я еще не тестировал его. - person Tim Schmelter; 22.08.2013
comment
Вот сгенерированный вывод URL, который я извлек в текстовый файл. Они выглядят беспорядочно, на самом деле это не формат URL. Не тот ожидаемый результат, которого я хотел, но я хочу усовершенствовать эту программу. Я приложу его в текстовом файле. mediafire.com/download/8hpv6e5hcu8e87c/linkOUTPUT.txt - person Marc Intes; 22.08.2013
comment
попробуйте проверить это с помощью этой ссылки поиска Google, которую я использую google.com.ph/ - person Marc Intes; 22.08.2013
comment
Я протестировал его с помощью ссылки Google, которую вы разместили, и извлечения кода 44 действительных URL-адреса + текст (обратите внимание, что я переопределил ToString). - person Tim Schmelter; 22.08.2013
comment
Я только что проверил ваш код, и да, он работает. но я хочу иметь возможность отображать только ссылки со словом test. Является ли это возможным? где должно быть помещено условие. Мне очень жаль, я новичок в этом HtmlAgilityPack, но я хочу учиться. - person Marc Intes; 22.08.2013
comment
@MarcIntes: Вы хотите искать данную строку в тексте, или в ссылке, или в том и другом, это должно быть целое слово или подстрока? Тем не менее, я уже показал способ выше, просто добавьте href.IndexOf("test", ... к запросу LINQ как Where или добавьте его в следующий цикл в If. - person Tim Schmelter; 22.08.2013
comment
указанное слово должно быть в ссылке, а не в самом слове. Например, если я укажу его для тестирования. Сгенерированные ссылки должны содержать слово test. www.drivetest.ca/ www.drivetest.ca/EN/bookatest/Pages/Road-Test-Booking.aspx www.drivetest.ca/EN/drivereducation/Pages/Driver-Testing.aspx www.cic.gc.ca/ английский/гражданство/cit-test.asp - person Marc Intes; 22.08.2013
comment
где именно я должен разместить условие? Я совсем запутался. - person Marc Intes; 22.08.2013
comment
@MarcIntes: я отредактировал свой ответ, включив в него перегрузку, которая фильтрует ссылки по заданному тексту (без учета регистра). Найдите запрошенную перегрузку, которая проверяет, содержит ли URL заданный текст. - person Tim Schmelter; 22.08.2013
comment
Я попробовал код и взял за основу слово test. Теперь он не показывает никаких ссылок. Я все еще основываюсь на URL-адресе поиска Google, который у меня есть. - person Marc Intes; 22.08.2013
comment
@MarcIntes: Итак, вы использовали это таким образом: Dim links = GetLinks(doc, "test")? Я протестировал его с помощью вашей ссылки на гугл-поиск, и он вернул 27 ссылок, где URL-адрес содержал тест. - person Tim Schmelter; 22.08.2013
comment
@MarcIntes: я сохранил сайт Google в виде текстового файла и использовал File.ReadAllText и HtmlDocument.LoadHtml(text) для загрузки всего html. Затем я получил 27 ссылок с 27 различными текстовыми свойствами и 27 различными URL-адресами, где каждый URL-адрес содержит текст подстроки (регистр не имеет значения). Однако я предполагаю, что на вопрос дан ответ, не так ли? - person Tim Schmelter; 22.08.2013
comment
Да, это ответ, однако результаты связаны только с Google. Моя основная цель - получить ссылки из результатов поиска Google. Мне очень нужно, чтобы этот проект был завершен. чего-то не хватает, но я не знаю, как. - person Marc Intes; 22.08.2013
comment
Пожалуйста, проверьте мой пост. я отредактировал нижнюю часть с образцом ссылки и тем, что я хочу извлечь из этой ссылки. - person Marc Intes; 22.08.2013