利用Abot爬虫和visjs 呈现漫威宇宙

1. 引言

最近接触Abot爬虫也有几天时间了,闲来无事打算从IMDB网站上爬取一些电影数据玩玩。正好美国队长3正在热映,打算爬取漫威近几年的电影并用vis这个JS库呈现下漫威宇宙的相关电影。

Abot是一个开源的C#爬虫,代码非常轻巧。可以参看这篇文章(利用Abot 抓取博客园新闻数据)入门Abot。

Vis 是一个JS的可视化库类似于D3。vis 提供了像Network 网络图的可视化,TimeLine 可视化等等。这里用到了network,只需要给vis传入简单的节点信息,边的信息就可以自动构建一个网络图。

2. 实现

首先从数据开始,得到漫威宇宙所有相关的电影名称,这个数据网上太多了:

从电影名称到IMDB的电影页面其实有个搜索过程,还好电影数目不多,这里偷个懒直接采用IMDB的电影链接作为种子Url

        public static List<string> ImdbFeedMovies = new List<string>(){//Iron man 2008"http://www.imdb.com/title/tt1233205/",//hunk 2008"http://www.imdb.com/title/tt0800080/",//Iron man 2 2010"http://www.imdb.com/title/tt1228705/",//Thor 2011"http://www.imdb.com/title/tt0800369/",//Captain America"http://www.imdb.com/title/tt0458339/",//Averages"http://www.imdb.com/title/tt0848228/",//Iron man 3 "http://www.imdb.com/title/tt1300854/",//thor 2"http://www.imdb.com/title/tt1981115/",//Captain America 2"http://www.imdb.com/title/tt1843866/",//Guardians of the Galaxy;"http://www.imdb.com/title/tt2015381/",//Ultron"http://www.imdb.com/title/tt2395427/",//ant-man"http://www.imdb.com/title/tt0478970/",//Civil war"http://www.imdb.com/title/tt3498820/",//Doctor Strange"http://www.imdb.com/title/tt1211837/",//Guardians of the Galaxy 2;"http://www.imdb.com/title/tt3896198/",//Thor 3"http://www.imdb.com/title/tt3501632/",// Black Panther"http://www.imdb.com/title/tt1825683/",//Avengers: Infinity War - Part I"http://www.imdb.com/title/tt4154756/"};

有了种子Url 就可以利用Abot 爬取电影的数据,这里只爬取电影名称,电影图片以及演员。

这里定义一些需要用到的数据结构:

    public class MarvellItem{/// <summary>/// http://www.imdb.com/title/tt0800369//// </summary>public string ImdbUrl { get; set; }public string Name { get; set; }public string Image { get; set; }}public class ImdbMovie{public string ImdbUrl { get; set; }public string Name { get; set; }public string Image { get; set; }public DateTime Date { get; set; }public List<MarvellItem> Actors { get; set; } }public static readonly Regex MovieRegex = new Regex("http://www.imdb.com/title/tt\\d+", RegexOptions.Compiled);

Abot中爬取页面后最主要的处理函数就是PageCrawlCompletedAsync ,这里给出爬取每个电影页面后的complete Callback函数

        private ConcurrentDictionary<string, ImdbMovie> movieResult; //爬取到的电影数据        public void Moviecrawler_ProcessPageCrawlCompletedAsync(object sender, PageCrawlCompletedArgs e){if (MovieRegex.IsMatch(e.CrawledPage.Uri.AbsoluteUri)){var csTitle = e.CrawledPage.CsQueryDocument.Select(".title_block > .title_bar_wrapper > .titleBar > .title_wrapper > h1");string title = HtmlData.HtmlDecode(csTitle.Text().Trim());var datetime =e.CrawledPage.CsQueryDocument.Select(".title_block > .title_bar_wrapper > .titleBar > .title_wrapper > .subtext > a:last > meta");var year = datetime.Attr("content").Trim();var csImg = e.CrawledPage.CsQueryDocument.Select(".poster > a > img");string image = csImg.Attr("src").Trim();if (!string.IsNullOrEmpty(image)){HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(image);webRequest.Credentials = CredentialCache.DefaultCredentials;var stream = webRequest.GetResponse().GetResponseStream();if (stream != null){Image bitmap = new Bitmap(stream);image = e.CrawledPage.Uri.AbsoluteUri.GetHashCode() + ".jpg";bitmap.Save(image);}}var csTable = e.CrawledPage.CsQueryDocument.Select("#titleCast > table");var csTrs = csTable.Select("tr", csTable);List<MarvellItem> actors = new List<MarvellItem>();foreach (var tr in csTrs){var csTr = new CsQuery.CQ(tr);var cslink = csTr.Select("td > a", csTr);if (cslink.Any()){string url = NormUrl(cslink.Attr("href").Trim());string actorTitle = cslink.Select("img", cslink).Attr("title").Trim();string actorImage = cslink.Select("img", cslink).Attr("src").Trim();actors.Add(new MarvellItem(){Name = actorTitle,ImdbUrl = url,Image = actorImage});}}this.movieResult.TryAdd(e.CrawledPage.Uri.AbsoluteUri, new ImdbMovie(){Name = title,Image = image,Date = DateTime.Parse(year),ImdbUrl = e.CrawledPage.Uri.AbsoluteUri,Actors = actors});}}

该函数的主要功能就是解析电影页面,得到电影名字 电影图片 和 演员信息。这里面还有一个小trick ,由于IMDB的限制,需要把爬到的图片下载下来,否则在生产环境下<img src=””/>  图片是无法显示的.

更多这个trick的细节可以参看 关于img 403 forbidden的一些思考

对于所有的电影链接,可以采用Task 并行执行:

           Task[] movieTasks = new Task[ImdbFeedMovies.Count];System.Console.WriteLine("Start crawl Movies");for (var i = 0; i < ImdbFeedMovies.Count; i++){var url = ImdbFeedMovies[i];movieTasks[i] = new Task(() =>{System.Console.WriteLine("Start crawl:" + url);var crawler = GetManuallyConfiguredWebCrawler();ConfigMovieCrawl(crawler);crawler.Crawl(new Uri(url));System.Console.WriteLine("End crawl:" + url);});movieTasks[i].Start();}Task.WaitAll(movieTasks);System.Console.WriteLine("End crawl Movies");

结束后我们得到一堆JSON 数据

把它传到前端:

@model List<ImdbMovie><div class="clearfix" style="background-color: black; position: relative"><div id="marvel-graph"></div>
</div>@section PostScripts{<script type="text/javascript">$(function () {var nodes = [];var edges = [];@for (int i = 0; i < Model.Count; i++){var film = Model[i];<text>nodes.push({id: '@film.ImdbUrl',title: '@film.Name',borderWidth: 4,shapeProperties: {useBorderWithImage: true},shape: "image",image: '@(string.IsNullOrEmpty(film.Image) ? "" : (film.Image.StartsWith("http") ? film.Image : Href("../../Images/marvel/"+film.Image)))',color: { border: '#4db6ac', background: '#009688' }});@if (i != Model.Count - 1){<text>edges.push({from: '@film.ImdbUrl',to: '@Model[i+1].ImdbUrl',arrows: { to: true },width: 4,length:360,color: "red"});</text>
                }@foreach (var actor in film.Actors){<text>nodes.push({id: '@film.ImdbUrl' + '@actor.ImdbUrl',title: '@actor.Name',borderWidth: 4,shapeProperties: { useBorderWithImage: true },shape: "circularImage",image: '@(string.IsNullOrEmpty(actor.Image) ? "" : (actor.Image.StartsWith("http") ? actor.Image : Href("../../Images/marvel/"+actor.Image)))',});edges.push({from: '@film.ImdbUrl',to: '@film.ImdbUrl' + '@actor.ImdbUrl',arrows: { to: true }});</text>
                }</text>
            }var container = document.getElementById("marvel-graph");var visNodes = new vis.DataSet(nodes);var data = {nodes: visNodes,edges: edges};var options = {layout: { improvedLayout: false },nodes: {borderWidth: 3,font: {color: '#000000',size: 12,face: 'Segoe UI'},color: { background: '#4db6ac', border: '#009688' }},edges: {color: '#c1c1c1',width: 2,font: {color: '#2d2d2d',size: 12},smooth: {enabled: false,type: 'continuous'}}};var network = new vis.Network(container, data, options);});</script>
}

vis network 主要就是 new Network(container, data, options); 传入节点 和 边即可。

最终的效果如图:

欢迎访问我的个人主页 51zhang.net  网站还在不断开发中…..

posted on 2016-05-14 15:59 禅宗花园...迷失的佛 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/VectorZhang/p/5492735.html

利用Abot爬虫和visjs 呈现漫威宇宙相关推荐

  1. Yuga Labs的猿猴元宇宙野心:迈向Web3一代的漫威宇宙 |链捕手

    作为如今NFT行业最具影响力的玩家之一,Yuga Labs是如何诞生的?它们又为何能如此成功?接下来将如何打造猿猴元宇宙? 作者 | Richard Lee 编辑 | 龚荃宇 收购 CryptoPun ...

  2. 3d游戏建模制作流程详解 丨漫威宇宙【万磁王】

    点击上方"蓝字",关注我们. 建模干货|巴西3D艺术家的个人作品 漫威宇宙[万磁王] 使用软件zbrush等等,分享给大家,看霸气的万磁王建模作品是如何从草图开始到最终渲染成型的完 ...

  3. python爬虫怎么赚钱-个人利用Python爬虫技术怎么挣钱-10万被动收入...

    我利用Python爬虫技术年挣10万被动收入的方式,在正式聊Python爬虫技术之前,先来说说挣钱的事,说说作为一个自由职业或兼职者怎么利用爬虫来挣钱. 个人爬虫挣钱方法大致如下 爬虫技术挣钱方法1: ...

  4. python爬虫赚钱的经历-个人利用Python爬虫技术怎么挣钱-10万被动收入

    我利用Python爬虫技术年挣10万被动收入的方式,在正式聊Python爬虫技术之前,先来说说挣钱的事,说说作为一个自由职业或兼职者怎么利用爬虫来挣钱. 个人爬虫挣钱方法大致如下 爬虫技术挣钱方法1: ...

  5. 02-分享:个人利用 Python 爬虫技术怎么挣钱-1万被动收入

    你好,我是悦创. 今天我来分享一篇,猿人学的文章.原文链接:https://www.yuanrenxue.com/crawler/earn-money-python-crawler.html 我利用 ...

  6. python爬虫怎么赚钱-个人利用Python爬虫技术怎么挣钱-10万被动收入

    我利用Python爬虫技术年挣10万被动收入的方式,在正式聊Python爬虫技术之前,先来说说挣钱的事,说说作为一个自由职业或兼职者怎么利用爬虫来挣钱. 个人爬虫挣钱方法大致如下 爬虫技术挣钱方法1: ...

  7. 利用python爬虫与数据分析,打造最强玩法,轻松成为大神级玩家!

    前言: 最近迷上了一款游戏,但是作为一名程序员的我是不可能只玩游戏的,我必须把它的官网数据采集下来! 环境: windows python3.6.5 模块: requests jsonpath pyg ...

  8. 企业级Python开发大佬利用网络爬虫技术实现自动发送天气预告邮件

    前天小编带大家利用Python网络爬虫采集了天气网的实时信息,今天小编带大家更进一步,将采集到的天气信息直接发送到邮箱,带大家一起嗨~~拓展来说,这个功能放在企业级角度来看,只要我们拥有客户的邮箱,之 ...

  9. 利用pyhton爬虫(案例4)--你想要的图片都在这

    学习笔记 爬取X度某吧里的小图片们 写个小案例,获取X度里,你指定的吧里,第kkk页之前所有帖子内的图片,当然这个kkk由你定. 爬取步骤 ①获取用户指定吧名和指定页数,得到贴吧主页URL. ②获取1 ...

最新文章

  1. canal+mysql+rocket
  2. 使用docker部署一个直接可用的puppet服务端
  3. SpringMVC(SSM)框架搭建JavaWeb项目时,前端页面文件上传,后台Java下载功能实现及相关问题记录说明
  4. vue怎么自己创建组件并引用_Vue 实现创建全局组件,并且使用Vue.use() 载入方式
  5. qt linux webservice,Qt实现访问WebService
  6. jeecg-framework 采用eclipse-maven运行
  7. LeetCode刷题(23)
  8. 【Oracle】使用logmnr工具挖掘日志
  9. 工程造价为什么会出现“三超问题”?
  10. 利用ettercap进行简单的arp欺骗和mitm攻击
  11. 工业设计公司:从外观设计到软硬件设计
  12. 【CDOJ 1323】柱爷的下凡
  13. Windows返回桌面快捷键
  14. 50例大数据术语英文翻译及详解
  15. 洛谷题目P1425 小鱼的游泳时间
  16. 一个关于xgen开发导入的问题,但其实我觉得更重要的是过程中发生的事情。
  17. HDU 4544 湫湫系列故事——消灭兔子 (贪心+优先队列)
  18. ecshop支持mysql_ecshop安装不支持MySQL
  19. 技术写作的两种方向和方法
  20. 论文:lda2vev:Mixing Dirichlet Topic Models and Word Embeddings to Make lda2vec

热门文章

  1. 关于 打印机可打印无法扫描报错“使用该设备需要WIA驱动程序,请从安装CS或从...” 的解决方法
  2. 什么是DTO 什么是KYC
  3. Bash脚本中进制转换
  4. 千千静听打开卡拉OK功能和弹窗广告过滤
  5. Swift语言官方文档翻译(1)
  6. CodeForces 891E Lust(生成函数)
  7. session在html页面跳转,session跨页面传值为空
  8. 产品需求文档的写作(一) – 写前准备(信息结构图)
  9. 用python批量插入数据到数据库中
  10. html5实现百度语音播报功能