c# http请求ajax页面
我们在用Http请求的时候,某些页面是ajax加载的,所以请求过来的页面数据不完整。也就是说ajax局部加载数据的地方,我们请求不到,这时候该怎么办呢?
WebDriver+phantomjs 这两个组合在一起使用,可以完成此任务。分别简单介绍下,WebDriver是一个前端的自动化测试框架,phantomjs是一个无界面的浏览器,基于webkit。WebDriver调用phantomjs.exe工作。下面是WebDriver提供的API,看来它能驱动各种浏览器工作。

使用前准备:
在Nuget上,下载 Selenium.WebDriver和Selenium.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页面的更多相关文章
- C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求
C# 动态创建SQL数据库(二) 使用Entity Framework 创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...
- ajax 多个setInterval进行ajax请求的页面长时间打开会出现页面卡死问题
多个setInterval进行ajax请求的页面长时间打开会出现页面卡死问题 浏览器的渲染(UI)线程和js线程是互斥的,在执行js耗时操作时,页面渲染会被阻塞掉.当我们执行异步ajax的时候没有问 ...
- Egret和Http请求 (Ajax、XMLHttpRequest、Post、Get)
一 Http请求 二 AJax和XMLHttpRequest 三 一个Ajax例子 四 Egret中的egret.HttpRequest 五 Post和Get区别 一 Http请求 Http深入 ...
- Learning Scrapy笔记(六)- Scrapy处理JSON API和AJAX页面
摘要:介绍了使用Scrapy处理JSON API和AJAX页面的方法 有时候,你会发现你要爬取的页面并不存在HTML源码,譬如,在浏览器打开http://localhost:9312/static/, ...
- 使用服务器端控制AJAX页面缓存
你知道 response.setHeader("Cache-Control","no-cache"); 这条语句是干什么的吗? 这是用来防止浏览器缓存动态内容生 ...
- JavaScrpit中异步请求Ajax实现
在前端页面开发的过程中,经常使用到Ajax请求,异步提交表单数据,或者异步刷新页面. 一般来说,使用Jquery中的$.ajax,$.post,$.getJSON,非常方便,但是有的时候,我们只因为需 ...
- 异步请求Ajax(取得json数据)
异步请求Ajax 没有学习Ajax之前请求数据的时候都是整个页面全部刷新了一次,也就是每次请求都会重新请求所有的资源.但是在很多时候不需要页面全部刷新,仅仅是需要页面的局部数据刷新即可,此时需要发送异 ...
- ajax 页面无刷新
<!-- 使用原生Ajax 和 $.ajax 实现局部刷新的过程 --><!-- 封装通用XMLHttpRequest对象 --><!DOCTYPE html>&l ...
- HTTP 错误 404.3 – Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。
今天,在vs2013中新建了一个placard.json文件,当我用jq读取它的时候,去提示404,直接在浏览器访问这个文件,提示: HTTP 错误 404.3 – Not Found 由于扩展配置问 ...
随机推荐
- 嵌入式LINUX环境下视频采集知识
V4L2是Linux环境下开发视频采集设备驱动程序的一套规范(API),它为驱动程序的编写提供统一的接口,并将所有的视频采集设备的驱动程序都纳入其的管理之中.V4L2不仅给驱动程序编写者带来极大的方便 ...
- 【Android应用开发】 Android 崩溃日志 本地存储 与 远程保存
示例代码下载 : http://download.csdn.net/detail/han1202012/8638801; 一. 崩溃日志本地存储 1. 保存原理解析 崩溃信息本地保存步骤 : -- 1 ...
- python跨行 print:多用(),换行符\要小心,少用+或者不用(其它程序代码跨行用\就行,不能用括号)
这两种是错的 # print '11' # 'tset3'#error # print '12' # +'tset4'#error python跨行用()和\都能实现.+只是连 ...
- oracle ebs应用产品安全性-定义访问权限集
定义 定义访问权限集是一项分配至责任层的可选的安全功能,是对Oracle 11i应用产品弹性域安全性定义的功能扩展,对总帐管理模块的一些内容进行安全性定义和权限分配的集合,以控制不同的责任对一些内容的 ...
- OJ题:字符串分隔
题目描述 •连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组:•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理. 输入描述: 连续输入字符串(输入2次,每个字符串长度小于10 ...
- 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 ...
- 将Ext JS 5应用程序导入Web项目以及实现本地化
在Ext JS 5,使用了新的脚本和样式加载方式,这对于将应用程序导入到Web项目中产生了点小麻烦.而对于本地化文件的导入,也采用了新的方式,本文将一一解答这些问题. 将Ext JS 5应用程序导入W ...
- python检测变量是否有定义(即使用前检查是否定义好)
http://www.cnblogs.com/starspace/archive/2008/12/03/1347007.html 第一种方法: 'var' in locals().keys() 第二种 ...
- (二十六)静态单元格(Cell)
制作类似iOS系统设置的页面,如果使用代码来实现,将会比较麻烦,可以通过静态单元格技术方便的实现. 注意:静态单元格只支持TableViewController. 可以通过storyboard直接操作 ...
- Notepad++ 使用探索
一.更换主题,视觉享受 1,http://wiki.macromates.com/Themes/UserSubmittedThemes,从网站上下载自己喜欢的主题,解压 2,复制Black Pearl ...