【大作业】一个完整的大作业

一、作业要求

1、选一个自己感兴趣的主题。

2、网络上爬取相关的数据。

3、进行文本分析,生成词云。

4、对文本分析结果解释说明。

5、写一篇完整的博客,附上源代码、数据爬取及分析结果,形成一个可展示的成果。

 

二、游戏王卡片简介

       《游戏王OCG》是由KONAMI研发、吉尼斯世界纪录认证的全世界销量最高的集换式卡牌游戏。改编自漫画《游戏王》中登场的卡片游戏“魔法与巫师卡”(动画版称为“决斗怪兽”),使用游戏王卡片进行对战的卡牌类益智游戏。这些卡片比普通的扑克稍大,卡上的图案取材于各种神话传说及未来幻想,包括日本、古印度、古埃及、古巴比伦等,还标明了该怪兽的属性、攻击、防守值与怪兽的效果(或介绍)。

       游戏王卡片于1999年在日本发售,至今包括英文专属版本卡片在内,已经发行了8568张不同的卡片。

       游戏王卡片基本种类有三种,分别是怪兽卡、陷阱卡和魔法卡,各类卡片还有子类卡片。怪兽卡都基本拥有名称、属性、种族、效果、攻击力与防守力的基本属性,此外还有星级属性,但由于后来发行的怪兽卡片类型出现了星级、阶级、连接级等针对不同怪兽卡片的星级属性,不再统一化,所以在本次爬虫中不会获取“星级”这个属性。而陷阱卡和魔法卡只有名称、属性、种类和效果这四个基本属性。

图1  游戏王卡片的基本种类

图2  游戏王卡片的基本属性

图3  游戏王卡片的属性类型的详细子类型

        国内游戏王爱好玩家聚在一起开发了在线卡查的游戏王查询网站,方便游戏王爱好者查询和及时了解卡片的最新信息。本次数据搜索与分析便基于这个在线卡查网站来进行爬虫。网站主页面为http://www.ourocg.cn/Cards/Lists-5-1。

三、爬虫步骤

1、爬取总页数

1 #函数功能:获取卡片的总页数
2 def getpage():
3     flag1 = '搜索结果     / 约 ' #该变量内容为总页数所在字段文本的前部分文字
4     flag2 = ''
5     card_page = soup.select('.result')[0].text.lstrip(flag1) #获取到总页数所在的字段文本    
6     page_num = card_page.find(flag2) #查找“条”字符所在的位置
7     allpage = int(card_page[0:page_num]) #输出“条”字前面的数字,即总卡片数
8     page = allpage//18  #输出总页数,每页有18条卡片记录
9     return page   

2、爬取卡片信息

       由于上面所说的星数问题,因此怪兽卡只获取名称、链接、类型、属性、种族和效果这6个元素,而由于魔法陷阱卡与怪兽卡有别,又为了能使它们的信息都放在同一张表上,因此魔法陷阱卡的信息中属性与种族的信息为空,以便保留格式一致。

 1 #函数功能:获取魔法陷阱卡的信息
 2 def getdetail_MagicTrap(url_MT):
 3     resd = requests.get(url_MT)
 4     resd.encoding = 'utf-8'
 5     soup_MT = BeautifulSoup(resd.text,'html.parser')
 6     card_news_MagicTrap = {}   
 7     for news in soup_MT.select('.card'):
 8         card_news_MagicTrap['名称'] = news.select('div')[3].text
 9         card_news_MagicTrap['链接'] = url_MT
10         card_type = news.select('div')[12].text
11         card_news_MagicTrap['类型'] = card_type[0:4]
12         card_news_MagicTrap['属性'] = ' '
13         card_news_MagicTrap['种族'] = ' '
14         card_effect_text = news.select(".effect")[0].text           
15         card_news_MagicTrap['效果'] = card_effect_text[2:len(card_effect_text)-1] 
16     return card_news_MagicTrap
17 
18 #函数功能:获取怪兽卡的信息
19 def getdetail_Monster(url_M):
20     resd = requests.get(url_M)
21     resd.encoding = 'utf-8'
22     soup_M = BeautifulSoup(resd.text,'html.parser')
23     card_news_Monster = {}   
24     for news in soup_M.select('.card'):
25         card_news_Monster['名称'] = news.select('div')[3].text
26         card_news_Monster['链接'] = url_M
27         card_type = news.select('div')[12].text
28         card_news_Monster['类型'] = card_type[0:4]
29         card_news_Monster['属性'] = news.select('div')[24].text
30         card_news_Monster['种族'] = news.select('div')[22].text
31         card_effect_text = news.select(".effect")[0].text           
32         card_news_Monster['效果'] = card_effect_text[0:len(card_effect_text)-1] 
33     return card_news_Monster

3、爬取每一页的卡片信息

       每个卡片信息都有个共同的h2标签作为开头,利用这个特性可以获取到每个卡片的链接,之后通过创建一个字符串来判断该卡片是何种类型的卡片,从而调用上面的不同种类的函数来获取卡片的信息。

 1 #函数功能:获取一个页面的卡片信息
 2 def onepage(url_page):
 3     res = requests.get(url_page)
 4     res.encoding = 'utf-8'
 5     soup_page = BeautifulSoup(res.text,'html.parser')
 6     card_newsls = [] #创建一个列表
 7     for allnews in soup_page.select('.card'):
 8         if len(allnews.select('h2'))>0:
 9             card_maintype = allnews.select('span')[0].text           
10             url = allnews.select('a')[0]['href']
11             card_url = ('http://www.ourocg.cn{}'.format(url))
12             if card_maintype in card_judge:   #这里用来判断卡片是怪兽卡还是魔法陷阱卡
13                 card_newsls.append(getdetail_MagicTrap(card_url))                
14             else:
15                 card_newsls.append(getdetail_Monster(card_url))               
16             #append():接受一个参数,这个参数可以是任何数据类型,并且简单地追加到list的尾部
17     return card_newsls
18 
19 card_judge = '魔法陷阱' #该字符串变量用于判断卡片是何类卡片

4、生成所有卡片信息的列表

 1 news_cardtotal = []  #存放所有卡片信息
 2 url_cards = 'http://www.ourocg.cn/Cards/Lists-5-1'  #网站首页
 3 news_cardtotal.extend(onepage(url_cards))  #把新list中的每个元素添加到原list中
 4 
 5 res_card = requests.get(url_cards)
 6 res_card.encoding = 'utf-8'  
 7 soup = BeautifulSoup(res_card.text,"html.parser")
 8 
 9 for i in range(2,getpage()+1):   #通过循环获取首页之后页数的卡片信息列表
10     url_list = 'http://www.ourocg.cn/Cards/Lists-5-{}'.format(i)
11     news_cardtotal.extend(onepage(url_list))
12 
13 df = pandas.DataFrame(news_cardtotal)  #转换成表格型数据(DataFrame型)
14 df.to_excel('card_info.xlsx')   #以excel表的形式保存结果

生成的结果可以用Excel表来查看具体的内容:

5、分词与云图的生成

 1 for j in range(len(news_cardtotal)):
 2     if j>0:
 3         race = race+news_cardtotal[j].get('种族')
 4         race = race+' '
 5     else:
 6         race = news_cardtotal[j].get('种族')
 7         race = race+' '
 8 words = jieba.lcut(race)   #进行文本分词
 9 
10 ls = []      #存放词组文本
11 counts = {}  #存放词组的计数
12 for word in words:
13     ls.append(word)
14     if len(word) == 0:
15         continue
16     else:
17         counts[word] = counts.get(word,0)+1  #计数字典
18 items = list(counts.items())  #计数列表
19 items.sort(key = lambda x:x[1], reverse = True)  #排序
20 for j in range(10):
21     word , count = items[j]
22     print ("{:<10}{:>5}".format(word,count))
23 
24 cy = WordCloud().generate(race)  #词云的制作与显示
25 plt.imshow(cy)
26 plt.axis("off")  #不显示标尺
27 plt.show()

          由于数量庞大,所以在电脑后台可以看到大量的数据流量交换。

 

四、结果分析

这次大作业会分析以下三点:

1、各种族的怪兽卡有多少张?(例如战士族的怪兽卡有多少张)哪个种族的卡片最多?

       我们把分词的关键词选为“种族”后进行分词,生成的文本用来生成云图。为了使分词更加准确,在每个分词后会添加一个空格以避免重复计算和重义计算,所以结果中空格永远会占最高排名位。代码与上面第五点一样。

       从结果最终可以看出,战士族是卡片数量最多的,主要是因为战士族是第一批发行的怪兽种族,而且主体系列卡片也比较多,自然比例就很高。

2、怪兽卡、魔法卡、陷阱卡的卡片数量以及它们子类卡片的数量比例是多少?

       我们把分词的关键词选为“类型”后进行分词,生成的文本用来生成云图即可。由于每个词都属于关键词,因此不需要做排除词的操作。

       从结果可以看出,怪兽卡的数量最多,而魔法陷阱卡的数量相差不大,而其中,效果怪兽的数量最多。这是因为游戏王每次发行卡包时都是40张怪兽卡、10张魔法卡和10张陷阱卡的,另外也会发行数量不规则的系列卡包,但是这占了少数。

3、卡片名称中哪些词出现的最多?

我们把分词的关键词选为“名称”后进行分词,生成的文本用来生成云图即可。

       由结果可以看出,“元素英雄”和“娱乐伙伴”的卡片最多。其实这些词都代表了一个系列的卡片,而“元素英雄”和“娱乐伙伴”系列是游戏王动画中第二代主角和第四部主角使用的系列卡片,加上衍生出的发行卡片,数量自然相对比较多。

 五、完整代码

  1 #——游戏王卡片信息爬虫——
  2 #——最后修改时间:2017.11.02——
  3 
  4 import requests
  5 import re
  6 import jieba
  7 import pandas
  8 import matplotlib.pyplot as plt
  9 from bs4 import BeautifulSoup
 10 from wordcloud import WordCloud
 11 
 12 #函数功能:获取卡片的总页数
 13 def getpage():
 14     flag1 = '搜索结果     / 约 ' #该变量内容为总页数所在字段文本的前部分文字
 15     flag2 = ''
 16     card_page = soup.select('.result')[0].text.lstrip(flag1) #获取到总页数所在的字段文本    
 17     page_num = card_page.find(flag2) #查找“条”字符所在的位置
 18     allpage = int(card_page[0:page_num]) #输出“条”字前面的数字,即总卡片数
 19     page = allpage//18  #输出总页数,每页有18条卡片记录
 20     return page   
 21 
 22 #函数功能:获取魔法陷阱卡的信息
 23 def getdetail_MagicTrap(url_MT):
 24     resd = requests.get(url_MT)
 25     resd.encoding = 'utf-8'
 26     soup_MT = BeautifulSoup(resd.text,'html.parser')
 27     card_news_MagicTrap = {}   
 28     for news in soup_MT.select('.card'):
 29         card_news_MagicTrap['名称'] = news.select('div')[3].text
 30         card_news_MagicTrap['链接'] = url_MT
 31         card_type = news.select('div')[12].text
 32         card_news_MagicTrap['类型'] = card_type[0:4]
 33         card_news_MagicTrap['属性'] = ' '
 34         card_news_MagicTrap['种族'] = ' '
 35         card_effect_text = news.select(".effect")[0].text           
 36         card_news_MagicTrap['效果'] = card_effect_text[2:len(card_effect_text)-1] 
 37     return card_news_MagicTrap
 38 
 39 #函数功能:获取怪兽卡的信息
 40 def getdetail_Monster(url_M):
 41     resd = requests.get(url_M)
 42     resd.encoding = 'utf-8'
 43     soup_M = BeautifulSoup(resd.text,'html.parser')
 44     card_news_Monster = {}   
 45     for news in soup_M.select('.card'):
 46         card_news_Monster['名称'] = news.select('div')[3].text
 47         card_news_Monster['链接'] = url_M
 48         card_type = news.select('div')[12].text
 49         card_news_Monster['类型'] = card_type[0:4]
 50         card_news_Monster['属性'] = news.select('div')[24].text
 51         card_news_Monster['种族'] = news.select('div')[22].text
 52         card_effect_text = news.select(".effect")[0].text           
 53         card_news_Monster['效果'] = card_effect_text[0:len(card_effect_text)-1] 
 54     return card_news_Monster
 55 
 56 #函数功能:获取一个页面的卡片信息
 57 def onepage(url_page):
 58     res = requests.get(url_page)
 59     res.encoding = 'utf-8'
 60     soup_page = BeautifulSoup(res.text,'html.parser')
 61     card_newsls = [] #创建一个列表
 62     for allnews in soup_page.select('.card'):
 63         if len(allnews.select('h2'))>0:
 64             card_maintype = allnews.select('span')[0].text           
 65             url = allnews.select('a')[0]['href']
 66             card_url = ('http://www.ourocg.cn{}'.format(url))
 67             if card_maintype in card_judge:   #这里用来判断卡片是怪兽卡还是魔法陷阱卡
 68                 card_newsls.append(getdetail_MagicTrap(card_url))                
 69             else:
 70                 card_newsls.append(getdetail_Monster(card_url))               
 71             #append():接受一个参数,这个参数可以是任何数据类型,并且简单地追加到list的尾部
 72     return card_newsls
 73 
 74 card_judge = '魔法陷阱' #该字符串变量用于判断卡片是何类卡片
 75 
 76 news_cardtotal = []  #存放所有卡片信息
 77 url_cards = 'http://www.ourocg.cn/Cards/Lists-5-1'  #网站首页
 78 news_cardtotal.extend(onepage(url_cards))  #把新list中的每个元素添加到原list中
 79 
 80 res_card = requests.get(url_cards)
 81 res_card.encoding = 'utf-8'  
 82 soup = BeautifulSoup(res_card.text,"html.parser")
 83 
 84 for i in range(2,getpage()+1):   #通过循环获取首页之后页数的卡片信息列表
 85     url_list = 'http://www.ourocg.cn/Cards/Lists-5-{}'.format(i)
 86     news_cardtotal.extend(onepage(url_list))
 87 
 88 df = pandas.DataFrame(news_cardtotal)  #转换成表格型数据(DataFrame型)
 89 df.to_excel('card_info.xlsx')   #以excel表的形式保存结果
 90 
 91 for j in range(len(news_cardtotal)):
 92     if j>0:
 93         race = race+news_cardtotal[j].get('种族')
 94         race = race+' '
 95     else:
 96         race = news_cardtotal[j].get('种族')
 97         race = race+' '
 98 words = jieba.lcut(race)   #进行文本分词
 99 
100 ls = []      #存放词组文本
101 counts = {}  #存放词组的计数
102 for word in words:
103     ls.append(word)
104     if len(word) == 0:
105         continue
106     else:
107         counts[word] = counts.get(word,0)+1  #计数字典
108 items = list(counts.items())  #计数列表
109 items.sort(key = lambda x:x[1], reverse = True)  #排序
110 for j in range(10):
111     word , count = items[j]
112     print ("{:<10}{:>5}".format(word,count))
113 
114 cy = WordCloud().generate(race)  #词云的制作与显示
115 plt.imshow(cy)
116 plt.axis("off")  #不显示标尺
117 plt.show()
游戏王卡片爬虫完整代码

 

posted @ 2017-11-02 16:28  27杨华星  阅读(339)  评论(0编辑  收藏  举报