Python爬虫之新天龙八部

Posted by JD on May 22, 2019

背景

新天龙八部已经是十二年的老游戏,但我对它的热情不减当年。不过,游戏内的人已经走了一批又一批,游戏账号在一批批人的打造中加强了许多。这里主要是爬取全部服务器排行前50的角色装备评分,并做一个简单的分析。

排行榜

它的排行榜页面也比较特别。可以看它源代码。

但是渲染后,可以看到

这说明,它是异步的,我们需要找到传输给前端的选项文件。

依旧是打开Chrome,进入排行榜页面,按下F12,点击Network,选择XHR。重新刷新页面,会发现

看到srvlist.txt文件,里面有乱码,但是看格式貌似就是我们想要的。

好的,转下编码看下,发现正是所需option信息。

首先获取srvlist.txt文件。

发现Request URL有记录获取地址

import requests
import pandas as pd

srvlist_url = "http://twjh.changyou.com/html/tldata/srvlist.txt"
headers = {
            'User-Agent': ('Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36'
                           ' (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36')
}
r = requests.get(srvlist_url, headers=headers)
r.encoding = 'utf-8'
sers = r.text
df = pd.DataFrame([ser.split(',') for ser in sers.split('\n')[:-1]],
                  columns=['daqu', 'qu', 'id'])
df.head()

代码输出

  daqu qu id
0 东部电信 九阴真经 38
1 东部电信 玉女心经 154
2 东部电信 北冥神功 65
3 东部电信 雁翎枪 65
4 东部电信 七伤拳 9140

找到每个选项后,发现下面展示的top50其实是嵌入的,使用iframe框架。

在属性src中,只需改变id就可以得到不同的服务器的排名,比如下图中的1053

df.id.size  # 761
df.id.unique().size  # 82
df.id.unique()

# array(['38', '154', '65', '9140', '172', '1010', '155', '47', '149',
         '2020', '1015', '3145', '1161', '162', '1191', '188', '182', '68',
         '1171', '2021', '191', '209', '198', '3048', '3144', '137', '168',
         '2202', '3081', '2201', '3016', '3079', '3085', '3125', '3128',
         '5024', '3200', '3202', '5057', '5016', '2082', '101', '22',
         '1138', '1053', '118', '2093', '111', '4036', '85', '134', '1043',
         '1042', '14', '3192', '3161', '4025', '5038', '5013', '5060',
         '5065', '5072', '5068', '5069', '5076', '5075', '5083', '5088',
         '5089', '5090', '5091', '5092', '5093', '5074', '5084', '5087',
         '5096', '5097', '5094', '5095', '9031', '9015'], dtype=object)

这十二年,居然开了761个区,搜狐真的很疯狂。

这么多区,也掩盖不了这游戏的没落,通过不断的合区,只剩下82个区。为什么合区,玩过网游都知道,就是因为区里人太少,要节约成本增加区里的活跃度,就开始合区!

把合区信息存到数据库中,并且以id为主键,将合并区的名称拼接起来。

data_qu = (df.groupby('id')['qu']
             .apply(lambda x: ','.join(x.values))
             .reset_index())
data_qu.columns = 'qu_id','qu_name'
data_qu.to_sql('tlbb_qu', con=conn,
               if_exists='append', index=False)

数据库中展示成

然后,就该爬取iframe里的内容,选择id=38

这里面我们需要爬取每一个角色的信息,包括排名装备评分等级门派所属帮派

<tr>里有5个<td>,就包含所要信息。

代码撸起来

qu_id = '38'
qu_ph_url = f"http://www.tl.changyou.com/tlbbrank/{qu_id}/top50zhanli.html"
ph_r = requests.get(qu_ph_url, headers=headers)
ph = BeautifulSoup(ph_r.content.decode('ANSI').replace('&nbsp;',''), 'lxml')
trs = ph.findAll('tr')[1:]
df_qu = pd.DataFrame([[td.text for td in tr.findAll('td')] for tr in trs],
             columns=['ph', 'player_name', 'score', 'grade', 'school', 'gang'])
df_qu['qu_id'] = qu_id
df_qu.head()

代码输出

  ph player_name score grade school gang qu_id
0 1 ﹡﹒芝芝芒芒 1309672 119 逍遥 水泊梁山 38
1 2 龍戰メ粱山 1046449 119 逍遥 水泊梁山 38
2 3 龍戰メ乐小雨 985207 119 唐门 水泊梁山 38
3 4 Moon°﹎欣子 827651 119 天山 月光下的光芒 38
4 5 ゞ冷锋 794809 119 唐门 天缘山庄 38

将数据存入mysql数据库,数据库对应的表示tlbb_ph

configs = {
            'host': '127.0.0.1',
            'user': 'root',
            'password': 'password',
            'database': 'testdb'
}
conn = create_engine("mysql+pymysql://{user}:{password}@{host}:3306/{database}".format(**configs))
df_qu.to_sql('tlbb_ph', con=conn, if_exists='append', index=False)

这个区的爬取工作完成,数据也可以保存到文件。然后相同方式爬取剩下81个区。

排名分析

统计每个区的总装备评分

data = pd.read_sql('select * from tlbb_ph', con=conn)
qu = pd.read_sql('select * from tlbb_qu', con=conn)
data_sum = data.groupby(['qu_id'])['score'].aggregate(np.sum).reset_index()
sort_data = (pd.merge(left=data_sum, right=qu, how='inner', on='qu_id')
               .sort_values(by='score', ascending=False)
               .reset_index(drop=True))
sort_data.head(10)

前十个区,如下图

第一就是阿牛哥的武林至尊,毕竟这么多大号。

没有想到宠爱一生居然可以排到第二,作为一个没有合过多少次的区,也真的是强!

薛慕华也是大神云集,王大驴是不是还在飞机上。

这些大区都是有曾经有大神坐镇,大神打造起号来真疯狂。

百万评分个数top10

top10 = (data[data['score'] >= 1000000].groupby('qu_id')['score']
                                       .size()
                                       .reset_index()
                                       .sort_values(by='score', ascending=False)
                                       .head(10))
pd.merge(left=top10, right=qu, how='inner', on='qu_id')

都是出了名的大区,感叹当年平头多么强势,霸占争霸赛多少年。现在已经不行了,合区少,并且老板也走了。天龙真的全靠这些大老板,不然压根起不了这么多的大号。

还是没想到,居然张艺兴兴的区有这么多大号!

各门派人数

school = (data.groupby('school')
              .size()
              .sort_values(ascending=False)
              .reset_index())
school.columns = 'school', 'qty'
ax = school.plot.bar(x='school', y='qty',
                     rot=0, figsize=(18, 10), fontsize=20)
fig = ax.get_figure()
fig.savefig(r'school.jpg')

观察下图有感,天山和唐门真的是亲儿子,玩的人也多。为什么这么多人玩,就是暴力!逍遥也是很多人喜欢,毕竟当年也是有一波绿蛤蟆浪潮。

慕容和少林真的是少的可怜,伤害虽然高,可怜腿短,没有爆发。

鬼谷还是有情可原,毕竟新门派。

但是门派差距也忒大了,畅游真的有必要调整下游戏的平衡性。