我们在用Http请求的时候,某些页面是ajax加载的,所以请求过来的页面数据不完整。也就是说ajax局部加载数据的地方,我们请求不到,这时候该怎么办呢?

  WebDriver+phantomjs 这两个组合在一起使用,可以完成此任务。分别简单介绍下,WebDriver是一个前端的自动化测试框架,phantomjs是一个无界面的浏览器,基于webkit。WebDriver调用phantomjs.exe工作。下面是WebDriver提供的API,看来它能驱动各种浏览器工作。

  

  使用前准备:

在Nuget上,下载 Selenium.WebDriverSelenium.PhantomJS.WebDriver两个包,在项目中引用 WebDriver.dll,在输出目录下要有phantomjs.exe。

  我们看一个完整的例子:

  

using OpenQA.Selenium;
using OpenQA.Selenium.PhantomJS;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApplication1
{
public interface ICrawler
{
event EventHandler<OnStartEventArgs> OnStart;
event EventHandler<OnCompletedEvent> OnCompleted;
event EventHandler<OnErrorEventArgs> OnError; Task Start(Uri uri, Script script, Operation opreation);
} public class Operation
{ public Action<PhantomJSDriver> Action; public Func<IWebDriver, bool> Condition; public int timeout { get; set; }
} public class Script
{
public string Code { set; get; } public object[] Args { set; get; } } public class OnStartEventArgs
{
public Uri Uri { set; get; } public OnStartEventArgs(Uri uri)
{
this.Uri = uri;
}
} public class OnErrorEventArgs
{
public Uri Uri { set; get; } public Exception Exception { set; get; } public OnErrorEventArgs(Uri uri, Exception ex)
{
this.Uri = uri; this.Exception = ex;
}
} public class OnCompletedEvent
{
public Uri Uri { set; get; } public int ThreadId { set; get; } public string PageSource { get; private set; } public long Milliseconds { get; private set; } public PhantomJSDriver Driver { get; private set; } public OnCompletedEvent(Uri uri, int threadId, string pageSource, long milliseconds, PhantomJSDriver driver)
{
this.Uri = uri;
this.ThreadId = threadId;
this.PageSource = pageSource;
this.Milliseconds = milliseconds;
this.Driver = driver;
}
} public class HighCrawler : ICrawler
{ public event EventHandler<OnStartEventArgs> OnStart; public event EventHandler<OnCompletedEvent> OnCompleted; public event EventHandler<OnErrorEventArgs> OnError; private static PhantomJSOptions _options;
private static PhantomJSDriverService _service; static HighCrawler()
{
var service = PhantomJSDriverService.CreateDefaultService();
service.DiskCache = true;
service.IgnoreSslErrors = true;
service.HideCommandPromptWindow = true;
service.LoadImages = false;
service.LocalToRemoteUrlAccess = true; _service = service; _options = new PhantomJSOptions();
} public Task Start(Uri uri, Script script, Operation operation)
{
return Task.Factory.StartNew(() =>
{
if (OnStart != null)
{
this.OnStart(this, new OnStartEventArgs(uri));
} var driver = new PhantomJSDriver(_service, _options);
try
{
var watch = DateTime.Now;
driver.Navigate().GoToUrl(uri.ToString()); if (script != null) driver.ExecuteScript(script.Code, script.Args); if (operation.Action != null) operation.Action.Invoke(driver); var driverWait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(operation.timeout)); //设置超时时间 if (operation.Condition != null) driverWait.Until(operation.Condition); var threadId = Thread.CurrentThread.ManagedThreadId; var milliseconds = DateTime.Now.Subtract(watch).Milliseconds; var pageSource = driver.PageSource; if (this.OnCompleted != null)
this.OnCompleted(this, new OnCompletedEvent(uri, threadId, pageSource, milliseconds, driver)); }
catch (Exception ex)
{
if (OnError != null)
this.OnError(this, new OnErrorEventArgs(uri, ex));
}
finally
{
driver.Close();
driver.Quit();
}
});
}
}
}

  这是封装了一个类,方便使用,我们看如何使用:

        /// <summary>
/// 解析网站
/// </summary>
/// <param name="url">待解析的网站</param>
/// <param name="waitId">等待加载的元素Id:"search-main"</param>
/// <param name="xpath">解析路径:"//div[@class=\"article panel article-result\"]//h5[@class=\"title\"]//a"</param>
private static void TestWaitForReady(string url, string waitId, string xpath, int timeout = )
{ var crawler = new HighCrawler(); crawler.OnStart += (s, e) =>
{ Console.WriteLine("爬虫开始抓取地址:" + e.Uri.ToString());
}; crawler.OnError += (s, e) =>
{
Console.WriteLine("爬虫出现错误:" + e.Uri.ToString() + ",异常信息" + e.Exception.ToString());
}; crawler.OnCompleted += (s, e) =>
{
Console.WriteLine("接收到的源码长度:" + e.PageSource.Length); Thread.Sleep();
Console.WriteLine("爬虫结束,花费时间:" + e.Milliseconds);
var items = e.Driver.FindElements(By.XPath(xpath)); foreach (var item in items)
{
Console.WriteLine(item.Text);
}
}; var operition = new Operation
{
Action = (x) =>
{ },
Condition = (x) =>
{
return x.FindElement(By.Id(waitId)).Displayed;
},
timeout = timeout
}; crawler.Start(new Uri(url), null, operition); }

  取ajax异步结果的核心原理:WebDriver把页面上的某个元素,作为标识,一旦出现此元素,表明ajax结束,这时候再返回结果,中间有个等待的过程。

  

c# http请求ajax页面的更多相关文章

  1. C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求

    C# 动态创建SQL数据库(二) 使用Entity Framework  创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...

  2. ajax 多个setInterval进行ajax请求的页面长时间打开会出现页面卡死问题

     多个setInterval进行ajax请求的页面长时间打开会出现页面卡死问题 浏览器的渲染(UI)线程和js线程是互斥的,在执行js耗时操作时,页面渲染会被阻塞掉.当我们执行异步ajax的时候没有问 ...

  3. Egret和Http请求 (Ajax、XMLHttpRequest、Post、Get)

    一  Http请求 二  AJax和XMLHttpRequest 三  一个Ajax例子 四 Egret中的egret.HttpRequest 五 Post和Get区别 一 Http请求 Http深入 ...

  4. Learning Scrapy笔记(六)- Scrapy处理JSON API和AJAX页面

    摘要:介绍了使用Scrapy处理JSON API和AJAX页面的方法 有时候,你会发现你要爬取的页面并不存在HTML源码,譬如,在浏览器打开http://localhost:9312/static/, ...

  5. 使用服务器端控制AJAX页面缓存

    你知道 response.setHeader("Cache-Control","no-cache"); 这条语句是干什么的吗? 这是用来防止浏览器缓存动态内容生 ...

  6. JavaScrpit中异步请求Ajax实现

    在前端页面开发的过程中,经常使用到Ajax请求,异步提交表单数据,或者异步刷新页面. 一般来说,使用Jquery中的$.ajax,$.post,$.getJSON,非常方便,但是有的时候,我们只因为需 ...

  7. 异步请求Ajax(取得json数据)

    异步请求Ajax 没有学习Ajax之前请求数据的时候都是整个页面全部刷新了一次,也就是每次请求都会重新请求所有的资源.但是在很多时候不需要页面全部刷新,仅仅是需要页面的局部数据刷新即可,此时需要发送异 ...

  8. ajax 页面无刷新

    <!-- 使用原生Ajax 和 $.ajax 实现局部刷新的过程 --><!-- 封装通用XMLHttpRequest对象 --><!DOCTYPE html>&l ...

  9. HTTP 错误 404.3 – Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。

    今天,在vs2013中新建了一个placard.json文件,当我用jq读取它的时候,去提示404,直接在浏览器访问这个文件,提示: HTTP 错误 404.3 – Not Found 由于扩展配置问 ...

随机推荐

  1. OpenCV实时美颜摄像并生成H264视频流

    为什么美颜摄像这么简单的功能,OpenCV这个开源项目网上很少有代码呢?对于在windows平台下,生成h264视频流也比价麻烦,没有现成的api可以使用,需要借助MinGw编译libx264,或者f ...

  2. 如何禁止App在后台运行以及如何保存和恢复App的状态

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 如果禁止App在后台运行 iOS上的App类似于Windows ...

  3. 04springMVC结构,mvc模式,spring-mvc流程,spring-mvc的第一个例子,三种handlerMapping,几种控制器,springmvc基于注解的开发,文件上传,拦截器,s

     1. Spring-mvc介绍 1.1市面上流行的框架 Struts2(比较多) Springmvc(比较多而且属于上升的趋势) Struts1(即将被淘汰) 其他 1.2  spring-mv ...

  4. Android的ImageSwitcher和TextSw-android学习之旅(三十四)

    ImageSwitcher简介 ImageSwitcher继承了ViewSwitcher,所以在切换时候会有动画,可以把它理解成一个动画版本的ImageView. 他的showNext(),和show ...

  5. 解决android 大图OOM的两种方法

    最近做程序中,需要用到一张大图.这张图片是2880*2180大小的,在我开发所用的华为3C手机上显示没有问题,但是给米3装的时候,一打开马上报OOM错误.给nexus5装,则是图片无法出来,DDMS中 ...

  6. Mat, IplImage, CvMat, Cvarr关系及元素获取

    自己目前正打算整理opencv数据结构之间关系,寻寻觅觅之间,发现这篇博文很全面,总结得很好,故转之.红色部分不对,自己已修改! 原文地址:http://blog.csdn.net/abcjennif ...

  7. Web Service进阶(二)如何用Apache TCPMon来截获SOAP消息

    注:以下是关于TCPMon的一些使用常识,如果不需要或是已经熟悉就不用往下看了. 在WebService服务器和客户机之间会传递SOAP消息,有时我们需要得到这些消息以便调试,而Apache的TCPM ...

  8. 解决 RtlCreateActivationContext() failed 0xc000000d

    gtest 示例的Debug版启动报错: Debug输出如下: 'sample1_unittest.exe': Loaded 'D:\LibSrc\gtest_1.7.0_build\Debug\sa ...

  9. FilterDispatcher is depredated!plesae use the new filters

    一些struts2的教程都是比较早的,当我们基于较新版本的struts2来实现代码的时候,往往会出现一些问题.比如这个警告:FilterDispatcher isdeprecated! 在web.xm ...

  10. Uva - 177 - Paper Folding

    If a large sheet of paper is folded in half, then in half again, etc, with all the folds parallel, t ...