aspNetHidden div 未根据客户端提供服务
aspNetHidden div not being served depending on client
我正在开发一个 C# 应用程序,它获取网页并逐行处理它们的内容。为此,我使用 HttpClient
class,并通过 ReadAsStreamAsync()
读取页面内容。然后我将流读入一个线数组并对其进行迭代。到目前为止一切顺利。
但是,我使用此方法获得的 HTML 与我使用 Chrome 或 Edge 导航到网页并使用 View 时观察到的 HTML 不同源码获取到HTML。特别是,当我使用浏览器时,__VIEWSTATE 和 __VIEWSTATEGENERATOR 隐藏的 input
元素被带有 class="aspNetHidden"
的 div
元素包围,但当我得到HTML 以编程方式。这破坏了我的行跟踪逻辑,因为浏览器看到的页面中有额外的行,与我在代码中获取的页面相关。
编辑。经过一些测试,我确信客户端使用的用户代理 header 决定是否提供 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
;如果我使用其他代理,例如 "Test Client",则不会提供 div
。
那么我的问题是,是否有任何文档说明哪些用户代理字符串会导致 div
得到服务,哪些不会?另外,我可以防止这种情况发生吗?
谢谢。
发生这种情况的原因有很多,最有可能的原因之一就是 @thangadurai 提到的 There may be a script which gets executed onload of the html and changes the html content.
。这可以通过使用 UI 测试框架(例如 Selenium)或以编程方式使用无头 Chrome 来避免。
另一个可能的原因是 User-Agent
依赖实现。这可以通过更改 User-Agent
header.
来简单解决
编辑: 如果您控制网页,您可能会禁用 ViewState(如果是这种情况)。该行为可能基于检测 User-Agent
功能。对于您的处理,您可以使用任一字符串并在发送请求时将其设为静态,尽管它可能不那么可靠。另一种无需解析的处理方法是使用正则表达式来匹配特定标签。 @pfx here.
很好地描述了决定呈现 ViewState 的细节
简而言之,不是documented/specified用户代理,而是浏览器功能。
基于浏览器用户代理设置了一组功能。
这些功能在网络服务器上的 .browser
配置文件中配置。
例如.NET 4
您在 %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\config\browsers
、
中找到这些文件
例如chrome.browser
、iphone.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.HtmlTextWriter
或 System.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
return true
RenderDivAroundHiddenInputs
,
见 Microsoft reference source.
关于这一切的更多阅读 here。
你能做什么。
如果您总是想要包装 div
,请使用一种众所周知的用户代理,否则使用自定义用户代理,例如您已经在使用的 Test Client
。
如果您控制被请求的网站,您可以为您的自定义用户代理设置一个自定义 .browser
文件...但我不想那样做 ...
发出请求时,只需在您的 HttpClient
上设置适当的 User-Agent
请求 header,例如:
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);
我正在开发一个 C# 应用程序,它获取网页并逐行处理它们的内容。为此,我使用 HttpClient
class,并通过 ReadAsStreamAsync()
读取页面内容。然后我将流读入一个线数组并对其进行迭代。到目前为止一切顺利。
但是,我使用此方法获得的 HTML 与我使用 Chrome 或 Edge 导航到网页并使用 View 时观察到的 HTML 不同源码获取到HTML。特别是,当我使用浏览器时,__VIEWSTATE 和 __VIEWSTATEGENERATOR 隐藏的 input
元素被带有 class="aspNetHidden"
的 div
元素包围,但当我得到HTML 以编程方式。这破坏了我的行跟踪逻辑,因为浏览器看到的页面中有额外的行,与我在代码中获取的页面相关。
编辑。经过一些测试,我确信客户端使用的用户代理 header 决定是否提供 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
;如果我使用其他代理,例如 "Test Client",则不会提供 div
。
那么我的问题是,是否有任何文档说明哪些用户代理字符串会导致 div
得到服务,哪些不会?另外,我可以防止这种情况发生吗?
谢谢。
发生这种情况的原因有很多,最有可能的原因之一就是 @thangadurai 提到的 There may be a script which gets executed onload of the html and changes the html content.
。这可以通过使用 UI 测试框架(例如 Selenium)或以编程方式使用无头 Chrome 来避免。
另一个可能的原因是 User-Agent
依赖实现。这可以通过更改 User-Agent
header.
编辑: 如果您控制网页,您可能会禁用 ViewState(如果是这种情况)。该行为可能基于检测 User-Agent
功能。对于您的处理,您可以使用任一字符串并在发送请求时将其设为静态,尽管它可能不那么可靠。另一种无需解析的处理方法是使用正则表达式来匹配特定标签。 @pfx here.
简而言之,不是documented/specified用户代理,而是浏览器功能。
基于浏览器用户代理设置了一组功能。
这些功能在网络服务器上的 .browser
配置文件中配置。
例如.NET 4
您在 %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\config\browsers
、
中找到这些文件
例如chrome.browser
、iphone.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.HtmlTextWriter
或 System.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
return true
RenderDivAroundHiddenInputs
,
见 Microsoft reference source.
关于这一切的更多阅读 here。
你能做什么。
如果您总是想要包装 div
,请使用一种众所周知的用户代理,否则使用自定义用户代理,例如您已经在使用的 Test Client
。
如果您控制被请求的网站,您可以为您的自定义用户代理设置一个自定义 .browser
文件...但我不想那样做 ...
发出请求时,只需在您的 HttpClient
上设置适当的 User-Agent
请求 header,例如:
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);