想到好久没写过.net的代码了,因此就尝试来写一写.net的代码。此外,也想要熟悉一下Phantomjs。


环境配置

  • .net core下载。可选的可以下载宇宙大IDEVisual Studio,当然更加推荐使用Visual Studio Code进行代码的书写。

  • Phantomjs。这个不用说了,今天的主角。采用无头浏览器爬取ACG小站的很大原因是它的页面很难分析,此外也有熟悉一下Phantomjs的意思。

  • HttpCode.Core,是一个.net core的HTTP请求库,可以使用Nuget安装。库本质上是基于HttpWebRequest实现的,但是为了舍去我们自己封装的麻烦,就采用此库来减少代码量。

  • AngleSharp,一个帮助解析HTML的.net库,可以直接使用LINQ来查询,很方便。

页面分析

详情页

就以其中随便的一个动漫链接下载为例子,发现了坑爹的玩意,下载链接的href属性是javascript:;。介于浅薄的javascript知识,百度了才知道这个是伪协议,实际运行了一段js代码回调,从而打开了新的页面。但是这个网站是用React写的,更可怕的在下面。

JavaScript

原本采用直接分析,并借助Debug调试来分析它点击后的回调函数,但是这个JavaScript文件竟然有2万行代码,Chrome打开调试定点,根本就没法format,不然直接卡死,于是放弃了这个念头,转而采用无头浏览器进行爬取。

实现

一般采用Phantomjs的手段都为Selenium+Phantomjs,但是性能不是很好,而且暂时也没怎么找.netSelenium接口,所以就选用了最近看到的直接让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 = "http://localhost:8088/";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")){# TODO}else{result = downloadPageUrl; //输出错误信息}return result;}

这里展示的是第一部分的代码,即请求详情页的代码,还未涉及到点了下载按钮之后页面的分析,实际上差不多。

JavaScript代码

"use strict";
var port = 8088;
var server = require('webserver').create();//服务端监听
server.listen(8088, function (request, response) {//传入的参数有待更改,目前为//{"Key":"https://acg12.com/200340/", "Value":"Tappable-inactive animated fadeIn"}的json字符窜//第一个参数为详情页,第二个为下载按钮的Domvar data = JSON.parse(request.postRaw);var url = data.Key.toString();var dom = data.Value.toString();var code = 0;var page = require('webpage').create();//初始化headerspage.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=20, max=100'};//根据Phantomjs的官网,这个回调在打开新标签页会触发page.onPageCreated = function(newPage) {//console.log('A new child page was created! Its requested URL is not yet available, though.');newPage.onLoadFinished = function(status) {console.log('A child page is Loaded: ' + newPage.url);//newPage.render('newPage.png');response.write(newPage.url);response.statusCode = code;response.close(); //写入返回给.net端的响应内容。};};//让Phantomjs帮助我们去请求页面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 (){//执行JavaScript代码,类似于在浏览器Console中执行JavaScriptpage.evaluate(function(dom) {console.log(dom);var btnList = document.getElementsByClassName(dom);if(btnList.length > 0){var btn = document.getElementsByClassName(dom)[1]; // 获取下载按钮btn.click(); //点击下载按钮,打开新标签页,触发page.onPageCreated回调函数。}}, dom);        }, 7000);}});//根据Phantomjs的官网,这个回调主要应对执行evaluate函数内部的console.log输出,因为两个环境是隔离的。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);};

这里的注释比较详细,就不细说了。

启动上述Phantomjs服务端的脚本

phantomjs  --ssl-protocol=any --debug=true .\server_get_detail_page.js

第一个参数是为了保持ssl的链接,第二个参数开启debug,第三个参数为上面的JavaScript代码。

还有之后的页面类似于以上的代码,但是有一些细节需要注意,为了防止文章过长(明明是再水一篇(๑ ̄ _   ̄๑))大家下期再见。等等,完整的源代码就先全放在Github上了

原文地址:http://www.jianshu.com/p/9b738a25b585


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

.net core之ACG小站爬虫(一)相关推荐

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

    紧跟着上一节说的文章,虽然已经放出了所写的全代码,但还是再解释一下另外一个页面的请求和分析过程吧. PS:又可以愉快的水一章了,咕嘿嘿. 页面分析 上回说到下载按钮的href属性是javascript ...

  2. .net core 实现简单爬虫—抓取博客园的博文列表

    一.介绍一个Http请求框架HttpCode.Core HttpCode.Core 源自于HttpCode(传送门),不同的是 HttpCode.Core是基于.net standard 2.0实现的 ...

  3. 推荐13个.Net开源的网络爬虫

    1:.Net开源的跨平台爬虫框架 DotnetSpider Star:430 DotnetSpider这是国人开源的一个跨平台.高性能.轻量级的爬虫软件,采用 C# 开发.目前是.Net开源爬虫最为优 ...

  4. VSCrawler 爬虫 java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory 解决方案

    长长的报错信息如下: 13:39:15.345 [main] WARN c.v.vscrawler.core.event.EventLoop - 程序已停止 13:39:15.376 [main] I ...

  5. 使用Python打造基本WEB漏洞扫描器(一) 网站爬虫+SQL注入检测

    一.实验介绍 扫描器需要实现功能的思维导图: 1.1 实验内容 编写一个简单的多线程爬虫,用于对网站地址进行爬取,编写一个简单的sql注入工具,用于对网站地址进行sql注入的检测. 1.2 实验知识点 ...

  6. Scrapy源码阅读分析_3_核心组件

    From:https://blog.csdn.net/weixin_37947156/article/details/74481758 这篇这要是关于核心组件,讲解这些核心组件初始化都做了哪些工作.包 ...

  7. 推荐一款.NET Core开源爬虫神器:DotnetSpider

    没有爬虫就没有互联网! 爬虫的意义在于采集大批量数据,然后基于此进行加工/分析,做更有意义的事情.谷歌,百度,今日头条,天眼查都离不开爬虫. 去开源中国和Github查询C#的爬虫项目,仅有几个非常简 ...

  8. ASP.NET Core 中的 User Agent 识别及搜索引擎爬虫鉴定方法

    User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器渲染引擎.浏览器语言.浏览器插件等. 百度百科 在 ...

  9. 发现一款.NET Core开源爬虫神器:DotnetSpider

    没有爬虫就没有互联网! 爬虫的意义在于采集大批量数据,然后基于此进行加工/分析,做更有意义的事情.谷歌,百度,今日头条,天眼查都离不开爬虫. 去开源中国和Github查询C#的爬虫项目,仅有几个非常简 ...

最新文章

  1. ITAA在线试学用户使用说明
  2. 解散了地图接口讨论群
  3. 通讯框架 t-io 学习——websocket 部分源码解析
  4. tableau应用实战案例(一)-如何通过Tableau绘制小提琴图
  5. 小工匠聊架构 - 分布式缓存技术
  6. python的protected和private
  7. UNIX再学习 -- TCP/UDP 客户机/服务器
  8. 你想带一顶什么样的硕士帽(转载)
  9. excel 2007 vba与宏完全剖析_Excel宏VBA小技巧系列 | 分段加合
  10. java 使用json-lib 对象,String,json互转
  11. c# 关于DataTable
  12. Spring MVC登录实例
  13. SQL 不常用的一些命令sp_OACreate,xp_cmdshell,sp_makewebtask
  14. 478.在圆内随机生成点
  15. 超薄计算机的HDMI接口,机身轻薄两面观 笔记本接口变化趋势解析
  16. 把ATmega128开发板转为Arduino
  17. 初中计算机会考知识点大全,初中信息技术会考知识点复习提纲
  18. 别让你的项目,毁在单片机选型上
  19. 淘客该怎么做,淘客+又是什么
  20. linux 临时文件夹设置,Linux 系统 tmp 目录的安全设置

热门文章

  1. 如何离线安装chrome插件
  2. exchange2013 owa-outlook界面语言
  3. JavaScript中“javascript:void(0) ”是什么意思
  4. java以Blob形式存储,读取图片并在jsp页面显示图片流
  5. UVA 11090 Going in Cycle!! 二分答案 + bellman-ford
  6. [转]ArcGIS.Server.9.3和ArcGIS API for Flex实现Toolbar功能(四)
  7. 思科3550 IOS
  8. HangFire循环作业中作业因执行时间太长未完成新作业开启导致重复数据的问题...
  9. OneOfT1,…,Tn清新
  10. 如何在 C# 中使用 反射