От новичка до гуру: Курсы программирования на CyberDuff

Разбор с помощью Async, HtmlAgilityPack и XPath

Я столкнулся с довольно странной проблемой. Это очень сложно объяснить, поэтому, пожалуйста, потерпите меня, но в основном вот краткое введение:

  • Я новичок в асинхронном программировании, но не смог найти проблему в своем коде.
  • Раньше я использовал HtmlAgilityPack, но никогда не использовал версию .NET 4.5.
  • Это учебный проект, я не пытаюсь соскабливать или что-то в этом роде.

По сути, происходит следующее: я извлекаю страницу из Интернета, загружаю ее через поток в HtmlDocument, затем извлекаю из нее определенные HtmlNodes, используя выражения XPath. Вот кусок упрощенного кода:

            myStream = await httpClient.GetStreamAsync(string.Format("{0}{1}", SomeString, AnotherString);

            using (myStream)
            {
                myDocument.Load(myStream);
            }

HTML извлекается правильно, но HTML-коды HtmlNodes, извлеченные с помощью XPath, искажаются. Вот пример фрагмента HTML, который я получил в ответе, взятом из Fiddler:

                    <div id="menu">
   <div id="splash">
      <div id="menuItem_1" class="ScreenTitle"  >Horse Racing</div>
      <div id="menuItem_2" class="Title"  >Wednesday Racing</div>
      <div id="subMenu_2">
         <div id="menuItem_3" class="Level2"  >&#187;  <a href="../coupon/?ptid=4020&amp;key=2-70-70-22361707-2-20181217-0-0-1-0-0-4020-0-36200255-1-0-0-0-0">21.51 Britannia Way</a></div>
         <div id="menuItem_4" class="Level2"  >&#187;  <a href="../coupon/?ptid=4020&amp;key=2-70-70-22361710-2-20181217-0-0-1-0-0-4020-0-36200258-1-0-0-0-0">21.54 Britannia Way</a></div>
         <div id="menuItem_5" class="Level2"  >&#187;  <a href="../coupon/?ptid=4020&amp;key=2-70-70-22361713-2-20181217-0-0-1-0-0-4020-0-36200261-1-0-0-0-0">21.57 Britannia Way</a></div>
         <div id="menuItem_6" class="Level2"  >&#187;  <a href="../coupon/?ptid=4020&amp;key=2-70-70-22361716-2-20181217-0-0-1-0-0-4020-0-36200264-1-0-0-0-0">22.00 Britannia Way</a></div>
         <div id="menuItem_7" class="Level2"  >&#187;  <a href="../coupon/?ptid=4020&amp;key=2-70-70-22361719-2-20181217-0-0-1-0-0-4020-0-36200267-1-0-0-0-0">22.03 Britannia Way</a></div>
         <div id="menuItem_8" class="Level2"  >&#187;  <a href="../coupon/?ptid=4020&amp;key=2-70-70-22361722-2-20181217-0-0-1-0-0-4020-0-36200270-1-0-0-0-0">22.06 Britannia Way</a></div>
      </div>
   </div>
</div>

XPath, который я использую, на 100% верен, потому что он работает в браузере на той же странице, но вот пример тега a, который он извлекает с ранее показанной страницы:

<a href="./coupon/?ptid=4020&amp;key=2-70-70-22361710-2-20181217-0-0-1-0-0-4020-0-36200258-1-0-0-0-0"">1.54 Britannia Way</</a>

А вот оригинал, который я для простоты скопировал сверху:

<a href="../coupon/?ptid=4020&amp;key=2-70-70-22361710-2-20181217-0-0-1-0-0-4020-0-36200258-1-0-0-0-0">21.54 Britannia Way</a></div>

Как видите, InnerText значительно изменился, как и URL. Очевидно, моя программа не работает, но я не знаю, как это сделать. Что может быть причиной этого? Это ошибка в HtmlAgilityPack? Пожалуйста, порекомендуйте! Спасибо за прочтение!


Ответы:


1

Не делайте предположения, что выражение XPath работает в вашем браузере (после преобразования DOM, возможно, загрузка данных с помощью AJAX, ...). Кажется, это сайт с котировками ставок, я предполагаю, что они загружают данные с помощью некоторых вызовов javascript.

Проверьте, соответствует ли ваше выражение XPath исходному коду страницы (например, полученному с помощью wget или нажав «Просмотреть исходный код» в браузере — не используйте для этого Firebug/...!

Если сайт использует AJAX для загрузки данных, вам может повезти с помощью Firebug для отслеживания того, какие ресурсы извлекаются во время загрузки страницы. Зачастую это JSON- или XML-файлы, которые очень легко парсить, и работать с ними даже проще, чем парсить веб-сайт с ужасной мешаниной HTML.

Обновление. В этом особом случае сайт перенаправляет пользователей, не отправляющих заголовок Accept-Language, на страницу выбора языка. Отправьте такой заголовок, чтобы получить то же содержимое, что и браузер. В завитке это будет выглядеть так:

curl -H "Accept-Language: en-US;q=0.6,en;q=0.4" https://mobile.bet365.com/sport/splash/Default.aspx?Sport
11.06.2014
  • Привет, спасибо за ваш комментарий, но сайт не загружает данные с помощью AJAX. Показанный выше HTML-код — это необработанный HTML-код, который я получил из ответа, и, как вы можете видеть, HTML-код, полученный с помощью выражения XPath, искажен (некоторые данные отсутствуют или добавлены). 12.06.2014
  • Мы не сможем вам помочь, если вы не предоставите всю необходимую информацию: URL-адрес страницы, выражения XPath. Проблема, которую невозможно воспроизвести, обычно не устраняется. 12.06.2014
  • URL-адрес — https://mobile.bet365.com/sport/splash/Default.aspx?Sport=2&key=2&L=1, затем щелкните сегодняшние гонки, и выражение XPath — //div[@id='subMenu_2']//a. Даже если выражение было неверным, оно не должно получить ничего или получить что-то другое, кроме того, что я хочу, получить не то, что я хочу, но с другим HTML. Может ли это быть ошибкой в ​​HTMLAGILITYPACK? Можешь попробовать воспроизвести? 12.06.2014
  • Если вы загрузите сайт с помощью wget/curl, вы поймете, что вместо этого вы будете перенаправлены на другую страницу, содержащую средство выбора языка. 12.06.2014
  • Пожалуйста, прочитайте, что я говорю. Я уже имел дело со страницей языка, я получаю именно тот HTML, который я показал выше. Я хочу знать, почему и как возможно, что выражение XPath получает HTML, которого нет на странице!! 12.06.2014
  • Вы никогда не писали о том, как обращаться с выбором языка. XPath никогда не вернет ничего, кроме страницы. Вы полностью уверены в получении того же HTML, что и в браузере, т.е. сбрасывая то, что вы получили от HTTP-запроса? Прочтите, пожалуйста, о том, как опубликовать SSCCE, так как вся дальнейшая информация является просто догадками. 12.06.2014
  • Я свяжусь с вами завтра, но HTML-код, который я разместил выше, был взят из ответа, который я получил от сервера. Я проверю, что на самом деле было загружено в HtmlDocument, чтобы быть уверенным. 12.06.2014
  • Что также может быть (таким образом, действительно тщательно проверьте, например, путем diffing вывода: некоторые из этих сайтов не любят, когда их очищают (угадайте, почему) и имеют некоторые контрмеры. Обработка неверных/поддельных данных для распознанных попыток очистки может быть одной из из тех. 12.06.2014
  • Я думал об этом раньше, но, как я уже сказал, я разместил точный HTML-код, который я получил, и, как вы можете видеть, это правильные данные. Это может быть что-то с кодировкой HtmlDocument; Я проверю завтра. Спасибо. 12.06.2014
  • Я разобрался, дружище, большое спасибо за помощь. Я разместил ответ ниже! Надеюсь, это поможет кому-то! 13.06.2014

  • 2

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

    Надеюсь, это сэкономит вам время, которое я потерял!

    12.06.2014
    Новые материалы

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

    Игра в прятки с данными
    Игра в прятки с данными Я хотел бы, чтобы вы сделали мне одолжение и ответили на следующие вопросы. Гуглить можно в любое время, здесь никто не забивается. Сколько регионов в Гане? А как..

    «Раскрытие математических рассуждений с помощью Microsoft MathPrompter и моделей больших языков»
    TL;DR: MathPrompter от Microsoft показывает, как использовать математические рассуждения с большими языковыми моделями; 4-этапный процесс для улучшения доверия и рассуждений в математических..

    Раскройте свой потенциал в области разработки мобильных приложений: Абсолютная бесплатная серия
    Глава 6: Работа в сети и выборка данных Глава 1: Введение в React Native Глава 2: Основы React Native Глава 3: Создание пользовательского интерфейса с помощью React Native Глава 4:..

    Все о кейсах: Camel, Snake, Kebab & Pascal
    В программировании вы сталкивались с ними при именовании переменной, класса или функции. Поддержание согласованности типов и стилей случаев делает ваш код более читабельным и облегчает совместную..

    Как работает дистанционное парное программирование и почему оно может изменить вашу жизнь
    Серебряная пуля от одиночества и отвлекающих факторов во время обучения программированию Независимо от того, работаете ли вы или учитесь удаленно, велика вероятность, что одиночество и..

    🔥🔥👉Питон 🆚Javascript👈🔥🔥
    Сегодня Python и Javascript потрясают мир в области ИТ. Все хотят выучить Python и Javascript, чтобы получить высокооплачиваемую работу. Различные фреймворки Python и Javascript расширяют..