如何使用C#的IndexOf方法解析HTML中的参数及其值?提取入院日期的代码返回错误结果,请求排查问题
帮你搞定HTML里的入院日期提取问题
嘿,我来帮你看看这段代码的问题哈!你现在的代码之所以返回错误内容,主要是踩了两个常见的坑:
第一个坑:硬编码的HTML片段太死板
你定义的parseString是完全固定的一段HTML,但实际页面里的HTML可没这么听话——比如style属性里多了个空格、class名大小写变了、属性顺序调换了,这些细微变化都会让IndexOf找不到匹配项,直接返回null。
第二个坑:截取逻辑完全错了
就算运气好parseString真的匹配到了,你把索引移到这个字符串末尾后去搜下一个</TD>,但实际上目标日期3/8/2021已经在你写的parseString的第二个<TD>里了呀!根本不需要往后找,反而应该从这段匹配的内容里提取。
给你两个解决方案
方案1:应急优化字符串匹配(不推荐长期用)
如果暂时不想引入额外库,可以调整匹配逻辑,只抓关键标识,不管那些无关的样式细节:
protected string ParseAdmissionDate(string Html) { // 先定位到AdmissionDate的那个DIV string admissionMarker = "<DIV class=\"a355\">AdmissionDate</DIV>"; int markerIndex = Html.IndexOf(admissionMarker, StringComparison.OrdinalIgnoreCase); if (markerIndex == -1) return null; // 从这个标记开始,找它后面的那个日期TD int startOfDateTd = Html.IndexOf("<TD", markerIndex); if (startOfDateTd == -1) return null; // 定位到日期DIV的起始位置 int startOfDateDiv = Html.IndexOf("<DIV class=\"a359\">", startOfDateTd); if (startOfDateDiv == -1) return null; startOfDateDiv += "<DIV class=\"a359\">".Length; // 找到日期DIV的结束标签 int endOfDateDiv = Html.IndexOf("</DIV>", startOfDateDiv); if (endOfDateDiv == -1) return null; // 提取并返回日期 return Html.Substring(startOfDateDiv, endOfDateDiv - startOfDateDiv).Trim(); }
这个版本的好处是只抓关键的class和文本,忽略那些容易变化的style、属性顺序,容错性强了不少。
方案2:用HTML解析库(强烈推荐!)
用字符串拆HTML真的是反模式,哪天页面改个小结构,你的代码就崩了。不如用专业的HTML解析库,比如HtmlAgilityPack,NuGet直接就能装:
先装包:
Install-Package HtmlAgilityPack
然后写代码:
using HtmlAgilityPack; protected string ParseAdmissionDate(string Html) { var doc = new HtmlDocument(); doc.LoadHtml(Html); // 找到写着"AdmissionDate"的DIV var admissionDiv = doc.DocumentNode.SelectSingleNode("//div[text()='AdmissionDate']"); if (admissionDiv == null) return null; // 找到这个DIV所在TD的下一个兄弟TD(注意跳过空白节点) var dateTd = admissionDiv.ParentNode.NextSibling; while (dateTd != null && dateTd.NodeType == HtmlNodeType.Text) dateTd = dateTd.NextSibling; if (dateTd == null) return null; // 提取日期DIV里的文本 var dateDiv = dateTd.SelectSingleNode(".//div[@class='a359']"); return dateDiv?.InnerText.Trim(); }
这个方案就靠谱多了,不管HTML里有多少空格、属性怎么排,都能精准定位到元素,以后页面结构有小变化,只要调整一下XPath或者节点查询逻辑就行,维护起来轻松太多。
额外小提示
要是你喜欢LINQ风格的代码,还可以这么写:
var dateDiv = doc.DocumentNode.Descendants("div") .FirstOrDefault(d => d.InnerText.Trim() == "AdmissionDate") ?.ParentNode ?.NextSibling ?.Descendants("div") .FirstOrDefault(d => d.GetAttributeValue("class", "") == "a359"); return dateDiv?.InnerText.Trim();
内容的提问来源于stack exchange,提问作者medpicz
相关产品推荐
相关产品推荐

