C#使用phantomjs,爬取AJAX加载完成之后的页面
1、开发思路:入参根据apiSetting配置文件,分配静态文件存储地址,可实现不同站点的静态页生成功能。静态页生成功能使用无头浏览器生成,生成之后的字符串进行正则替换为固定地址,实现本地正常访问。
2、已发现问题:如果js在载入页面时进行某些重写dom操作,已用正则替换掉的动态路径代码,会被覆盖,导致本地访问无效。 这一点只能是站点开发那边重新对页面进行优化,从而避免这种情况。 但是这仅影响本地情况,如果静态页面部署到服务器,使用相对路径其实也不会影响。
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc; namespace QuartZNetService.Controllers
{
public class BuildStaticController : Controller
{
/// <summary>
/// 配置地址
/// </summary>
public static string jsonUrl = AppDomain.CurrentDomain.BaseDirectory + "apiSetting.json"; /// <summary>
/// 网站配置类
/// </summary>
public class HttpConfig
{
/// <summary>
/// 网站cookie信息
/// </summary>
public string Cookie { get; set; } /// <summary>
/// 页面Referer信息
/// </summary>
public string Referer { get; set; } /// <summary>
/// 默认(text/html)
/// </summary>
public string ContentType { get; set; } public string Accept { get; set; } public string AcceptEncoding { get; set; } /// <summary>
/// 超时时间(毫秒)默认100000
/// </summary>
public int Timeout { get; set; } public string UserAgent { get; set; } /// <summary>
/// POST请求时,数据是否进行gzip压缩
/// </summary>
public bool GZipCompress { get; set; } public bool KeepAlive { get; set; } public string CharacterSet { get; set; } public HttpConfig()
{
this.Timeout = ;
this.ContentType = "text/html; charset=" + Encoding.UTF8.WebName; this.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";
this.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
this.AcceptEncoding = "gzip,deflate";
this.GZipCompress = false;
this.KeepAlive = true;
this.CharacterSet = "UTF-8";
}
} /// <summary>
/// 利用phantomjs 爬取AJAX加载完成之后的页面
/// JS脚本刷新时间间隔为3秒,防止页面AJAX请求时间过长导致数据无法获取
/// </summary>
/// <param name="url"></param>
/// <param name="sitId">站点ID 用于配置站点盘符位置</param>
/// <param name="type">存储文件夹 可为空</param>
/// <param name="config"></param>
/// <param name="interval"></param>
/// <returns></returns>
public JsonResult Do(string url, string sitId, string typeId, string fileName, HttpConfig config, int interval = )
{
try
{
var readjson = Readjson(sitId, typeId);
JObject jo = (JObject)JsonConvert.DeserializeObject(readjson.ToString());
var sitUrl = jo["url"].ToString();
var folder = jo["folder"].ToString(); string path = System.AppDomain.CurrentDomain.BaseDirectory.ToString();
ProcessStartInfo start = new ProcessStartInfo(path + @"webTools\phantomjs.exe");//设置运行的命令行文件问ping.exe文件,这个文件系统会自己找到
start.WorkingDirectory = path + @"webTools\"; //设置命令参数
string commond = string.Format("{0} {1} {2} {3} {4} {5}", path + @"webTools\codes.js", url, interval, config.UserAgent, config.Accept, config.Referer);
start.Arguments = commond;
StringBuilder sb = new StringBuilder();
start.CreateNoWindow = true;//不显示dos命令行窗口
start.RedirectStandardOutput = true;//
start.RedirectStandardInput = true;//
start.UseShellExecute = false;//是否指定操作系统外壳进程启动程序
Process p = Process.Start(start);
StreamReader reader = new StreamReader(p.StandardOutput.BaseStream,Encoding.UTF8);//截取输出流 //正则匹配完整外链js
Regex myreg = new Regex("(http|https)://(?<domain>[^(:|/]*)");
Match myMatch = myreg.Match(url);
var reader_txt = reader.ReadToEnd();
StringBuilder reader_write = new StringBuilder(reader_txt);
Regex regex = new Regex("<script[^>]*?src=\"([^>]*?)\"[^>]*?>", RegexOptions.IgnoreCase);//正则匹配外链html代码
MatchCollection userMatchColl = regex.Matches(reader_txt); //自定义替换区域 bg
if (userMatchColl.Count > )
{
foreach (Match matchItem in userMatchColl)
{
if (reader_write.ToString().IndexOf(matchItem.Value) > && matchItem.Value.IndexOf("xxx.cn") == -)
{
reader_write.Insert(
(reader_write.ToString().IndexOf(matchItem.Value) + matchItem.Value.IndexOf("src=\"") + ("src=\"").Length),
"https://www.xxx.cn"
);
}
}
}
reader_write.Replace("src=\"//", "src=\"https://");//增加https
reader_write.Replace("href=\"//", "href=\"https://");//增加https
reader_write.Replace("\"//images", "\"https://images");//增加https
//自定义替换区域 end StreamWriter write = new StreamWriter(sitUrl + folder + "//" + fileName, false, Encoding.UTF8);//写入文件
write.Write(reader_write);
write.Flush();
write.Close();
p.WaitForExit();//等待程序执行完退出进程
p.Close();//关闭进程
reader.Close();//关闭流
return Json(true, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(ex.Message, JsonRequestBehavior.AllowGet);
}
} /// <summary>
/// 读取配置文件
/// </summary>
/// <param name="sitId"></param>
/// <param name="typeId"></param>
/// <returns></returns>
public static string Readjson(string sitId, string typeId)
{
string url = "";
string folder = "";
using (System.IO.StreamReader file = System.IO.File.OpenText(jsonUrl))
{
using (JsonTextReader reader = new JsonTextReader(file))
{
JObject JObject = (JObject)JToken.ReadFrom(reader);
//取站点路径
var sit = JObject["sit"];
foreach (JObject item in sit)
{
if (item["sitId"].ToString() == sitId)
{
url = item["sitUrl"].ToString();
}
}
//取文件夹名称 可为空
var type = JObject["type"];
foreach (JObject item in type)
{
if (item["typeId"].ToString() == typeId)
{
folder = item["folder"].ToString();
}
}
}
}
return JsonConvert.SerializeObject(new
{
url = url,
folder = folder
});
}
}
}
codes.js 配置
var page = require('webpage').create(), system = require('system');
var url = system.args[];
var interval = system.args[];
var settings = {
timeout: interval,
encoding: "UTF-8",
operation: "GET",
headers: {
"User-Agent": system.args[],
"Accept": system.args[],
"Accept-Language": "zh-CN,en;q=0.7,en-US;q=0.3",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": ,
"Connection": "keep-alive",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Referer": system.args[]
}
}
page.settings = settings;
page.open(url, function (status) {
phantom.outputEncoding = "UTF-8";
if (status !== 'success') {
console.log('Unable to post!');
phantom.exit();
} else {
setTimeout(function () {
console.log(page.content);
phantom.exit();
}, interval);
}
});
apiSetting.json 配置
{
"sit": [
{
"sitId": "",
"sitUrl": "D://"
},
{
"sitId": "",
"sitUrl": "D://"
}
],
"type": [
{
"typeId": "",
"folder": "zmPC"
},
{
"typeId": "",
"folder": "zmCP"
}
]
}
C#使用phantomjs,爬取AJAX加载完成之后的页面的更多相关文章
- Python+Selenium爬取动态加载页面(2)
注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...
- Python+Selenium爬取动态加载页面(1)
注: 最近有一小任务,需要收集水质和水雨信息,找了两个网站:国家地表水水质自动监测实时数据发布系统和全国水雨情网.由于这两个网站的数据都是动态加载出来的,所以我用了Selenium来完成我的数据获取. ...
- Scrapy 框架 使用 selenium 爬取动态加载内容
使用 selenium 爬取动态加载内容 开启中间件 DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMidd ...
- 爬虫再探实战(三)———爬取动态加载页面——selenium
自学python爬虫也快半年了,在目前看来,我面临着三个待解决的爬虫技术方面的问题:动态加载,多线程并发抓取,模拟登陆.目前正在不断学习相关知识.下面简单写一下用selenium处理动态加载页面相关的 ...
- Python 爬取异步加载的数据
在我们的工作中,可能会遇到这样的情况:我们需要爬取的数据是通过ajax异步加载的,这样的话通过requests得到的只是一个静态页面,而我们需要的是ajax动态加载的数据! 那我们应该怎么办呢??? ...
- Python爬虫爬取异步加载的数据
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:努力努力再努力 爬取qq音乐歌手数据接口数据 https://y.qq ...
- 爬虫再探实战(四)———爬取动态加载页面——请求json
还是上次的那个网站,就是它.现在尝试用另一种办法——直接请求json文件,来获取要抓取的信息. 第一步,检查元素,看图如下: 过滤出JS文件,并找出包含要抓取信息的js文件,之后就是构造request ...
- appendHTML方法ajax加载更多评论实例页面
//在后添加 <script>var appendHTML = function(el, html) { var divTemp = document.createElement(&quo ...
- Jsoup配合 htmlunit 爬取异步加载的网页
加入 jsoup 和 htmlunit 的依赖 <dependency> <groupId>org.jsoup</groupId> <artifactId&g ...
随机推荐
- 安装VMware虚拟机和centos操作系统
1,安装包:百度网盘: 2,安装教程:https://blog.csdn.net/qq_31362105/article/details/80706096 配置好操作系统,内存,网络等: 3,Cen ...
- Linux 系统配置永久性时间同步
临时修改系统时间(reboot后系统时间恢复): date 查看系统时间 date -s "设置的系统时间" 永久性修改系统时间: date 查看系统时间 hwclock --s ...
- Axure实现提示文本单击显示后自动消失的效果
Axure实现提示文本单击显示后自动消失的效果 方法/步骤 如图所示,框出的部分为提示文本(已经命名为tooltip),希望达到的效果是默认加载时不显示,点击帮助图标后显示,且2秒后自动消失. ...
- 安装Rabbitmq脚本
安装RabbitMQ时需要先安装erlang插件 [root@ZHONG-LONG javascripts]# vim -erlang.sh #!/bin/sh ######安装erl插件 PRO=/ ...
- 深入浅出ConcurrentHashMap1.8+CAS+volatile
1.深入浅出CAS 前言 CAS(Compare and Swap),即比较并替换,实现并发算法时常用到的一种技术,Doug lea大神在java同步器中大量使用了CAS技术,鬼斧神工的实现了多线程执 ...
- 【matlab】模拟变焦拼接代码备份
1.初版,边缘未处理. % % In----near % If----far % In=imread('D:\文件及下载相关\桌面\模拟变焦拼接\Matlab_code\nearframe\frame ...
- Qt编写自定义控件34-磁盘容量统计
一.前言 磁盘容量统计控件,说白了,就是用来统计本地盘符占用的容量,包括但不限于已用空间.剩余空间.总大小.已用百分比等,其中对应的百分比采用进度条显示,该进度条的前景色和背景色及文字颜色可以设置,在 ...
- 读取yml 文件中的参数
第一种方法: yml 文件: spring: main: allow-bean-definition-overriding: true cloud: consul: host: 192.168.1.1 ...
- Flutter 移动端屏幕适配方案和制作
flutter_screenutil插件 flutter 屏幕适配方案,让你的UI在不同尺寸的屏幕上都能显示合理的布局! 注意:此插件仍处于开发阶段,某些API可能尚未推出. 安装依赖: 安装之前请查 ...
- Java进程监控
目录 1.引言 2. 程序启停, 为进程自定义项目名称 3. 操作系统判断 4. 获取进程信息 5. 内存,CPU信息 6. 堆内存信息 7. 端口信息 8. 线程信息 9. MXBean使用样例 9 ...