【问题标题】:aspNetHidden div not being served depending on clientaspNetHidden div 未根据客户端提供服务
【发布时间】:2020-05-26 15:24:16
【问题描述】:

我正在开发一个获取网页并逐行处理其内容的 C# 应用程序。为此,我使用HttpClient 类,并通过ReadAsStreamAsync() 读取页面内容。然后我将流读入一个线阵列并对其进行迭代。到目前为止一切顺利。

但是,我使用此方法获得的 HTML 与我使用 Chrome 或 Edge 导航到网页并使用查看源代码访问 HTML 时观察到的 HTML 不同。特别是,当我使用浏览器时,隐藏的 __VIEWSTATE 和 __VIEWSTATEGENERATOR input 元素被带有 class="aspNetHidden"div 元素包围,但当我以编程方式获取 HTML 时则不然。这破坏了我的行跟踪逻辑,因为浏览器看到的页面中有与我在代码中获取的页面相关的额外行。

编辑。经过一些测试,我确信客户端使用的用户代理标头决定了是否提供 class="aspNetHidden" div。当我模仿浏览器的用户代理(“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")时,div送达;如果我使用“测试客户端”等其他代理,则不会提供div

然后我的问题是,是否有任何文档说明哪些用户代理字符串导致div 被提供,哪些不提供?另外,我可以防止这种情况发生吗?

谢谢。

【问题讨论】:

  • 可能有一个脚本会在加载 html 时执行并更改 html 内容。您在浏览器(查看源代码)上看到的 HTML 可能不必与您使用 HttpClient 阅读的 HTML 相匹配。
  • 你是如何解析 html 的?如果您使用 Html Agility Pack 之类的内容,则行数无关紧要。
  • @VDWWD:我不是在解析 HTML,而是在做一些面向行的处理。

标签: c# html asp.net dotnet-httpclient


【解决方案1】:

简而言之,它不是在用户代理方面记录/指定,而是在浏览器功能方面。

根据浏览器用户代理设置了一组功能。
这些功能在网络服务器上的.browser 配置文件中进行配置。
例如.NET 4 您可以在 %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\config\browsers 中找到这些文件,
例如chrome.browseriphone.browser

这样的.browser 文件包含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.HtmlTextWriterSystem.Web.UI.Html32TextWriter 以写入输出。

Default.browser文件中的默认配置,将tagwriter声明为:

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

此外,如果tagwriter 功能缺失,则正在使用Html32TextWriter
来自Microsoft reference source

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 reference source

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

HtmlTextWriter 确实为RenderDivAroundHiddenInputs 返回true, 见Microsoft reference source

更多关于这一切的阅读here


你能做什么。

如果您总是想要包装 div,请使用众所周知的用户代理之一,否则请使用您已经在使用的 Test Client 之类的自定义用户代理。
如果您控制所请求的网站,则可以为您的自定义用户代理设置自定义 .browser 文件...但我不想那样做 ...

发出请求时,只需在您的HttpClient 上设置适当的User-Agent 请求标头,例如:

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

【讨论】:

    【解决方案2】:

    发生这种情况的原因有很多,其中最可能的原因之一是@thangadurai 提到的There may be a script which gets executed onload of the html and changes the html content.。这可以通过使用诸如 Selenium 之类的 UI 测试框架或以编程方式使用无头 Chrome 来避免。

    其他可能的原因之一是 User-Agent 依赖实现。这可以通过更改User-Agent 标头来简单地解决。

    编辑:如果您控制网页,您可能会禁用 ViewState。该行为可能基于检测User-Agent 功能。对于您的处理,您可以使用任一字符串并在发送请求时将其设为静态,尽管它可能不那么可靠。另一种无需解析的处理方法是使用正则表达式来匹配特定标签。 @pfx here 很好地描述了决定渲染 ViewState 的细节。

    【讨论】:

    • 谢谢。我会检查这个并回复你。
    • 我已经彻底检查了页面,似乎没有任何脚本可以改变 HTML。
    • 我也检查了代理,这很有效。我正在相应地更新我的问题。谢谢你的建议。
    • 添加了可能解决方案的编辑,也提到了@pfx 答案,因为他更好地描述了渲染的细节。我希望这能解决您的问题。
    猜你喜欢
    • 1970-01-01
    • 2019-09-22
    • 2015-04-18
    • 1970-01-01
    • 2023-03-24
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    相关资源
    最近更新 更多