aspNetHidden div не обслуживается в зависимости от клиента - PullRequest
6 голосов
/ 26 мая 2020

Я разрабатываю приложение C#, которое получает веб-страницы и обрабатывает их содержимое построчно. Для этого я использую класс HttpClient и читаю содержимое страницы через ReadAsStreamAsync(). Затем я считываю поток в линейный массив и перебираю его. Пока все хорошо.

Однако HTML, которое я получаю с помощью этого метода, не идентично HTML, которое я наблюдаю, если перехожу на веб-страницу с помощью Chrome или Edge и использую View Источник, чтобы попасть в HTML. В частности, скрытые элементы input __VIEWSTATE и __VIEWSTATEGENERATOR окружены элементами div с class="aspNetHidden", когда я использую браузер, но не когда я получаю HTML программно. Это разрушает мою логику отслеживания строк c, поскольку на странице есть лишние строки, видимые браузером по отношению к странице, которую я получаю в коде.

EDIT . После некоторого тестирования я уверен, что заголовок пользовательского агента, используемый клиентом, определяет, обслуживается ли class="aspNetHidden" div. Когда я использую c пользовательский агент своего браузера ("Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (K HTML, как Gecko) Chrome / 83.0.4103.61 Safari / 537.36 Edg / 83.0. 478,37 "), обслуживается div; если я использую какой-либо другой агент, такой как «Тестовый клиент», div не обслуживается.

Тогда мой вопрос: есть ли какая-либо документация о том, какие строки пользовательского агента вызывают обслуживание div и чего нет? Кроме того, могу ли я предотвратить это?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 02 июня 2020

Короче говоря, это не задокументировано / указано в терминах пользователей, а не в виде возможностей браузера.

В зависимости от используемого агента браузера настраивается набор возможностей.
Эти возможности настраиваются в .browser файлы конфигурации на веб-сервере.
Например, .NET 4 вы найдете эти файлы в %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\config\browsers,
например, chrome.browser, iphone.browser, et c.

Такой * Файл 1013 * содержит возможность tagwriter.
Например, chrome.browser:

<browsers>
    <!-- Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.1 (KHTML, like Gecko) Chrome/2.0.168.0 Safari/530.1 -->
    <browser id="Chrome" parentID="WebKit">
        <identification>
            <userAgent match="Chrome/(?'version'(?'major'\d+)(\.(?'minor'\d+)?)\w*)" />
        </identification>

        <capabilities>
          <capability name="browser"   value="Chrome" />
          <capability name="tagwriter" value="System.Web.UI.HtmlTextWriter" />

          <!-- ... -->  
        </capabilities>
    </browser>
</browsers> 

Возможность tagwriter определяет, будет ли создан экземпляр System.Web.UI.HtmlTextWriter или System.Web.UI.Html32TextWriter для записи вывод.

Конфигурация по умолчанию в файле Default.browser объявляет tagwriter как:

<capability name="tagwriter" value="System.Web.UI.Html32TextWriter" />

Кроме того, если возможность tagwriter отсутствует, используется Html32TextWriter .
Из справочного источника Microsoft :

internal HtmlTextWriter CreateHtmlTextWriterInternal(TextWriter tw) {
    Type tagWriter = TagWriter;
    if (tagWriter != null) {
        return Page.CreateHtmlTextWriterFromType(tw, tagWriter);
    }

    // Fall back to Html 3.2
    return new Html32TextWriter(tw);
}

Html32TextWriter заявляет, что не отображает div вокруг скрытых полей ввода.
Из Справочный источник Microsoft :

internal override bool RenderDivAroundHiddenInputs {
    get {
        return false;
    }
}

HtmlTextWriter действительно возвращает true для RenderDivAroundHiddenInputs, см. Micros .

Еще немного информации обо всем этом здесь .


Что вы можете сделать.

Если вы всегда хотите обертку div, используйте один из хорошо известных юзерагентов, в противном случае используйте настраиваемый, например Test Client, который вы уже используете.
Если вы контролируете запрашиваемый веб-сайт, вы можете настроить собственный .browser файл для вашего пользовательского агента ... , но я бы предпочел не go таким образом ...

При выполнении запроса просто установите соответствующий заголовок User-Agent запроса на вашем HttpClient, например:

var client = new HttpClient();
var userAgent = "Test Client"; // Or "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37"
client.DefaultRequestHeaders.Add("User-Agent", userAgent);
1 голос
/ 29 мая 2020

Это может произойти по ряду причин, одна из наиболее вероятных - это та, в которой @ thangadurai упоминается There may be a script which gets executed onload of the html and changes the html content.. Этого можно избежать, используя среду тестирования пользовательского интерфейса, такую ​​как Selenium, или используя headless Chrome программно.

Одна из других возможных причин - это реализация, зависимая от User-Agent. Это можно просто решить, изменив заголовок User-Agent.

EDIT: Если вы управляете веб-страницей, вы, вероятно, можете отключить ViewState, если это так. Поведение может быть основано на обнаружении возможностей User-Agent. Для обработки вы можете go с любой строкой и сделать его stati c при отправке запроса, хотя это может быть не так надежно. Другой метод обработки без синтаксического анализа может заключаться в использовании регулярного выражения для соответствия определенным тегам c. Особенности принятия решения о рендеринге ViewState были красиво описаны @pfx здесь .

...