用python對steam一萬個遊戲的資料分析
發現Github和知乎上關於steam的爬蟲和資料分析比較少,同時想找個專案實戰一下,而且steam對於爬蟲相對友好,非常適合作為一個練手的專案,於是就有了這篇文章。
分為兩大部分
一。爬取steam遊戲資訊:需要有相關包‘requests’,‘bs4’,‘pandas’,‘re’
二。清洗資料及資料視覺化:需要有相關包‘pandas’,‘re’,matplotlib’,‘pandas’,‘numpy’
一.爬取steam遊戲資訊
整體來說steam還是很好爬的,不加headers都可以成功get到頁面,但是因為有的遊戲頁面進入前會驗證年齡之類的,解決方法:重新抓重新定向的頁面。我嫌麻煩,直接在賬號設定裡可以關閉提示,然後加headers就沒有這個問題了。而且不需要代理池和限制頻率,還是很友好的。
1.1 先爬熱銷遊戲的列表
主要就提取遊戲的連結和ID,轉成dataframe然後儲存。steam每個遊戲都有自己的ID,比如csgo的連結是store。steampowered。com/app/730/CounterStrike_Global_Offensive/
730就是遊戲的ID,後面就是遊戲的名字,即使不加名字也是可以重定向到這個頁面。本來是想透過連結提取遊戲名字的,結果發現漢字名字在連結中不會顯示,比如三國志14:
https://
store。steampowered。com/
app/872410/14/
的只會顯示14,索性放棄,在後面1。2中再提取遊戲名字。另外get的網址後面已經加上過濾DLC的引數了。
如果你是Python初學者:一共需要修改3個引數 一個是headers,一個是爬取頁數n的值,以及儲存路徑path,然後run就可以了。
import
requests
from
bs4
import
BeautifulSoup
import
re
import
pandas
as
pd
headers
=
{
‘Accept’
:
‘’
,
‘Accept-Encoding’
:
‘’
,
‘Accept-Language’
:
‘’
,
‘Cache-Control’
:
‘’
,
‘Connection’
:
‘’
,
‘Cookie’
:
‘’
,
‘Host’
:
‘’
,
‘Sec-Fetch-Mode’
:
‘’
,
‘Sec-Fetch-Site’
:
‘’
,
‘Sec-Fetch-User’
:
‘’
,
‘Upgrade-Insecure-Requests’
:
‘’
,
‘User-Agent’
:
‘’
}
#替換你自己的headers
n
=
20
#n代表爬取到多少頁
path
=
‘1。xlsx’
#修改你的儲存位置
def
getgamelist
(
n
):
linklist
=
[]
IDlist
=
[]
for
pagenum
in
range
(
1
,
n
):
r
=
requests
。
get
(
‘https://store。steampowered。com/search/?ignore_preferences=1&category1=998&os=win&filter=globaltopsellers&page=
%d
’
%
pagenum
,
headers
=
headers
)
soup
=
BeautifulSoup
(
r
。
text
,
‘lxml’
)
soups
=
soup
。
find_all
(
href
=
re
。
compile
(
r
“https://store。steampowered。com/app/”
),
class_
=
“search_result_row ds_collapse_flag”
)
for
i
in
soups
:
i
=
i
。
attrs
i
=
i
[
‘href’
]
link
=
re
。
search
(
‘https://store。steampowered。com/app/(\d*?)/’
,
i
)
。
group
()
ID
=
re
。
search
(
‘https://store。steampowered。com/app/(\d*?)/(。*?)/’
,
i
)
。
group
(
1
)
linklist
。
append
(
link
)
IDlist
。
append
(
ID
)
(
‘已完成’
+
str
(
pagenum
)
+
‘頁,目前共’
+
str
(
len
(
linklist
)))
return
linklist
,
IDlist
def
getdf
(
n
):
#轉df
linklist
,
IDlist
=
getgamelist
(
n
)
df
=
pd
。
DataFrame
(
list
(
zip
(
linklist
,
IDlist
)),
columns
=
[
‘Link’
,
‘ID’
])
return
df
if
__name__
==
“__main__”
:
df
=
getdf
(
n
)
#n代表爬取到多少頁
df
。
to_excel
(
path
)
#儲存
df是這個樣子的:
1.2爬詳細資訊。
基本思路是對df遍歷每行資料。對於每行來說,用requests。get(Link),再用bs4解析,然後提取出關鍵字(名字,價格,好評率,評論等),然後寫入df中。
def
gamename
(
soup
):
#遊戲名字
try
:
a
=
soup
。
find
(
class_
=
“apphub_AppName”
)
k
=
str
(
a
。
string
)
except
:
a
=
soup
。
find
(
class_
=
“apphub_AppName”
)
k
=
str
(
a
。
text
)
return
k
def
gameprice
(
soup
):
#價格
try
:
a
=
soup
。
findAll
(
class_
=
“discount_original_price”
)
for
i
in
a
:
if
re
。
search
(
‘¥|free|免費’
,
str
(
i
),
re
。
IGNORECASE
):
a
=
i
k
=
str
(
a
。
string
)
。
replace
(
‘ ’
,
‘’
)
。
replace
(
‘
\n
’
,
‘’
)
。
replace
(
‘
\r
’
,
‘’
)
。
replace
(
‘ ’
,
‘’
)
except
:
a
=
soup
。
findAll
(
class_
=
“game_purchase_price price”
)
for
i
in
a
:
if
re
。
search
(
‘¥|free|免費’
,
str
(
i
),
re
。
IGNORECASE
):
a
=
i
k
=
str
(
a
。
string
)
。
replace
(
‘ ’
,
‘’
)
。
replace
(
‘
\n
’
,
‘’
)
。
replace
(
‘
\r
’
,
‘’
)
。
replace
(
‘ ’
,
‘’
)
return
k
def
taglist
(
soup
):
#標籤列表
list1
=
[]
a
=
soup
。
find_all
(
class_
=
“app_tag”
)
for
i
in
a
:
k
=
str
(
i
。
string
)
。
replace
(
‘ ’
,
‘’
)
。
replace
(
‘
\n
’
,
‘’
)
。
replace
(
‘
\r
’
,
‘’
)
if
k
==
‘+’
:
pass
else
:
list1
。
append
(
k
)
list1
=
str
(
‘
\n
’
。
join
(
list1
))
return
list1
def
description
(
soup
):
#遊戲描述
a
=
soup
。
find
(
class_
=
“game_description_snippet”
)
k
=
str
(
a
。
string
)
。
replace
(
‘ ’
,
‘’
)
。
replace
(
‘
\n
’
,
‘’
)
。
replace
(
‘
\r
’
,
‘’
)
return
k
def
reviewsummary
(
soup
):
#總體評價
a
=
soup
。
find
(
class_
=
“summary column”
)
try
:
k
=
str
(
a
。
span
。
string
)
except
:
k
=
str
(
a
。
text
)
return
k
def
getdate
(
soup
):
#發行日期
a
=
soup
。
find
(
class_
=
“date”
)
k
=
str
(
a
。
string
)
return
k
def
userreviewsrate
(
soup
):
#總體數量好評率
a
=
soup
。
find
(
class_
=
“user_reviews_summary_row”
)
k
=
str
((
a
。
attrs
)[
‘data-tooltip-html’
])
return
k
def
developer
(
soup
):
#開發商
a
=
soup
。
find
(
id
=
“developers_list”
)
k
=
str
(
a
。
a
。
string
)
return
k
def
getreviews
(
ID
):
#獲取評論
r1
=
requests
。
get
(
‘https://store。steampowered。com/appreviews/
%s
?cursor=*&day_range=30&start_date=-1&end_date=-1&date_range_type=all&filter=summary&language=schinese&l=schinese&review_type=all&purchase_type=all&playtime_filter_min=0&playtime_filter_max=0&filter_offtopic_activity=1’
%
str
(
ID
),
headers
=
headers
,
timeout
=
10
)
soup
=
BeautifulSoup
(
r1
。
json
()[
‘html’
],
‘lxml’
)
a
=
soup
。
findAll
(
class_
=
“content”
)
list1
=
[]
for
i
in
a
:
list1
。
append
(
i
。
text
。
replace
(
‘ ’
,
‘’
)
。
replace
(
‘
\n
’
,
‘’
)
。
replace
(
‘
\r
’
,
‘’
)
。
replace
(
‘ ’
,
‘,’
))
k
=
str
(
‘
\n
’
。
join
(
list1
))
return
k
def
getdetail
(
x
):
tag
,
des
,
reviews
,
date
,
rate
,
dev
,
review
,
name
,
price
=
‘ ’
,
‘ ’
,
‘ ’
,
‘ ’
,
‘ ’
,
‘ ’
,
‘ ’
,
‘ ’
,
‘ ’
global
count
try
:
r
=
requests
。
get
(
x
[
‘Link’
],
headers
=
headers
,
timeout
=
10
)
except
:
(
‘伺服器無響應1’
)
try
:
r
=
requests
。
get
(
x
[
‘Link’
],
headers
=
headers
,
timeout
=
10
)
except
:
(
‘伺服器無響應2’
)
try
:
r
=
requests
。
get
(
x
[
‘Link’
],
headers
=
headers
,
timeout
=
10
)
except
:
(
‘伺服器無響應3’
)
try
:
soup
=
BeautifulSoup
(
r
。
text
,
‘lxml’
)
name
=
gamename
(
soup
)
tag
=
taglist
(
soup
)
des
=
description
(
soup
)
reviews
=
reviewsummary
(
soup
)
date
=
getdate
(
soup
)
rate
=
userreviewsrate
(
soup
)
dev
=
developer
(
soup
)
review
=
getreviews
(
str
(
x
[
‘ID’
]))
price
=
gameprice
(
soup
)
(
‘已完成: ’
+
name
+
str
(
x
[
‘ID’
])
+
‘第
%d
個’
%
count
)
except
:
(
‘未完成: ’
+
str
(
x
[
‘ID’
])
+
‘第
%d
個’
%
count
)
price
=
‘error’
count
+=
1
return
name
,
price
,
tag
,
des
,
reviews
,
date
,
rate
,
dev
,
review
if
__name__
==
“__main__”
:
df1
=
pd
。
read_excel
(
‘1。xlsx’
)
count
=
1
df1
[
‘詳細’
]
=
df1
。
apply
(
lambda
x
:
getdetail
(
x
),
axis
=
1
)
df1
[
‘名字’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
0
],
axis
=
1
)
df1
[
‘價格’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
1
],
axis
=
1
)
df1
[
‘標籤’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
2
],
axis
=
1
)
df1
[
‘描述’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
3
],
axis
=
1
)
df1
[
‘近期評價’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
4
],
axis
=
1
)
df1
[
‘發行日期’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
5
],
axis
=
1
)
df1
[
‘近期數量好評率’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
6
],
axis
=
1
)
df1
[
‘開發商’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
7
],
axis
=
1
)
df1
[
‘評論’
]
=
df1
。
apply
(
lambda
x
:
x
[
‘詳細’
][
8
],
axis
=
1
)
df1
。
to_excel
(
‘2。xlsx’
)
(
‘已完成全部’
)
大概說幾句,各個函式中實在懶得給變數起名字了。評價指標選擇的是近期,不是總體。因為我沒想到能夠用apply函式同時,在dataframe中寫入多列的方法。所以傳送一次get請求後把各類資訊作為元組打包寫入[‘詳細’],最終還要把[‘詳細’]裡的元組再依次提取出來寫入各列。結果如下圖,
我一共爬了一萬個遊戲,不同時期獲取的結果也會有所不同,因為地區限制等原因某些遊戲不在國區賣,所以是直接df中drop還是自備梯子就取決於你自己了。
1.3爬線上人數
steam自己有個資料統計的網頁,直接while迴圈+time。sleep簡單粗暴,每10分鐘以當前時間為名把資料直接儲存為xlsx格式。我直接丟vps上24小時跑了。
while True:
try:
r = requests。get(‘https://store。steampowered。com/stats/Steam-Game-and-Player-Statistics?l=schinese’,headers = headers ,timeout=15)
if r。status_code == 200:
soup = BeautifulSoup(r。text, ‘lxml’)
a = soup。findAll(class_=“player_count_row”)
NOW =[]
MAX=[]
ID=[]
for i in a :
NOW。append(str(i。contents[1]。span。string))
MAX。append(str(i。contents[3]。span。string))
ID。append(re。search(‘\d+’,str(i。contents[7]。a。attrs[‘href’]))。group())
df = pd。DataFrame(list(zip(NOW, MAX,ID)),
columns =[‘now’,‘max’, ‘ID’])
df1 = df。set_index(‘ID’)
path_stats = str(time。strftime(“%Y年%m月%d日%H時%M分%S秒”,time。localtime()))+‘。xlsx’
df1。to_excel(path_stats)
print(path_stats)
time。sleep(600)
except:
pass
二。清洗資料及資料視覺化:
2。1資料清洗
這部分相對簡單,因為爬取的資料已經相對來說比較規範了。由於我忘記備份最初始的原始文件了,所以以下範例只用200條遊戲資料做的。
首先
import pandas as pd
import re
然後讀取之前爬蟲的結果
path
=
‘’
df
=
pd
。
read_excel
(
path
,
index_col
=
0
)
df
。
info
()
#看一下資料結構
結果如下
首先看一下價格這一列
實際在爬蟲爬取的遊戲中,大多數都是價格,少部分是‘免費遊玩’‘Free’之類的,極少部分是遊戲demo,遊戲demo這個就很煩,還要根據實際情況判斷遊戲價格,由於數量極少,直接歸為免費遊戲。
def price(x):
try:
pricenum = int(x[‘價格’]。replace(‘¥’,‘’))
except:
pricenum = 0
return pricenum
df[‘價格’] = df。apply(lambda x:price(x),axis=1)
df[‘價格’] = pd。to_numeric(df[‘價格’])#轉為int64
df。info()
結果如下,可以看到價格一列已經變成int64
接下來提取評價人數和好評率
def getreviewsnum(x):
x1 = x[‘總體數量好評率’]
x2 = x[‘總體評價’]
if re。search(‘過去 30 天內的 (。*?) 篇使用者評測中有 (\d*%) 為好評。’,x1):
num = re。search(‘過去 30 天內的 (。*?) 篇使用者評測中有 (\d*%) 為好評。’,x1)。group(1)
elif re。search(‘(\d*) 篇使用者的遊戲評測中有 (\d*%) 為好評。’,x1):
num = re。search(‘(\d*) 篇使用者的遊戲評測中有 (\d*%) 為好評。’,x1)。group(1)
elif re。search(‘\d* 篇使用者評測’,x2):
num = re。search(‘(\d*) 篇使用者評測’,x2)。group(1)
else:
num = ‘0’
return num
def getreviewsrate(x):
x = x[‘總體數量好評率’]
if re。search(‘過去 30 天內的 (。*?) 篇使用者評測中有 (\d*%) 為好評。’,x):
rate = re。search(‘過去 30 天內的 (。*?) 篇使用者評測中有 (\d*%) 為好評。’,x)。group(2)
elif re。search(‘(\d*) 篇使用者的遊戲評測中有 (\d*%) 為好評。’,x):
rate = re。search(‘(\d*) 篇使用者的遊戲評測中有 (\d*%) 為好評。’,x)。group(2)
else :
rate=‘’
return rate
df[‘評價數量’]=df。apply(lambda x:getreviewsnum(x),axis=1)
df[‘好評率’]=df。apply(lambda x:getreviewsrate(x),axis=1)
df
結果如下,可以看到後面多了2列
然後同價格一樣,轉一下格式
df
[
‘評價數量’
]
=
df
[
‘評價數量’
]
。
apply
(
lambda
x
:
x
。
replace
(
‘,’
,
‘’
))
df
[
‘好評率’
]
=
df
[
‘好評率’
]
。
apply
(
lambda
x
:
str
(
x
)
。
replace
(
‘%’
,
‘’
))
df
[
‘評價數量’
]
=
pd
。
to_numeric
(
df
[
‘評價數量’
])
df
[
‘好評率’
]
=
pd
。
to_numeric
(
df
[
‘好評率’
])
df
[
‘ID’
]
=
df
[
‘ID’
]
。
astype
(
‘str’
)
#這裡順路把ID轉為str
df
。
to_excel
(
path
)
最後說一下發行時間這裡,這裡又有一些坑,因為存在部分資料沒有日或者月的情況,所以我並沒找到簡便的方式把日期變成datetime格式。這裡如果有大佬可以教我一下,不勝感激。
但是方法總是有的嘛,開啟excel,把這一列改為短日期格式,但是並沒有變化。這裡如果雙擊一下那個單元格,發現變成了我們想要的格式,
怎麼批次改呢,我在網上搜到這樣的方式
資料→分列→下一步→下一步(選擇日期)→完成
然後就ok了,5秒搞定。
這時我們重新讀一下df發現已經變成datetime64格式了。
把爬取過程中產生的沒用的列刪掉,最後儲存
df=df。drop(‘Unnamed: 0。1’, axis=1)
df。to_excel(path)
關於遊戲玩家實時數量的資料我打算攢夠一個月再做清洗分析,等資料量夠了我再補這部分的內容。
2.2 資料視覺化
首先
#coding:utf-8
import
pandas
as
pd
import
numpy
as
np
import
matplotlib。pyplot
as
plt
from
matplotlib
import
cm
import
datetime
plt
。
rcParams
[
‘font。sans-serif’
]
=
[
‘SimHei’
]
#用來正常顯示中文標籤
plt
。
rcParams
[
‘axes。unicode_minus’
]
=
False
#用來正常顯示負號
讀取檔案,把發行日期的年份提取到額外的一列[‘year’]後面會用到,然後選取前一千行製作一份copy,選取評價數量為0的也就是未發售的遊戲也製作一份copy。
dfraw = pd。read_excel(path,index_col=0)
dfraw[‘year’] = dfraw。apply(lambda x:str(x[‘發行日期’])[0:4],axis = 1)
df = dfraw。copy()
df_top1k = dfraw[0:1000]。copy()
df_now = dfraw[dfraw[‘評價數量’]。values!=0]。copy()
看一下整體情況,這裡我爬了一萬條,但是有些未在國區發售,去除掉之後還剩9887條。
df。info()
df。describe()
可以看到平均遊戲價格41。91,平均好評率79。28,畫出一個散點圖看一下分佈情況
Y
=
df_now
[
‘價格’
]
# 每一個點的Y值
X
=
df_now
[
‘發行日期’
]
# 每一個點的X值
plt
。
style
。
use
(
‘seaborn’
)
#畫布風格
plt
。
rcParams
[
‘font。sans-serif’
]
=
[
‘Microsoft YaHei’
]
#字型
plt
。
figure
(
figsize
=
(
20
,
5
))
#大小
#這裡散點大小是熱銷排行的倒數,也就是說越熱銷的遊戲,圓點也就越大
#顏色取決於好評率高低,colorbar也就是cmap選擇‘RdYlBu’風格
plt
。
scatter
(
X
,
Y
,
s
=
15000
/
(
df_now
。
index
+
200
),
c
=
df_now
[
‘好評率’
],
alpha
=。
9
,
cmap
=
plt
。
get_cmap
(
‘RdYlBu’
))
plt
。
colorbar
()
。
set_label
(
‘好評率’
,
fontsize
=
20
)
plt
。
xlabel
(
‘年份’
,
fontsize
=
20
)
plt
。
ylabel
(
‘價格’
,
fontsize
=
20
)
plt
。
show
()
可以看到已釋出的遊戲絕大多數分佈在2010年到2020年,0到200元以內,少部分遊戲突破了400元。如果區域性放大一下
Y = df_now[‘價格’] # 每一個點的Y值
X = df_now[‘發行日期’]# 每一個點的X值
plt。style。use(‘seaborn’)#畫布風格
plt。rcParams[‘font。sans-serif’]=[‘Microsoft YaHei’]#字型
plt。figure(figsize=(20, 5))#大小
#這裡散點大小是熱銷排行的倒數,也就是說越熱銷的遊戲,圓點也就越大
#顏色取決於好評率高低,colorbar也就是cmap選擇‘RdYlBu’風格
plt。scatter(X,Y, s=15000/(df_now。index+200), c=df_now[‘好評率’], alpha=。9,cmap=plt。get_cmap(‘RdYlBu’))
datenow = datetime。datetime(2021,1,1)
dstart = datetime。datetime(2010,1,1)
plt。xlim(dstart, datenow)
plt。ylim(0, 500)
plt。xlabel(‘年份’,fontsize=20)
plt。ylabel(‘價格’,fontsize=20)
plt。colorbar()。set_label(‘好評率’,fontsize=20)
plt。show()
接下來以年分組進行平均價格和平均好評率的計算繪入圖中,
df_yearprice = df。groupby(‘year’)[‘價格’]。mean()。to_frame()。reset_index()。sort_values(by=‘year’)#按年分組,求平均價格
df_yearreview = df。groupby(‘year’)[‘好評率’]。mean()。to_frame()。reset_index()。sort_values(by=‘year’)#按年分組,求平均好評率
plt。figure(figsize=(20, 5))
plt。plot(df_yearreview[‘year’],df_yearreview[‘好評率’], c=‘g’,label=‘平均好評率%’)
plt。plot(df_yearprice[‘year’],df_yearprice[‘價格’], c=‘c’,label=‘平均價格’)
plt。xlabel(‘年份’,fontsize=20)
plt。legend()
plt。title(‘年份與價格、好評率’)
plt。xlim(4,35)
plt。ylim(0, 100)
plt。show()
從1990年到2020年遊戲平均價格從20多增長到50多,相對比,2019年2個月豬肉就能翻一倍。但這樣對比其實並不科學,因為可以看出來2019年以前在2013年平均價格達到了峰值,之後因為湧入了大量的免(ke)費(jin)遊戲以及遊戲模式的改變(比如開箱子GO、DLC DAY 2等)導致遊戲的入門價格平均值在不斷的被拉低。好評率在30年內還算相對穩定。
接下來根據遊戲型別做一個整體統計,根據我們爬的遊戲標籤對遊戲做分類,首先做標籤的詞頻統計,這裡的思路就是把所有的標籤作為一個list,然後遍歷list統計為dict,然後做降序處理。這裡繪2次圖選擇不同的資料來源,一次全部一萬個遊戲,一次為前1000個遊戲。以下程式碼是全部一萬個,前1000只需要把所有df改為df_top1k就可以。
list1 = []
list1 = df[‘標籤’]。to_list()#全部一萬個
list1 = ‘\n’。join(list1)
list1 =list1。split(‘\n’)#把所有標籤加入list1
frequency = {}
frequency1 = {}
for word in list1:#詞頻統計
if word not in frequency:
frequency[word] = 1
else:
frequency[word] += 1
frequency = sorted(frequency。items(),key = lambda x :x[1], reverse=True)#根據詞頻降序做排列輸出一個元組
for i in frequency:
frequency1[str(i[0])[0:2]+‘\n’+str(i[0])[2:4]+‘\n’+str(i[0])[4:6]+‘\n’+str(i[0])[6:8]]=i[1]#元組轉為字典,再讓標籤每隔2個字加\n,後面柱狀圖會用到
dffre = df。copy()
for i in list(frequency)[0:50]:#檢驗50個tag覆蓋率
dffre = dffre[dffre[‘標籤’]。str。contains(i[0])== False]
print(len(dffre))
這裡輸出了21,說明50個遊戲標籤覆蓋了絕大多數遊戲,只有21個遊戲沒在這個範圍內。然後繪圖不再詳細說了,跟前面差不多。
Y = list(frequency1。keys())[0:50]#取前50個標籤
X = list(frequency1。values())[0:50]
plt。figure( figsize=(20, 5),)
plt。bar(Y,X, facecolor=‘#ff9999’, edgecolor=‘white’)
plt。xlabel(‘遊戲型別’,fontsize=20)
plt。ylabel(‘遊戲數量’,fontsize=20)
plt。xlim(-。5, 49。5)
for a,b in zip(Y,X):
plt。text(a, b,int(b), ha=‘center’, va= ‘bottom’,fontsize=10)
plt。show()
資料來源為全部的結果
資料來源為熱銷榜前一千的結果
從整體上講,都符合長尾型分佈,獨立 單人 動作 冒險這四種無論是否為熱銷遊戲,都是熱門標籤。令我最吃驚的居然是單機的標籤數量佔比居然這麼高,熱銷榜11。7%的遊戲居然有裸露標籤。
今天先更到這,後面改天再更