/// <summary> /// 分析表达式 /// </summary> void Analyse() { //得到当前页面的HTML内容 string htmlContent = ""; //原素标签 var elementTags = new string[] { "p", "span", "strong", "font", "h1", "o:p", "dd" }; //用于HTML处理 HtmlDocument htmlDom = new HtmlDocument(); //基url Uri baseUri = new Uri(IndexPageUrl); #region #endregion try { //得到当前页面的HTML内容 //并将HTML转换成为xml content = htmlContent = IndexPageUrl.GetWeb(); //格式化为html htmlDom.LoadHtml(htmlContent); //格式化为html htmlContent = Tong.HtmlToXML.HTMLConvert(htmlDom.DocumentNode.OuterHtml); //重新加载HTML字符串 对一些标签进行闭合 htmlDom.LoadHtml(htmlContent.FiltrateHTML(elementTags)); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(DateTime.Now + ex.Message + "|||||" + ex.StackTrace); return; } #region 分析数据内容 #region 处理所有原素数据 生成所有带a 的原素 //可能的原素 List <PossiblyResultElement> possiblyResultElements = new List <PossiblyResultElement>(); //开始循环子原素 SingleListPageAnalyse.AnalyseMaxATagNearest(htmlDom.DocumentNode, possiblyResultElements, 0, new PossiblyResultElement() { ParentPossiblyResult = null, CurrnetHtmlElement = htmlDom.DocumentNode, LayerIndex = -1, ContainTagNum = 0 }); #region 尝试分析原始,找到包括 a href 最多的原素 目前 还不能完成 ////得到最合适的原素 //var els = from p in possiblyResultElements // where p.ContainTagNum > 0 // orderby p.LayerIndex ascending // orderby p.ContainTagNum , p.ContainTagNum descending // select p; ////得到结果 //var relsutels = els.ToList().Take(3); #endregion #endregion #region 测试代码可以删除 //计算当前所有HTML原素中的A原素 var PageAElements = from a in possiblyResultElements where a.CurrnetHtmlElement.Name == "a" && a.CurrnetHtmlElement.Attributes["href"] != null select a; //计算每个级别A原素的数量 var aElGroups = from a in PageAElements.GroupBy(p => p.LayerIndex) select new { LayerIndex = a.Key, Count = a.Count(), AEls = a.ToList() }; //对A原素的级别的数量进行排序。 最多的 a原素的级别将排在最前 var aElGroupsOrder = aElGroups.OrderByDescending(p => p.Count); //最后一层的所有 A 原素分组 if (aElGroupsOrder.Count() > 0) { //计算每个A原素的 XPath 表达式的路径对像集合 var AElXPaths = from a in aElGroupsOrder.ElementAt(0).AEls select new { XPath = a.CurrnetHtmlElement.XPath, el = a, xpathPathArr = a.CurrnetHtmlElement.XPath.Split('/') }; //得到a 原素的表达式字符串集合 string xpaths = string.Join("\r\n", (from a in AElXPaths select a.XPath).ToArray()); //得到表达式长度分集合 var XpathLengthGroups = AElXPaths.GroupBy(p => p.xpathPathArr.Length); //相同的最短路径 List <string> MinPath = new List <string>(); //开始循环分组 foreach (var groux in XpathLengthGroups) { //对每个级别的表达式字符串进行排序 for (int k = 0; k < groux.Key; k++) { //得到当前级别的表达式字符串保存在数组中 var xpa = from p in groux select p.xpathPathArr[k]; //对当前表达式进行分组拿出最大的一组 var xpaGroups = xpa.GroupBy(p => p).OrderByDescending(p => p.Count()); //添加到表达式集合 if (xpaGroups.Count() > 0) { //如果这是一个有效的结果 if (xpaGroups.ElementAt(0).Count() > AElXPaths.Count() - 10) { MinPath.Add(xpaGroups.ElementAt(0).Key); } else { //后面不再有相同的联接出现了 //直接跳出 break; } } } } //得到结果表达式 string PathStr = string.Join("/", MinPath.ToArray()); //得到包括这个表达式结果的所有A原素 PageAElements = PageAElements.Where(p => p.CurrnetHtmlElement.XPath.Contains(PathStr)); MinPath.Clear(); } #endregion //得到所页面中所有的A标题原素 //并将标题转换成为简体中文 var allAElements = from a in PageAElements where a.CurrnetHtmlElement.Name == "a" && a.CurrnetHtmlElement.Attributes["href"] != null && ( a.CurrnetHtmlElement.Attributes["href"].Value.EndsWith(".html", StringComparison.CurrentCultureIgnoreCase) || a.CurrnetHtmlElement.Attributes["href"].Value.EndsWith(".aspx", StringComparison.CurrentCultureIgnoreCase) || a.CurrnetHtmlElement.Attributes["href"].Value.EndsWith(".asp", StringComparison.CurrentCultureIgnoreCase) || a.CurrnetHtmlElement.Attributes["href"].Value.EndsWith(".htm", StringComparison.CurrentCultureIgnoreCase) || a.CurrnetHtmlElement.Attributes["href"].Value.EndsWith(".php", StringComparison.CurrentCultureIgnoreCase) || a.CurrnetHtmlElement.Attributes["href"].Value.EndsWith(".shtml", StringComparison.CurrentCultureIgnoreCase) ) select new ListPageContentUrl() { Url = new Uri(baseUri, a.CurrnetHtmlElement.Attributes["href"].Value), Title = a.CurrnetHtmlElement.InnerText.WordTraditionalToSimple(), index = System.Text.RegularExpressions.Regex.Match(a.CurrnetHtmlElement.InnerText.WordTraditionalToSimple(), @"第[壹一两贰二叁三肆四伍五陆六柒七捌八玖九拾十佰百仟千萬万零|(0-9)]{1,}章").Value.Replace("第", "").Replace("章", "").ConverToDigit(), Indexs = GetTitleIndexs(System.Text.RegularExpressions.Regex.Match(a.CurrnetHtmlElement.InnerText.WordTraditionalToSimple(), @"第[壹一两贰二叁三肆四伍五陆六柒七捌八玖九拾十佰百仟千萬万零|(0-9)]{1,}章").Value.Replace("第", "").Replace("章", "").ConverToDigit()) }; ; ListPageContentUrls = allAElements.ToList(); #region 各种排序方法 这个方法不完善无法实现得到正确的文章顺序 ////如果可以作文章的ID来排序则用ID来排序 //var noIdsurl = ListPageContentUrls.Where(p => p.index == 0); //int pagesCount = noIdsurl.Count(); //if (pagesCount <= 1) //{ // #region 章节编号排序,一般不会出现问题只有当为0的index 大于2以上才进行以下排序 // ListPageContentUrls = ListPageContentUrls.OrderBy(p => p.index).ToList(); // #endregion //} //else //{ // #region 如果索引为0的数据过大则 开始查找最第一章 和最后一章节 既索引最大的那个章节 中间差的用数字填起来 // //初始化一个类集合 // var results = (from p in noIdsurl select new { page = p, index = 0, IsIndex = false }).ToList(); // //选进行排序 // var descReoceds = ListPageContentUrls.OrderByDescending(p => p.index); // //得到最大章节与最小章节 // int min = ListPageContentUrls.Min(p => p.index); // //取值 // ListPageContentUrl maxItem = descReoceds.ElementAt(0); // //清空变量用于下面的添加匿名类型 // results.Clear(); // //同一个索引可能出现多个 // System.Collections.Generic.Dictionary<int, List<ListPageContentUrl>> dic = new Dictionary<int, List<ListPageContentUrl>>(); // //得到索引产生的字典 // ListPageContentUrls.Where(p => p.index != 0).ToList().ForEach( // (x) => // { // //如果不包含就直接添加 // if (!dic.ContainsKey(x.index)) // { // dic.Add(x.index, new List<ListPageContentUrl>() { x }); // } // else // { // //添加到集合中 // dic[x.index].Add(x); // } // } // ); // //对章节进行对号入坐 // for (int i = min; i <= maxItem.index; i++) // { // if (dic.ContainsKey(i)) // { // results.Add(new { page = dic[i][0], index = i, IsIndex = true }); // } // else // { // results.Add(new { page = new ListPageContentUrl(), index = i, IsIndex = false }); // } // } // #endregion // #region 章节与目录列的项对号入坐后对所有索引0的项进行处理 // #endregion // #region 页面ID排序 有可能会出现问题 // Func<ListPageContentUrl, bool> func = p => // { // string last = p.Url.Segments.Last(); // decimal o; // if (last.IndexOf(".") != -1) // { // last = last.Substring(0, last.Length - last.IndexOf(".")); // return decimal.TryParse(last, out o); // } // return true; // }; // Func<ListPageContentUrl, double> funx = p => // { // string last = p.Url.Segments.Last(); // double o; // if (last.IndexOf(".") != -1) // { // last = last.Substring(0, last.Length - last.IndexOf(".")); // double.TryParse(last, out o); // return o; // } // return -1; // }; // #endregion // //如果可以作文章的ID来排序则用ID来排序 // pagesCount = ListPageContentUrls.Where(func).Count(); // //如果可以用ID排序 // if (pagesCount <= ListPageContentUrls.Count - 1) // { // ListPageContentUrls = ListPageContentUrls.OrderBy(p => funx(p)).ToList(); // } // //默认排序 //} #endregion #endregion //清空变量可以释放内存 possiblyResultElements.Clear(); }
/// <summary> /// 分析表达式 /// </summary> void Analyse() { //得到当前页面的HTML内容 string htmlContent = ""; //原素标签 var elementTags = new string[] { "p", "span", "strong", "font", "h1", "tbody", "o:p", "dd", "tr", "table" }; //用于HTML处理 HtmlDocument htmlDom = new HtmlDocument(); //基url Uri baseUri = new Uri(IndexPageUrl); #region #endregion try { //得到当前页面的HTML内容 //并将HTML转换成为xml content = htmlContent = IndexPageUrl.GetWeb(); //格式化为html htmlDom.LoadHtml(htmlContent); //格式化为html htmlContent = Tong.HtmlToXML.HTMLConvert(htmlDom.DocumentNode.OuterHtml); //重新加载HTML字符串 对一些标签进行闭合 htmlDom.LoadHtml(htmlContent.FiltrateHTML(elementTags)); } catch { return; } #region 分析数据内容 #region 处理所有原素数据 生成所有带a 的原素 //可能的原素 List <PossiblyResultElement> possiblyResultElements = new List <PossiblyResultElement>(); //开始循环子原素 SingleListPageAnalyse.AnalyseMaxATagNearest(htmlDom.DocumentNode, possiblyResultElements, 0, new PossiblyResultElement() { ParentPossiblyResult = null, CurrnetHtmlElement = htmlDom.DocumentNode, LayerIndex = -1, ContainTagNum = 0 }); #region 尝试分析原始,找到包括 a href 最多的原素 目前 还不能完成 ////得到最合适的原素 //var els = from p in possiblyResultElements // where p.ContainTagNum > 0 // orderby p.LayerIndex ascending // orderby p.ContainTagNum , p.ContainTagNum descending // select p; ////得到结果 //var relsutels = els.ToList().Take(3); #endregion #endregion //得到所页面中所有的A标题原素 //并将标题转换成为简体中文 var allAElements = from a in possiblyResultElements where a.CurrnetHtmlElement.Name == "a" && a.CurrnetHtmlElement.Attributes["href"] != null select new ListPageContentUrl() { Url = new Uri(baseUri, a.CurrnetHtmlElement.Attributes["href"].Value), Title = a.CurrnetHtmlElement.InnerText.WordTraditionalToSimple(), index = System.Text.RegularExpressions.Regex.Match(a.CurrnetHtmlElement.InnerText.WordTraditionalToSimple(), @"第[壹一两贰二叁三肆四伍五陆六柒七捌八玖九拾十佰百仟千萬万零|(0-9)]{1,}章").Value.Replace("第", "").Replace("章", "").ConverToDigit(), Indexs = GetTitleIndexs(System.Text.RegularExpressions.Regex.Match(a.CurrnetHtmlElement.InnerText.WordTraditionalToSimple(), @"第[壹一两贰二叁三肆四伍五陆六柒七捌八玖九拾十佰百仟千萬万零|(0-9)]{1,}章").Value.Replace("第", "").Replace("章", "").ConverToDigit()) }; //对联接的路径深度进行排序 allAElements = allAElements.OrderBy(p => p.Url.Segments.Length); var groupAElements = (from p in allAElements group p by new { 路径深度 = p.Url.Segments.Length, 基本路径字符串 = string.Join("", new Func <string[]>(() => { var templist = p.Url.Segments.ToList(); templist.RemoveAt(templist.Count - 1); return(templist.ToArray()); }).Invoke()), }).OrderByDescending(p => p.Count()) ; //当前分组对像的复制版本 var tempElements = groupAElements.ToList(); //清空对像 tempElements.Clear(); ///如果有数据出现 if (groupAElements.Count() > 2) { //如果第一重类型的数据是第二重类型数据的数倍之多则取第一种类型的数据 if (groupAElements.ElementAt(0).Count() / groupAElements.ElementAt(1).Count() >= 3) { //只取第一次的数据 tempElements.Add((groupAElements.ElementAt(0))); } else { for (int n = 1; n < groupAElements.Count(); n++) { //这里可能传奇引发n+1超出范围的索引异常 if (groupAElements.Count() > n + 1) { //如果第一重类型的数据是第二重类型数据的数倍之多则取第一种类型的数据 if (groupAElements.ElementAt(n).Count() / groupAElements.ElementAt(n + 1).Count() >= 3) { //取得数据后直接返回 tempElements.Add((groupAElements.ElementAt(n))); break; } } } } } //如果找到了a href 分类列表集合 if (tempElements.Count > 0) { //给内容页面集合传值 var tempListPageContentUrls = tempElements.ElementAt(0).ToList(); #region 过滤无用的数据只留下列表 int kcount = tempListPageContentUrls.Count; //去掉列面前面的一些不用的数据 for (int k = 0; k < kcount; k++) { //第一章以前的联接全部删除 if (tempListPageContentUrls[0].Title.Trim().Contains("第一章") || tempListPageContentUrls[0].Title.Trim().Contains("第1章")) { k = 9999999; break; } else { tempListPageContentUrls.RemoveAt(0); } } // for (int k = 0; k < kcount; k++) { //第一章以前的联接全部删除 if (tempListPageContentUrls.Last().index > 0) { k = 9999999; break; } else { //删除最后的数据 tempListPageContentUrls.Remove(tempListPageContentUrls.Last()); } } #endregion ListPageContentUrls = tempListPageContentUrls; #region 各种排序方法 这个方法不完善无法实现得到正确的文章顺序 ////如果可以作文章的ID来排序则用ID来排序 //var noIdsurl = ListPageContentUrls.Where(p => p.index == 0); //int pagesCount = noIdsurl.Count(); //if (pagesCount <= 1) //{ // #region 章节编号排序,一般不会出现问题只有当为0的index 大于2以上才进行以下排序 // ListPageContentUrls = ListPageContentUrls.OrderBy(p => p.index).ToList(); // #endregion //} //else //{ // #region 如果索引为0的数据过大则 开始查找最第一章 和最后一章节 既索引最大的那个章节 中间差的用数字填起来 // //初始化一个类集合 // var results = (from p in noIdsurl select new { page = p, index = 0, IsIndex = false }).ToList(); // //选进行排序 // var descReoceds = ListPageContentUrls.OrderByDescending(p => p.index); // //得到最大章节与最小章节 // int min = ListPageContentUrls.Min(p => p.index); // //取值 // ListPageContentUrl maxItem = descReoceds.ElementAt(0); // //清空变量用于下面的添加匿名类型 // results.Clear(); // //同一个索引可能出现多个 // System.Collections.Generic.Dictionary<int, List<ListPageContentUrl>> dic = new Dictionary<int, List<ListPageContentUrl>>(); // //得到索引产生的字典 // ListPageContentUrls.Where(p => p.index != 0).ToList().ForEach( // (x) => // { // //如果不包含就直接添加 // if (!dic.ContainsKey(x.index)) // { // dic.Add(x.index, new List<ListPageContentUrl>() { x }); // } // else // { // //添加到集合中 // dic[x.index].Add(x); // } // } // ); // //对章节进行对号入坐 // for (int i = min; i <= maxItem.index; i++) // { // if (dic.ContainsKey(i)) // { // results.Add(new { page = dic[i][0], index = i, IsIndex = true }); // } // else // { // results.Add(new { page = new ListPageContentUrl(), index = i, IsIndex = false }); // } // } // #endregion // #region 章节与目录列的项对号入坐后对所有索引0的项进行处理 // #endregion // #region 页面ID排序 有可能会出现问题 // Func<ListPageContentUrl, bool> func = p => // { // string last = p.Url.Segments.Last(); // decimal o; // if (last.IndexOf(".") != -1) // { // last = last.Substring(0, last.Length - last.IndexOf(".")); // return decimal.TryParse(last, out o); // } // return true; // }; // Func<ListPageContentUrl, double> funx = p => // { // string last = p.Url.Segments.Last(); // double o; // if (last.IndexOf(".") != -1) // { // last = last.Substring(0, last.Length - last.IndexOf(".")); // double.TryParse(last, out o); // return o; // } // return -1; // }; // #endregion // //如果可以作文章的ID来排序则用ID来排序 // pagesCount = ListPageContentUrls.Where(func).Count(); // //如果可以用ID排序 // if (pagesCount <= ListPageContentUrls.Count - 1) // { // ListPageContentUrls = ListPageContentUrls.OrderBy(p => funx(p)).ToList(); // } // //默认排序 //} #endregion } #endregion }