【C#】WinForm 之 DOTA2英雄搭配助手(网页抓取+在线绿色版+源码开放)

睡不着,无聊......再整理点好玩的出来。先上图


效果


碎碎念

自从13级后打出DOTA2的天梯积分以来简直是逆水行舟不进则退啊,室友已经高呼着被游戏玩了!!结果怒删游戏

其实我也发现这游戏不合适我玩…天梯里场场被各种选英雄针对,普通场又是剑圣、斧王横行。加之本人比较懒,不爱看视频,场均10死那是常有的事(打起来跟打WOW战场一样,反正死了有复活:P)

不瞎扯了,其实初衷就是不想被针对(想选个最脏阵容神马的我会告诉你嘛)


核心功能

这里要从Dotamax(http://dotamax.com/)说起,因为程序的核心都是在于如何抓取该DOTA2数据门户提供的英雄数据。

看了这个网站相信大家基本有数了,说好的大数据、可视化这网站就用上了。我这里用的就是“克制指数”与“配合指数”(高玩说这个还是比较靠谱的,然后我就信了)。

通过以下函数获得目标地址的网页内容(我基本用的是字符串处理,DOM分析也是没问题的)

private string GetWebContent(string Url)
        {
            string strResult = "";
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
                //声明一个HttpWebRequest请求
                request.Timeout = 30000;
                //设置连接超时时间
                request.Headers.Set("Pragma", "no-cache");
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream streamReceive = response.GetResponseStream();
                Encoding encoding = Encoding.GetEncoding("utf-8");
                StreamReader streamReader = new StreamReader(streamReceive, encoding);
                strResult = streamReader.ReadToEnd();
            }
            catch
            {
                MessageBox.Show("获取信息失败,请检查网络连接");
            }
            return strResult;
        }

以下是抓取的步骤,由于本人第一次做此类应用,小白之处请及时指出哈。

A.抓取英雄信息

首先是抓取英雄信息。

目标URL:  http://dotamax.com/hero/

页面分析:

<div id="半人马战行者" class="hero-list-hero Unused-Hero" onclick="DoNav(‘/hero/detail/centaur/‘)">
    <img class="hero-hover opacity-img img-shadow" src="http://www.dota2.com.cn/images/heroes/centaur_hphover.png">
    <div class="hero-top-list-bar">
        <span style="position: absolute;left:5px;color:rgb(87,186,53);bottom:-4px;"><img src="/static/image/overviewicon_str.png" style="width:15px;"></span>
    </div>
    <div class="hero-list-bar">
        <span style="color:#ccc !important;text-align: center;">半人马战行者 </span>
    </div>
</div>

从这段标签应该很容易找到

  • 中文英雄名称
  • 英文英雄名称
  • 英雄头像

这几个字段有了后就可以建立本地缓存或者添加一行记录了,具体代码:

private void getHeros()
        {
            heroDataTable = new DataTable("heros");
            heroDataTable.Columns.Add("英雄名", typeof(string));            

            //要抓取的URL地址
            string Url = "http://www.dotamax.com/hero/";
            //得到指定Url的源码
            string html = GetWebContent(Url);

            string EnName, ChName;
            string key;
            int index = 0;
            //string output = "";
            int count = 0;

            do
            {
                key = "onclick=\"DoNav(‘/hero/detail/";
                int i = html.IndexOf(key, index);

                if (i == -1)
                    break;

                i += key.Length;
                int j = html.IndexOf("/", i);
                EnName = html.Substring(i, j - i);

                key = "<span style=\"color:#ccc !important;text-align: center;\">";
                i = html.IndexOf(key, j + 1);
                i += key.Length;
                j = html.IndexOf(" </span>", i);
                ChName = html.Substring(i, j - i);

                Ch2En.Add(ChName, EnName);
                heroList.Add(ChName);

                DataRow dr = heroDataTable.NewRow();
                dr["英雄名"] = ChName;
                heroDataTable.Rows.Add(dr);
                count++;

                index = j;

            } while (true);
        }

B.抓取克制指数

根据英雄名称,到指定URL抓取克制该英雄的英雄列表。

目标URL:http://dotamax.com/hero/detail/match_up_anti/英文英雄名称/

页面分析:

<tr>
    <td>
        <a href="/hero/detail/phantom_assassin"><img class="hero-img-list" src="http://www.dota2.com.cn/images/heroes/phantom_assassin_hphover.png"></a>
        <span class="hero-name-list">幻影刺客</span>
    </td>
    <td>
        <div style="height: 10px">3.19%</div>
        <div class="segment segment-green" style="width:33.997677256%;"></div>
    </td>
    <td>
        <div style="height: 10px">56.96%</div>
        <div class="segment segment-gold" style="width:56.9584024346%;"></div>
    </td>
    <td>
        <div style="height: 10px">292445</div>
        <div class="segment segment-green" style="width:%;"></div>
    </td>
</tr>

页面中有大段的注释干扰(不知道是不是特意设置 don‘t care),反正注意跳过去,别抓错

<!--
                    <td><div style="height: 10px">%</div><div class="segment segment-green" style="width:%;"></div></td><td><div style="height: 10px">%</div><div class="segment segment-green" style="width:%;"></div></td>
                    -->

从这段标签找到

  • 克制英雄名称
  • 克制指数

这样子如果自己这方选了该克制英雄就加上对应克制指数。然后按这个数值排好序,给出推荐。具体代码:

private void addAntiIndex(string hero,int no)
        {
            no++;

            string CurEnName = Ch2En[hero];
            string CurChName = hero;
            string Url = "http://www.dotamax.com/hero/detail/match_up_anti/" + CurEnName + "/";
            //得到指定Url的源码
            html = GetWebContent(Url);

            string AntiName, AntiValue, WinRate, UsedTime;
            string key;
            int index = 0;;

            do
            {
                key = "<span class=\"hero-name-list\">";
                int i = html.IndexOf(key, index);

                if (i == -1)
                {
                    autoSorting();
                    return;
                }

                i += key.Length;
                int j = html.IndexOf("</span>", i);
                AntiName = html.Substring(i, j - i);

                key = "<div style=\"height: 10px\">";
                i = html.IndexOf(key, j + 1);
                i += key.Length;
                j = html.IndexOf("</div>", i);
                AntiValue = html.Substring(i, j - i);

                //去除反抓取
                j = html.IndexOf("-->", j);

                key = "<div style=\"height: 10px\">";
                i = html.IndexOf(key, j + 3);
                i += key.Length;
                j = html.IndexOf("</div>", i);
                WinRate = html.Substring(i, j - i);

                key = "<div style=\"height: 10px\">";
                i = html.IndexOf(key, j + 1);
                i += key.Length;
                j = html.IndexOf("</div>", i);
                UsedTime = html.Substring(i, j - i);

                index = j;

                AntiValue = AntiValue.Substring(0, AntiValue.Length - 1);
                double value = Convert.ToDouble(AntiValue);
                int t_no = findHero(AntiName);
                heroDataTable.Rows[t_no][no] = -value;

                double sum = 0;
                for (int h = 2; h < 12; h++)
                {
                    sum += (double)heroDataTable.Rows[t_no][h];
                }
                heroDataTable.Rows[t_no][1] = sum;
            } while (true);
        }

C.抓取配合指数

根据英雄名称,到指定URL抓取配合该英雄的英雄列表。

目标URL:http://dotamax.com/hero/detail/match_up_comb/英文英雄名称/

页面跟之前那步基本没什么区别,这里就不重复说了。

目的是找到

  • 配合英雄名称
  • 配合指数

这样在克制对面的基础上,继续结合队友选择的英雄,选出最XXX阵容。具体代码:

private void addCombIndex(string hero, int no)
        {
            no++;

            string CurEnName = Ch2En[hero];
            string CurChName = hero;
            string Url = "http://www.dotamax.com/hero/detail/match_up_comb/" + CurEnName + "/";
            //得到指定Url的源码
            html = GetWebContent(Url);

            string CombName, CombValue, WinRate, UsedTime;
            string key;
            int index = 0; ;

            do
            {
                key = "<span class=\"hero-name-list\">";
                int i = html.IndexOf(key, index);

                if (i == -1)
                {
                    autoSorting();
                    return;
                }

                i += key.Length;
                int j = html.IndexOf("</span>", i);
                CombName = html.Substring(i, j - i);

                key = "<div style=\"height: 10px\">";
                i = html.IndexOf(key, j + 1);
                i += key.Length;
                j = html.IndexOf("</div>", i);
                CombValue = html.Substring(i, j - i);

                //去除反抓取
                j = html.IndexOf("-->", j);

                key = "<div style=\"height: 10px\">";
                i = html.IndexOf(key, j + 3);
                i += key.Length;
                j = html.IndexOf("</div>", i);
                WinRate = html.Substring(i, j - i);

                key = "<div style=\"height: 10px\">";
                i = html.IndexOf(key, j + 1);
                i += key.Length;
                j = html.IndexOf("</div>", i);
                UsedTime = html.Substring(i, j - i);

                index = j;

                CombValue = CombValue.Substring(0, CombValue.Length - 1);
                double value = Convert.ToDouble(CombValue);
                int t_no = findHero(CombName);
                heroDataTable.Rows[t_no][no] = value;

                double sum = 0;
                for (int h = 2; h < 12; h++)
                {
                    sum += (double)heroDataTable.Rows[t_no][h];
                }
                heroDataTable.Rows[t_no][1] = sum;
            } while (true);
        }

D.简单的查找、排序

这个貌似没啥好说的.

写在最后

本人先后使用txt文件、MS-SQL(VS比较方便)缓存网页数据,但为了简化安装方便基友测试还是再写了一个在线绿色版本,即:边分析边显示,所有数据仅用变量存储,只占用部分内存而不生成任何缓存文件,整个程序仅一个exe文件。

当然,C#的程序还是需要预先有 .net framework,然而身为CS专业的小伙伴竟然还真有没装.NET的,我已无力吐槽

不过这样子也有个问题就是响应速度变慢了,因为除了启动程序的时候将所有英雄信息导入内存以外,每添加一个英雄还要抓取一次克制/配合信息。反正我自己肯定是用离线版的拉,不然哪有时间边选英雄边统计数据,不过大家真要改改也快的哈,而且看着爬过来的数据填满数据库,感觉良好:P

其实最最大的问题在于手动添加英雄太麻烦了,但是DOTA2貌似只有RPG版才能做Lua插件…反正我真心不知道多玩盒子这些DOTA插件是怎么跟游戏交互的。so 只能做成"DOTA2英雄搭配助手"而不是啥"最脏DOTA2插件"了…有谁知道的话求告诉哈~那啥,我还是很想做成XXXX插件的哈。(说模式识别的基友你好,再见!)

Dota2Aid在线绿色版: http://files.cnblogs.com/files/KC-Mei/Dota2Aid.zip (不知道那个帮助写明白没,应该是能用的吧)

恩,说好的开源,VS2012的项目文件: https://github.com/Blz-Galaxy/Dota2Aid_OnlineVersion

由于自己都用的是本地数据库版本,在线版的可能还有一些BUG没修复,原谅我懒得改了…反正感觉这个响应速度打死我也不会真正用这个。

继续跪求多玩盒子的交互原理…

最后附赠个MS-SQL服务监视器,做本地数据库的话搭配用妥妥的~

【C#】WinForm 之 SQL Server 服务监控器(避免开机启动服务)http://www.cnblogs.com/KC-Mei/p/4334179.html

时间: 2024-10-11 05:50:44

【C#】WinForm 之 DOTA2英雄搭配助手(网页抓取+在线绿色版+源码开放)的相关文章

一个实用的C#网页抓取类代码分享

一个实用的C# 网页抓取类 模拟蜘蛛,类中定义了超多的C#采集文章.网页抓取文章的基础技巧,下面分享代码: using System; using System.Data; using System.Configuration; using System.Net; using System.IO; using System.Text; using System.Collections.Generic; using System.Text.RegularExpressions; using Sys

用Python进行网页抓取

引言 从网页中提取信息的需求日益剧增,其重要性也越来越明显.每隔几周,我自己就想要到网页上提取一些信息.比如上周我们考虑建立一个有关各种数据科学在线课程的欢迎程度和意见的索引.我们不仅需要找出新的课程,还要抓取对课程的评论,对它们进行总结后建立一些衡量指标.这是一个问题或产品,其功效更多地取决于网页抓取和信息提取(数据集)的技术,而非以往我们使用的数据汇总技术. 网页信息提取的方式 从网页中提取信息有一些方法.使用API可能被认为是从网站提取信息的最佳方法.几乎所有的大型网站,像Twitter.

基于Casperjs的网页抓取技术【抓取豆瓣信息网络爬虫实战示例】

CasperJS is a navigation scripting & testing utility for the PhantomJS (WebKit) and SlimerJS (Gecko) headless browsers, written in Javascript. PhantomJS是基于WebKit内核的headless browser SlimerJS则是基于Gecko内核的headless browser Headless browser: 无界面显示的浏览器,可以用于

网页抓取:PHP实现网页爬虫方式小结

来源:http://www.ido321.com/1158.html 抓取某一个网页中的内容,需要对DOM树进行解析,找到指定节点后,再抓取我们需要的内容,过程有点繁琐.LZ总结了几种常用的.易于实现的网页抓取方式,如果熟悉JQuery选择器,这几种框架会相当简单. 一.Ganon 项目地址: http://code.google.com/p/ganon/ 文档: http://code.google.com/p/ganon/w/list 测试:抓取我的网站首页所有class属性值是focus的

淘搜索之网页抓取系统分析与实现(2)—redis + scrapy

1.scrapy+redis使用 (1)应用 这里redis与scrapy一起,scrapy作为crawler,而redis作为scrapy的调度器.如架构图中的②所示.图1 架构图 (2)为什么选择redis redis作为调度器的实现仍然和其特性相关,可见<一淘搜索之网页抓取系统分析与实现(1)--redis使用>(http://blog.csdn.net/u012150179/article/details/38226711)中关于redis的分析. 2.redis实现scrapy sc

用python做网页抓取与解析入门笔记[zz]

(from http://chentingpc.me/article/?id=961) 事情的起因是,我做survey的时候搜到了这两本书:Computational Social Network Analysis和Computational Social Network,感觉都蛮不错的,想下载下来看看,但是点开网页发现这个只能分章节下载,晕,我可没时间一章一章下载,想起了迅雷的下载全部链接,试试看,果真可以把他们一网打尽,但是,sadly,迅雷下载的时候,文件名没办法跟章节名对应起来,晕,我可

网页抓取

### -*- coding: cp936 -*-###<a href="http://home.51cto.com" target="_blank">家园</a>##import urllib##str0='<a href="http://home.51cto.com" target="_blank">家园</a>'##href=str0.find('<a href')#

网页抓取与处理的一些方法

昨天还是2014,今天就变成了2015.时间总是那么快,这篇文章就作为2015年的一个开始吧. 这篇文章主要介绍一些网页抓取及抓取下来的内容处理. 所需要的jar包点击打开链接,我放在百度云盘里.有需要的可以下载,其他的请自行下载. 百度百科对网页抓取的定义,当然本文并没有介绍的那么多,只是介绍对单个页面的抓取,和模拟提交表单抓取页面,如需深究,请自行baidu or google. 上面的方法直接返回String字符串,只需传入一个链接即可.相信大家都看的懂. 那么获取到的String字符串,

一个极其简洁的Python网页抓取程序

paip. 混合编程的实现resin4 (自带Quercus ) 配置 php 环境 #---混合编程的类型 1.代码inline 方式 2.使用库/api  解析方式. #----配置resin 支持php resin4默认自动支持php.. 也能手动配置了.web.xml加php的servlet解析..参考Quercus让你的PHP开心在Servlet容器奔跑 #----配置 php.ini路线 运行t.php,,看见 Configuration File (php.ini) Path =>