我们在用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. 嵌入式LINUX环境下视频采集知识

    V4L2是Linux环境下开发视频采集设备驱动程序的一套规范(API),它为驱动程序的编写提供统一的接口,并将所有的视频采集设备的驱动程序都纳入其的管理之中.V4L2不仅给驱动程序编写者带来极大的方便 ...

  2. 【Android应用开发】 Android 崩溃日志 本地存储 与 远程保存

    示例代码下载 : http://download.csdn.net/detail/han1202012/8638801; 一. 崩溃日志本地存储 1. 保存原理解析 崩溃信息本地保存步骤 : -- 1 ...

  3. python跨行 print:多用(),换行符\要小心,少用+或者不用(其它程序代码跨行用\就行,不能用括号)

    这两种是错的 # print '11' #       'tset3'#error # print '12' #       +'tset4'#error python跨行用()和\都能实现.+只是连 ...

  4. oracle ebs应用产品安全性-定义访问权限集

    定义 定义访问权限集是一项分配至责任层的可选的安全功能,是对Oracle 11i应用产品弹性域安全性定义的功能扩展,对总帐管理模块的一些内容进行安全性定义和权限分配的集合,以控制不同的责任对一些内容的 ...

  5. OJ题:字符串分隔

    题目描述 •连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组:•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理. 输入描述: 连续输入字符串(输入2次,每个字符串长度小于10 ...

  6. Python基础 语法特别注意笔记(和Java相比)

    Python变量和数据类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ...

  7. 将Ext JS 5应用程序导入Web项目以及实现本地化

    在Ext JS 5,使用了新的脚本和样式加载方式,这对于将应用程序导入到Web项目中产生了点小麻烦.而对于本地化文件的导入,也采用了新的方式,本文将一一解答这些问题. 将Ext JS 5应用程序导入W ...

  8. python检测变量是否有定义(即使用前检查是否定义好)

    http://www.cnblogs.com/starspace/archive/2008/12/03/1347007.html 第一种方法: 'var' in locals().keys() 第二种 ...

  9. (二十六)静态单元格(Cell)

    制作类似iOS系统设置的页面,如果使用代码来实现,将会比较麻烦,可以通过静态单元格技术方便的实现. 注意:静态单元格只支持TableViewController. 可以通过storyboard直接操作 ...

  10. Notepad++ 使用探索

    一.更换主题,视觉享受 1,http://wiki.macromates.com/Themes/UserSubmittedThemes,从网站上下载自己喜欢的主题,解压 2,复制Black Pearl ...