.net core之ACG小站爬虫(二)

紧跟着上一节说的文章,虽然已经放出了所写的全代码,但还是再解释一下另外一个页面的请求和分析过程吧。

PS:又可以愉快的水一章了,咕嘿嘿。


页面分析

上回说到下载按钮的href属性是javascript:;伪协议,导致了新打开的页面链接携带#符号,但是我们通过了phantomjs已经解决了第一次跳转的问题。


下载页面

事实证明,这里更加狠,连个伪协议都没有。不过没关系,我们还是沿用上回的那个方法,使用phantomjs来渲染页面并且将跳转的页面链接以响应返回给我们的客户端请求。

实现

采用上一节所说的让Phantomjs作为服务端,然后去请求它,让它把要爬取的结果反馈给.net。注意,这里的返回给客户端的响应结果可以是网页页面,也可以是Phantomjs进行HTML解析完的真实数据。

.Net Core代码

 public async Task<string> GetDownloadPageAsync(string url){string result = string.Empty;//请求phantomjs 获取下载页面string dom = "Tappable-inactive animated fadeIn";KeyValuePair<string, string> url2dom = new KeyValuePair<string, string>(url, dom);var postData = JsonConvert.SerializeObject(url2dom);CookieContainer cc = new CookieContainer();  HttpHelpers helper = new HttpHelpers();  HttpItems items = new HttpItems();HttpResults hr = new HttpResults();items.Url = this.PostUrl1;items.Method = "POST";items.Container = cc;items.Postdata = postData;items.Timeout = 100000;hr = await helper.GetHtmlAsync(items);var downloadPageUrl = hr.Html;Console.WriteLine($"first => { downloadPageUrl }");if(downloadPageUrl.Contains("http")){//获取百度云下载地址和分享密码//string code1 = "1";dom = "Tappable-inactive btn btn-success btn-block"; // 下载链接url2dom = new KeyValuePair<string, string>(downloadPageUrl, dom);postData = JsonConvert.SerializeObject(url2dom);items = new HttpItems{Url = this.PostUrl2};items.Method = "POST";items.Container = cc;items.Postdata = postData;items.Timeout = 1000000;hr = await helper.GetHtmlAsync(items);result = hr.Html; //返回json数据Console.WriteLine($"second => { result }");}else{result = downloadPageUrl; //输出错误信息}return result;}

这里包含了第一次在详情页获取下载页的那个请求,以及下载页面获取百度云链接和分享密码的请求。

JavaScript代码

"use strict";
var port = 8089;
var server = require('webserver').create();server.listen(8089, function (request, response) {//传入的参数有待更改,目前为//{"Key":"https://acg12.com/download/#60e21d8417ab60fbfJfcqnT1BC8Qd20PehAIKv3J4ZO%2FJCo0htE9hP5IFZU", //"Value":"Tappable-inactive btn btn-success btn-block"}的json字符窜//第一个参数为经过第一次请求所返回的下载页面,第二个为下载按钮的Domvar data = JSON.parse(request.postRaw);var url = data.Key.toString();console.log(url);var dom = data.Value.toString();console.log(dom);var code = 200;var pwdArray = new Array();var result = new Array();var page = require('webpage').create();page.onInitialized = function() {page.customHeaders = {};};page.settings.loadImages = false;page.customHeaders = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36","Referer": url};response.headers = {'Cache': 'no-cache','Content-Type': 'text/plain','Connection': 'Keep-Alive','Keep-Alive': 'timeout=40, max=100'};//根据Phantomjs的官网,这个回调在打开新标签页会触发page.onPageCreated = function(newPage) {//console.log('A new child page was created! Its requested URL is not yet available, though.');page.onInitialized = function() {newPage.customHeaders = {};};newPage.settings.loadImages = false;newPage.customHeaders = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36"};//newPage.viewportSize = { width: 1920, height: 1080 };//当百度云页面打开并渲染完成时触发newPage.onLoadFinished = function(status) {//console.log('A child page is Loaded: ' + newPage.url);//newPage.render('newPage.png', {format: 'png', quality: '100'});//console.log(pwdArray.length);if(pwdArray.length > 0){//console.log("enter");//从数组中pop出密码,当无密码时pop的数据为null字符窜var temp = {"url": newPage.url.toString(), "password": pwdArray.pop().toString()};console.log(JSON.stringify(temp));result.push(temp); // 将json数据push进返回结果}};};page.open(url, function (status) {console.log("----" + status);if (status !== 'success') {code = 400;response.write('4XX');response.statusCode = code;response.close();} else {code = 200;window.setTimeout(function (){//var dom = dom;pwdArray = page.evaluate(function(dom) {console.log(dom);var pwdArray = new Array();var btnList = document.getElementsByClassName(dom); // 百度云链接for(var i = 0; i < btnList.length;i ++ ){//猜测所有下载节点都有密码var temp = document.getElementById("downloadPwd-" + i);if(temp != undefined){//console.log("****" + temp.value);pwdArray.push(temp.value); // 有密码push进数组}else{//console.log("****null");pwdArray.push("null"); // 无密码则push进null字符窜,这样做到和url的一一对应}}for(var i = 0; i < btnList.length;i ++ ){//console.log("click");btnList[i].click(); // 点击下载,打开新标签页}return pwdArray;}, dom);}, 6000);}});//设置等待20秒后才发送客户端的响应结果,这样保证上述方法都能成功运行结束window.setTimeout(function(){var rs = JSON.stringify(result)console.log(rs);response.write(rs);response.statusCode = code;response.close();}, 20000);page.onConsoleMessage = function(msg, lineNum, sourceId) {console.log("$$$$$" + msg);};page.onError = function(msg, trace) {var msgStack = ['PHANTOM ERROR: ' + msg];if (trace && trace.length) {msgStack.push('TRACE:');trace.forEach(function(t) {msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function +')' : ''));});}console.log(msgStack.join('\n'));phantom.exit(1);};
});
phantom.onError = function(msg, trace) {var msgStack = ['PHANTOM ERROR: ' + msg];if (trace && trace.length) {msgStack.push('TRACE:');trace.forEach(function(t) {msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function +')' : ''));});}console.log(msgStack.join('\n'));phantom.exit(1);};

完整的源代码已经放在Github上了,里面有写好的bat文件,直接运行run.bat就行。当然前提,第一节的那些环境都配置完成了。大家下周见,下周可能可以尝试用用DotnetSpider,这是借鉴了WebMagic写的.net core地爬虫框架,有兴趣的可以先去尝试一下玩玩。

原文地址:http://www.jianshu.com/p/27bf3bb9ca60


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323563.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.net core之ACG小站爬虫(一)

想到好久没写过.net的代码了&#xff0c;因此就尝试来写一写.net的代码。此外&#xff0c;也想要熟悉一下Phantomjs。环境配置.net core下载。可选的可以下载宇宙大IDEVisual Studio&#xff0c;当然更加推荐使用Visual Studio Code进行代码的书写。Phantomjs。这个不用说了&am…

数组:完成等差等比数列,及其他数列

有没有想过用c语言来编写一些数列呢&#xff0c;编写数列&#xff0c;数组是最好的选择。 等差&#xff1a; #include<stdio.h> main(){ int a[1000],b,i;a[0]1;scanf("%d",&b);for(i0;i<b;i){a[i1]a[i]2;}for(i0;i<b;i){printf("a%d%-8d\t&q…

Spring MVC竟然有5种参数绑定的方式?你知道几种?

转载自 Spring MVC竟然有5种参数绑定的方式&#xff1f;你知道几种&#xff1f; SpringMVC参数绑定&#xff0c;简单来说就是将客户端请求的key/value数据绑定到controller方法的形参上&#xff0c;然后就可以在controller中使用该参数了下面通过5个常用的注解演示下如何进行参…

微服务中如何切换配置文件、部署

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 最近改了个微服务的项目&#xff0c;在本身的业务上加上一个演示的业务。 以前没有弄过微服务的项目&#xff0c;这次改完之后&#xff0c;部署花了不少时间&#xff0c;一方面是因为服务器…

asp.net core mvc View Component 应用

ViewComponent1、View 组件介绍在ASP.NET CORE MVC中,View组件有点类似于partial views,但是他们更强大&#xff0c;View组件不能使用model binding,当你调用它的时候仅仅依赖与你提供的数据一个View组件特点&#xff1a;.呈现一大块而不是一个整体的响应。 .包含在控制器和视…

分离三位数

#include<stdio.h> main(){ int k,l,m,n;printf("请输入一个三位数"); scanf("%d",&k);lk/100;mk/10%10;nk%10;printf("这个三位数的百位是:%d\n",l);printf("这个三位数的十位是:%d\n",m);printf("这个三位数的个位是…

大湾区第二次.NET技术交流会圆满成功

2017年9月16日的深圳阳光明媚&#xff0c;一场为庆祝.NET Core 2.0发布和.NET 社区大会&#xff08;https://www.dotnetconf.net/&#xff09; 的召开的本地社区活动&#xff0c;这次活动还得到如鹏网杨中科老师的大力支持开通网上直播&#xff0c;网上有300多位参与活动&#…

五分钟轻松了解Hbase面向列的存储

转载自 五分钟轻松了解Hbase面向列的存储 说明&#xff1a;从严格的列式存储的定义来看&#xff0c;Hbase并不属于列式存储&#xff0c;有人称它为面向列的存储&#xff0c;请各位看官注意这一点。 行式存储 传统的数据库是关系型的&#xff0c;且是按行来存储的。如下图&a…

jeecg微服务项目调用接口报错Token验证失效的解决方法

大家好&#xff0c;我是雄雄。 前言 今天&#xff0c;记录一篇啼笑皆非的问题。 昨晚上在做微信公众号开发时&#xff0c;遇到了个解决好久的问题&#xff0c;即&#xff1a;微信公众号上配置服务器信息之后&#xff0c;回调服务器接口总是报错token验证失败。 剧透&#xf…

是时候开始用C#快速开发移动应用了

从2015年接触Xamarin到至今已经2个年头&#xff0c;我对Xamarin的技能没有长进多少&#xff0c;但它却已经足够成熟到在跨平台移动开发工具中占有一席之地。在扫了一些资料之后&#xff0c;突然发现国外有很多移动端的应用已经是用Xamarin开发&#xff0c;Telerik还有专门的团队…

十分钟理解负载均衡

转载自 十分钟理解负载均衡 开头先理解一下所谓的“均衡” 不能狭义地理解为分配给所有实际服务器一样多的工作量&#xff0c;因为多台服务器的承载能力各不相同&#xff0c;这可能体现在硬件配置、网络带宽的差异&#xff0c;也可能因为某台服务器身兼多职&#xff0c;我们…

输入一个字母,转大小写

用scanf完成 #include<stdio.h> main(){char m;scanf("%c",&m);if(m>a&&m<z){mm-32;}else if(m>A&&m<Z){m32;}printf("%c",m);}用getcahr完成 #include<stdio.h> main(){char m;mgetchar();if(m>a&&…

.net core 使用Redis的发布订阅

Redis是一个性能非常强劲的内存数据库&#xff0c;它一般是作为缓存来使用&#xff0c;但是他不仅仅可以用来作为缓存&#xff0c;比如著名的分布式框架dubbo就可以用Redis来做服务注册中心。接下来介绍一下.net core 使用Redis的发布/订阅功能。Redis 发布订阅Redis 发布订阅(…

MYSQL性能优化的最佳20+条经验

转载自 MYSQL性能优化的最佳20条经验 今天&#xff0c;数据库的操作越来越成为整个应用的性能瓶颈了&#xff0c;这点对于Web应用尤其明显。关于数据库的性能&#xff0c;这并不只是DBA才需要担心的事&#xff0c;而这更是我们程序员需要去关注的事情。当我们去设计数据库表结…

用数组选出最大的数并且排序

选出数组最大的值 #include<stdio.h> main(){//选出最大的 int a[5]{200,110,101,1010,5},i,max;maxa[0];for(i0;i<5;i){if(a[i]>max){maxa[i];}} printf("%d",max); }排序 #include<stdio.h> main(){//排序 int a[5]{200,110,101,1010,5},i,max…

java实现微信服务(公众)号用户关注时,获取openid,安全模式下的加密解密实现

大家好&#xff0c;我是雄雄&#xff0c;欢迎你的到来~ 前言 需求是这样的&#xff0c;当用户关注公司服务&#xff08;公众&#xff09;号时&#xff0c;就自动注册成为了会员&#xff0c;且通过小程序设置提醒&#xff0c;然后后台可以通过服务&#xff08;公众&#xff09;…

王者荣耀是怎样炼成的(二)《王者荣耀》unity安装及使用的小白零基础入门

工欲善其事&#xff0c;必先利其器。上回书《王者荣耀是怎样炼成的&#xff08;一&#xff09;《王者荣耀》用什么开发&#xff0c;游戏入门&#xff0c;unity3D介绍》说到&#xff0c;开发游戏用到unity和C#。本篇博客将从零开始做一个unity的基础入门。\(^o^)/~欢迎大家的斧正…

史上最全MySQL 大表优化方案(长文)

转载自 史上最全MySQL 大表优化方案&#xff08;长文&#xff09; 当MySQL单表记录数过大时&#xff0c;增删改查性能都会急剧下降&#xff0c;可以参考以下步骤来优化&#xff1a; 一、单表优化 除非单表数据未来会一直不断上涨&#xff0c;否则不要一开始就考虑拆分&…

阶乘的值

#include<stdio.h> main(){//阶乘 int a,i,sum;printf("请输入你所需要的阶乘数&#xff1a;\n");scanf("%d",&a);sum1;for(i1;i<a;i){sumsum*i;} printf("%d",sum); } 输出阶乘的数

“.Net 社区大会”(dotnetConf) 2017 Day 1 Keynote: .NET Everywhere

8月份已经发布了.NET Core 2.0, 大会Keynote 一开始花了大量的篇幅回顾.NET Core 2.0的发布&#xff0c;社区的参与度已经非常高。大会的主题是.NET 无处不在&#xff1a;NET Core 2.0已经完成了服务端的布局&#xff0c;那么各种终端的覆盖就是Xamarin的主场&#xff0c;Xamar…