最近在做一个采集网页数据的功能,要获取博客园主页的二级分类,但是源代码里却没有,请问可以使用什么方式获取源代码里无法显示的内容????
可能是通过ajax异步加载的。可以把网站地址贴出来,帮你看看怎么解决。
我是用HtmlAgilityPack采集文章的,我想要获取的就是博客园主页文章里面的标签
@lchcoder:
我在网上下载了你说的那个插件来用了,没有什么问题的呀。
代码:
using HtmlAgilityPack; using System; namespace HtmlAnalyzeDemo { class Program { static void Main(string[] args) { HtmlWeb htmlWeb = new HtmlWeb(); HtmlDocument htmlDoc = htmlWeb.Load("http://www.cnblogs.com"); HtmlNodeCollection htmlNodeCollection = htmlDoc.DocumentNode.SelectNodes("//div[@class='post_item_body']"); foreach (var item in htmlNodeCollection) { Console.WriteLine("标题:"+item.ChildNodes[1].FirstChild.InnerText); Console.WriteLine("链接:" + item.ChildNodes[1].FirstChild.Attributes["href"].Value); Console.WriteLine(); } } }
运行效果
@凝冰: 这些我都能获取到,但是有些标签是隐藏的,只有鼠标移上去才会显示,比如说博客园主页的第二级的分类,在源码里面是查看不到的,所以也就获取不到第二级的分类,文章里的标签也是如此,我是想找个方法能获取到二级分类和文章标签,这些都是源码里面看不到的。
@lchcoder:这个需要分析的。
1、首先我们打开google浏览器的开发者工具。
我们在请求到的源代码中搜索ASP.NET关键字。是找不到的。我们推测是异步加载的。
2、我们在google浏览器中查看所有异步请求。
发现有一个aggsite/SubCategories(子菜单)的请求正是我们需要的。
3、查看js代码。
查看.net技术标签上有一个onmouseover方法。
4、在浏览器控制台中打印出函数
5、获取函数定义
6、根据规则编写程序。获取cateshow函数中参数,然后根据参数来获取cate_content_block_xxx。就获取到子菜单了、
@凝冰: 不好意思,我是个菜鸟,我想请问然后怎么获取到子菜单,我的那个小程序是用WPF做的,直接用HtmlAgilityPack这个插件是找不到的。
@lchcoder: 用什么做不存在,主要是思路。我们控制台程序做测试。快些。看一下是不是要获取下面的效果。
代码
using HtmlAgilityPack; using System; using System.IO; using System.Net; using System.Text; using System.Threading; namespace HtmlAnalyzeDemo { public class HttpWebRequestBeginGetRequest { private static ManualResetEvent allDone = new ManualResetEvent(false); static string postData = "{\"cateIds\":\"108698,2,108701,108703,108704,108705,108709,108712,108724,4\"}"; private static string html = ""; public static void Main(string[] args) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.cnblogs.com/aggsite/SubCategories"); request.Accept = "text/plain, */*; q=0.01"; request.Host = "www.cnblogs.com"; request.ContentType = "text/plain;charset=UTF-8"; request.ContentLength = postData.Length; request.Method = "POST"; //异步请求子菜单 request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request); allDone.WaitOne(); //将获取到的源代码转为流 byte[] array = Encoding.UTF8.GetBytes(html); MemoryStream stream = new MemoryStream(array); StreamReader reader = new StreamReader(stream); HtmlDocument htmlDocumentSub = new HtmlDocument(); //加载html成xml htmlDocumentSub.Load(reader); //获取html首页的一级菜单 HtmlDocument htmlDocument = new HtmlWeb().Load("http://www.cnblogs.com"); HtmlNodeCollection htmlNodes = htmlDocument.DocumentNode.SelectNodes("//ul[@id='cate_item']/li"); foreach (var node in htmlNodes) { string onmouseover = node.Attributes["onmouseover"].Value; string cateshowId=onmouseover.Split(new char[]{'(',')'})[1]; HtmlNodeCollection htmlCateNodes = htmlDocumentSub.DocumentNode.SelectNodes("//div[@id='cate_content_block_" + cateshowId + "']/div/ul/li"); Console.WriteLine("--" + node.InnerText); if (htmlCateNodes != null) { foreach (var cateNode in htmlCateNodes) { Console.WriteLine("----"+cateNode.InnerText); } } } //Console.WriteLine(htmlDocumentSub.DocumentNode.InnerHtml); } private static void GetRequestStreamCallback(IAsyncResult asynchronousResult) { HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; Stream postStream = request.EndGetRequestStream(asynchronousResult); byte[] byteArray = Encoding.UTF8.GetBytes(postData); postStream.Write(byteArray, 0, postData.Length); postStream.Close(); //请求完成后异步读取数据 request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request); } private static void GetResponseCallback(IAsyncResult asynchronousResult) { HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult); Stream streamResponse = response.GetResponseStream(); StreamReader streamRead = new StreamReader(streamResponse); string responseString = streamRead.ReadToEnd(); //请求完成的字符串保存到html中 html = responseString; streamResponse.Close(); streamRead.Close(); response.Close(); allDone.Set(); } } }
@凝冰: 那这部分代码的作用是什么,有点看不懂
@lchcoder: 这个是http协议里面的东西。推荐你看一下园里里面大神些的http协议详解。
http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html。
主要作用是使用http协议来模拟请求。所有的网站都是用到http协议来进行请求。返回数据的。
给你截一张http请求报文的图。
@凝冰: 非常感谢,问题已经解决,可以加你QQ吗,有什么不会的可以请教你。
@凝冰: 这是群号吗?
@lchcoder: 个人qq号546341921,打错了。
webbrowse+js可以搞定
可是我是用的WPF,那该如何获取呢??