0


【机器学习】网络爬虫实战详解

【机器学习】网络爬虫详解


在这里插入图片描述

活动地址:CSDN21天学习挑战赛


作者简介:在校大学生一枚,华为云享专家,阿里云星级博主,腾云先锋(TDP)成员,云曦智划项目总负责人,全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC)志愿者,以及编程爱好者,期待和大家一起学习,一起进步~
.
博客主页:ぃ灵彧が的学习日志
.
本文专栏:机器学习
.
专栏寄语:若你决定灿烂,山无遮,海无拦
.
在这里插入图片描述

文章目录


前言

什么是网络爬虫?

编写程序从网络中自动获取数据的过程叫作数据爬取,也叫作网络爬虫。网络爬虫一般步骤为:获取爬取页的url,获取页面内容、解析页面、获取所需数据,重复上述过程至爬取结束。


一、明星图片爬取

明星图片爬取基于百度搜索的返回结果进行,在百度搜索“中国艺人”,解析返回页面展示的艺人图片链接并保持。


(一)、定义爬取指定url页面的函数

  1. 导入相关包:
  1. import requests
  2. import json
  3. import os

  1. 直接使用程序爬取网络数据会被网站识别出来,然后封禁该IP,导致数据爬取中断,所以我们需要首先将程序访问页面伪装成浏览器访问页面

User-Agent:定义一个真实浏览器的代理名称,表明自己的身份(是哪种浏览器),本demo为谷歌浏览器

Accept:告诉WEB服务器自己接受什么介质类型,*/* 表示任何类型

Referer:浏览器向WEB服务器表明自己是从哪个网页URL获得点击当前请求中的网址/URL

Connection:表示是否需要持久连接

Accept-Language:浏览器申明自己接收的语言

Accept-Encoding:浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate)


  1. defgetPicinfo(url):
  2. headers ={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36","Accept":"*/*","Referer":"https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E4%B8%AD%E5%9B%BD%E8%89%BA%E4%BA%BA&fenlei=256&rsv_pq=cf6f24c500067b9f&rsv_t=c2e724FZlGF9fJYeo9ZV1I0edbhV0Z04aYY%2Fn6U7qaUoH%2B0WbUiKdOr8JO4&rqlang=cn&rsv_dl=ib&rsv_enter=1&rsv_sug3=15&rsv_sug1=6&rsv_sug7=101","Host":"sp0.baidu.com","Connection":"keep-alive","Accept-Language":"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6","Accept-Encoding":"gzip, deflate"}# 根据url,使用get()方法获取页面内容,返回相应
  3. response = requests.get(url,headers)# 成功访问了页面if response.status_code ==200:return response.text
  4. # 没有成功访问页面,返回NonereturnNone

(二)、爬取图片

使用上述定义好的函数,进行指定url页面的爬取,然后解析返回的页面源码,获取其中的图片链接,并保存图片:

  1. #图片存放地址
  2. Download_dir='picture'if os.path.exists(Download_dir)==False:
  3. os.mkdir(Download_dir)
  4. pn_num=1# 爬取多少页
  5. rn_num=10# 每页多少个图片for k inrange(pn_num):# for循环,每次爬取一页
  6. url="https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?resource_id=28266&from_mid=1&&format=json&ie=utf-8&oe=utf-8&query=%E4%B8%AD%E5%9B%BD%E8%89%BA%E4%BA%BA&sort_key=&sort_type=1&stat0=&stat1=&stat2=&stat3=&pn="+str(k)+"&rn="+str(rn_num)+"&_=1613785351574"
  7. res = getPicinfo(url)# 调用函数,获取每一页内容
  8. json_str=json.loads(res)# 将获取的文本格式转化为字典格式
  9. figs=json_str['data'][0]['result']for i in figs:# for循环读取每一张图片的名字
  10. name=i['ename']
  11. img_url=i['pic_4n_78']# img_url:图片地址
  12. img_res=requests.get(img_url)# 读取图片所在页面内容if img_res.status_code==200:
  13. ext_str_splits=img_res.headers['Content-Type'].split('/')
  14. ext=ext_str_splits[-1]# 索引-1指向列表倒数第一个元素
  15. fname=name+"."+ext
  16. # 保存图片open(os.path.join(Download_dir,fname),'wb').write(img_res.content)print(name,img_url,"saved")

爬取内容部分如图1-1所示:

在这里插入图片描述


二、股票行情爬取与分析

首先爬取一个股票名称列表,再获取列表里每支股票的信息。


(一)、爬取股票列表信息

代码如下:

  1. #coding=utf-8'''
  2. Created on 20210220
  3. @author: zhongshan
  4. '''#http://quote.eastmoney.com/center/gridlist.html#爬取该页面股票信息import requests
  5. from fake_useragent import UserAgent
  6. from bs4 import BeautifulSoup
  7. import json
  8. import csv
  9. defgetHtml(url):
  10. r = requests.get(url,headers={'User-Agent': UserAgent().random,})
  11. r.encoding = r.apparent_encoding
  12. return r.text
  13. #num为爬取多少条记录,可手动设置
  14. num =20#该地址为页面实际获取数据的接口地址
  15. stockUrl='http://99.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112408733409809437476_1623137764048&pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&fid=f3&fs=m:0+t:80&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152&_=1623137764167:formatted'if __name__ =='__main__':
  16. responseText = getHtml(stockUrl)
  17. jsonText = responseText.split("(")[1].split(")")[0];
  18. resJson = json.loads(jsonText)
  19. datas = resJson["data"]["diff"]
  20. datalist =[]for data in datas:# if (str().startswith('6') or str(data["f12"]).startswith('3') or str(data["f12"]).startswith('0')):
  21. row =[data["f12"],data["f14"]]
  22. datalist.append(row)print(datalist)
  23. f =open('stock.csv','w+',encoding='utf-8',newline="")
  24. writer = csv.writer(f)
  25. writer.writerow(('代码','名称'))for data in datalist:
  26. writer.writerow((data[0]+"\t",data[1]+"\t"))
  27. f.close()

输出结果如图2-1所示:

在这里插入图片描述


(二)、股票数据获取

在获取股票代码及名称列表之后,逐个下载股票数据,根据观察,每支股票的历史数据由四部分组成:头url,上市地(深市,沪市)、股票代码、尾url,只需要组合好上述url,即可获得csv格式的数据,并下载,如下:

  1. import csv
  2. import urllib.request as r
  3. import threading
  4. #读取之前获取的个股csv丢入到一个列表中defgetStockList():
  5. stockList =[]
  6. f =open('stock.csv','r',encoding='utf-8')
  7. f.seek(0)
  8. reader = csv.reader(f)for item in reader:
  9. stockList.append(item)
  10. f.close()return stockList
  11. defdownloadFile(url,filepath):# print(filepath)try:
  12. r.urlretrieve(url,filepath)except Exception as e:print(e)print(filepath,"is downloaded")pass#设置信号量,控制线程并发数
  13. sem = threading.Semaphore(1)defdownloadFileSem(url,filepath):with sem:
  14. downloadFile(url,filepath)
  15. urlStart ='http://quotes.money.163.com/service/chddata.html?code='
  16. urlEnd ='&end=20210221&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;VOTURNOVER;VATURNOVER'if __name__ =='__main__':
  17. stockList = getStockList()
  18. stockList.pop(0)print(stockList)for s in stockList:
  19. scode =str(s[0].split("\t")[0])#0:沪市;1:深市
  20. url = urlStart +("0"if scode.startswith('6')else"1")+ scode + urlEnd
  21. print(url)
  22. filepath =(str(s[1].split("\t")[0])+"_"+scode)+".csv"
  23. threading.Thread(target=downloadFileSem,args=(url,filepath)).start()

下载文件部分列表如图2-2所示:

在这里插入图片描述


(三)、股票数据分析

现在,我们对股票数据做一些简单的分析,比如股票的最高价、最低价随时间的变化,股票的涨跌幅/涨跌额随时间的变化,以及当天的成交量与前一天的涨跌幅有何关系等。

上述分析可以使用作图的方式进行直观展示。

  1. 定义加载数据的功能函数:
  1. import pandas as pd
  2. import matplotlib.pyplot as plt
  3. import csv
  4. # 设置显示中文
  5. plt.rcParams['font.sans-serif']=['simhei']# 指定默认字体
  6. plt.rcParams['axes.unicode_minus']=False# 用来显示负号
  7. plt.rcParams['figure.dpi']=100# 每英寸点数
  8. files =[]# ['日期' '股票代码' '名称' '收盘价' '最高价' '最低价' '开盘价' '前收盘' '涨跌额' '涨跌幅' '成交量' '成交金额']defread_file(file_name):
  9. data = pd.read_csv(file_name,encoding='gbk')
  10. col_name = data.columns.values
  11. return data, col_name
  12. defget_files_path():
  13. stock_list=getStockList()
  14. paths =[]for stock in stock_list[1:]:
  15. p = stock[1].strip()+"_"+stock[0].strip()+".csv"print(p)
  16. data,_ = read_file(p)iflen(data)>1:
  17. files.append(p)print(p)
  18. get_files_path()print(files)
  1. 定义get_diff(file_name)函数,作该股票的涨跌幅/涨跌额随时间的变化图像,可以将该支股票的波动性观察一段时间。
  1. # 获取股票的涨跌额及涨跌幅度变化曲线# ['日期' '股票代码' '名称' '收盘价' '最高价' '最低价' '开盘价' '前收盘' '涨跌额' '涨跌幅' '成交量' '成交金额']defget_diff(file_name):
  2. data, col_name = read_file(file_name)
  3. index =len(data['日期'])-1
  4. sep = index//15
  5. plt.figure(figsize=(15,17))
  6. x = data['日期'].values.tolist()
  7. x.reverse()# x = x[-index:]
  8. xticks=list(range(0,len(x),sep))
  9. xlabels=[x[i]for i in xticks]
  10. xticks.append(len(x))# xlabels.append(x[-1])
  11. y1 =[float(c)if c!='None'else0for c in data['涨跌额'].values.tolist()]
  12. y2=[float(c)if c!='None'else0for c in data['涨跌幅'].values.tolist()]
  13. y1.reverse()
  14. y2.reverse()# y1 = y1[-index:]# y2 = y2[-index:]
  15. ax1 = plt.subplot(211)
  16. plt.plot(range(1,len(x)+1),y1,c='r')
  17. plt.title('{}-涨跌额/涨跌幅'.format(file_name.split('_')[0]),fontsize=20)
  18. ax1.set_xticks(xticks)
  19. ax1.set_xticklabels(xlabels, rotation=40)# plt.xlabel('日期')
  20. plt.ylabel('涨跌额',fontsize=20)
  21. ax2 = plt.subplot(212)
  22. plt.plot(range(1,len(x)+1),y2,c='g')# plt.title('{}-涨跌幅'.format(file_name.split('_')[0]))
  23. ax2.set_xticks(xticks)
  24. ax2.set_xticklabels(xlabels, rotation=40)
  25. plt.xlabel('日期',fontsize=20)
  26. plt.ylabel('涨跌幅',fontsize=20)
  27. plt.savefig('work/'+file_name.split('.')[0]+'_diff.png')
  28. plt.show()
  1. 定义get_max_min(file_name)函数,做该股票的每日最高价/最低价随时间的变化图像,也可以将该支股票的波动性或者是否增值观察一段时间。
  1. defget_max_min(file_name):
  2. data, col_name = read_file(file_name)
  3. index =len(data['日期'])-1
  4. sep = index//15
  5. plt.figure(figsize=(15,10))
  6. x = data['日期'].values.tolist()
  7. x.reverse()
  8. x = x[-index:]
  9. xticks=list(range(0,len(x),sep))
  10. xlabels=[x[i]for i in xticks]
  11. xticks.append(len(x))# xlabels.append(x[-1])
  12. y1 =[float(c)if c!='None'else0for c in data['最高价'].values.tolist()]
  13. y2=[float(c)if c!='None'else0for c in data['最低价'].values.tolist()]
  14. y1.reverse()
  15. y2.reverse()
  16. y1 = y1[-index:]
  17. y2 = y2[-index:]
  18. ax = plt.subplot(111)
  19. plt.plot(range(1,len(x)+1),y1,c='r',linestyle="-")
  20. plt.plot(range(1,len(x)+1),y2,c='g',linestyle="--")
  21. plt.title('{}-最高价/最低价'.format(file_name.split('_')[0]),fontsize=20)
  22. ax.set_xticks(xticks)
  23. ax.set_xticklabels(xlabels, rotation=40)
  24. plt.xlabel('日期',fontsize=20)
  25. plt.ylabel('价格',fontsize=20)
  26. plt.legend(['最高价','最低价'],fontsize=20)
  27. plt.savefig('work/'+file_name.split('.')[0]+'_minmax.png')
  28. plt.show()
  1. 定义get_deal(file_name)函数,作该股票的每日成交量/成交金额随时间变化的图像,可以观察一段时间内该支股票的成交量变化,以及是否存在大宗交易:
  1. defget_deal(file_name):
  2. data, col_name = read_file(file_name)
  3. index =len(data['日期'])-1
  4. sep = index//15
  5. plt.figure(figsize=(15,10))
  6. x = data['日期'].values.tolist()
  7. x.reverse()
  8. x = x[-index:]
  9. xticks=list(range(0,len(x),sep))
  10. xlabels=[x[i]for i in xticks]
  11. xticks.append(len(x))# xlabels.append(x[-1])
  12. y1 =[float(c)if c!='None'else0for c in data['成交量'].values.tolist()]
  13. y2=[float(c)if c!='None'else0for c in data['成交金额'].values.tolist()]
  14. y1.reverse()
  15. y2.reverse()
  16. y1 = y1[-index:]
  17. y2 = y2[-index:]
  18. ax = plt.subplot(111)
  19. plt.plot(range(1,len(x)+1),y1,c='b',linestyle="-")
  20. plt.plot(range(1,len(x)+1),y2,c='r',linestyle="--")
  21. plt.title('{}-成交量/成交金额'.format(file_name.split('_')[0]),fontsize=20)
  22. ax.set_xticks(xticks)
  23. ax.set_xticklabels(xlabels, rotation=40)
  24. plt.xlabel('日期',fontsize=20)# plt.ylabel('')
  25. plt.legend(['成交量','成交金额'],fontsize=20)
  26. plt.savefig('work/'+file_name.split('.')[0]+'_deal.png')
  27. plt.show()
  1. 定义get_rel(flie_name)函数,做该股票的成交量与前一天涨跌额的关系图像,直观地展示涨跌额对成交量的影响。
  1. defget_rel(file_name):
  2. data, col_name = read_file(file_name)
  3. index =len(data['日期'])-1
  4. sep = index//15
  5. plt.figure(figsize=(15,10))
  6. x = data['日期'].values.tolist()
  7. x.reverse()
  8. x = x[-index:]
  9. xticks=list(range(0,len(x),sep))
  10. xlabels=[x[i]for i in xticks]
  11. xticks.append(len(x))# xlabels.append(x[-1])
  12. y1 =[float(c)if c!='None'else0for c in data['成交量'].values.tolist()]
  13. y2=[float(c)if c!='None'else0for c in data['涨跌幅'].values.tolist()]
  14. y1.reverse()
  15. y2.reverse()
  16. y1 = y1[-index:]
  17. y2 = y2[-index:]
  18. y2 =[0]+ y2[:-1]
  19. ax = plt.subplot(111)
  20. plt.scatter(y2,y1)
  21. plt.title('{}-成交量与前一天涨跌幅的关系'.format(file_name.split('_')[0]),fontsize=20)# ax.set_xticks(xticks)# ax.set_xticklabels(xlabels, rotation=40)
  22. plt.xlabel('前一天涨跌幅',fontsize=20)
  23. plt.ylabel('成交量',fontsize=20)# plt.legend(['成交量','成交金额'],fontsize=20)
  24. plt.savefig('work/'+file_name.split('.')[0]+'_rel.png')
  25. plt.show()# for file in files:# get_diff(file)# for file in files:# get_max_min(file)print(len(files))
  1. 调用上述分析函数,为每支股票绘制相关的展示图:
  1. forfilein files:
  2. get_max_min(file)
  3. get_deal(file)
  4. get_diff(file)
  5. get_rel(file)

股票的涨跌额及涨跌幅度变化如下图2-3、2-4所示:

在这里插入图片描述

在这里插入图片描述

股票的最高价/最低价变化如图2-5所示:

在这里插入图片描述

股票成交量/成交金额变化如图2-6所示:

在这里插入图片描述

股票的涨跌额与次日成交量关系如下图2-7所示:

在这里插入图片描述


三、科比职业生涯数据爬取与分析

本实验从网址http://www.stat-nba.com获取科比的相关数据,主要包括:常规赛、季后赛、全明星赛三种赛事的数据。


(一)、科比职业生涯赛事数据爬取

  1. 导入相关包
  1. import requests
  2. from bs4 import BeautifulSoup
  3. import csv
  4. import matplotlib.pyplot as plt
  5. import pandas as pd
  1. 获取url页面内容,并以文本格式返回
  1. defgetKobeList(code):
  2. url ="http://www.stat-nba.com/player/stat_box/195_"+code+".html"
  3. response = requests.get(url)
  4. resKobe = response.text
  5. return resKobe
  1. 获取Kobe历史数据
  1. #获取kobe历史数据defgetRow(resKobe,code):
  2. soup = BeautifulSoup(resKobe,"html.parser")
  3. table = soup.find_all(id='stat_box_avg')#表头
  4. header =[]if code =="season":
  5. header =["赛季","出场","首发","时间","投篮","命中","出手","三分","命中","出手","罚球","命中","出手","篮板","前场","后场","助攻","抢断","盖帽","失误","犯规","得分","胜","负"]if code =="playoff":
  6. header =["赛季","出场","时间","投篮","命中","出手","三分","命中","出手","罚球","命中","出手","篮板","前场","后场","助攻","抢断","盖帽","失误","犯规","得分","胜","负"]if code =="allstar":
  7. header =["赛季","首发","时间","投篮","命中","出手","三分","命中","出手","罚球","命中","出手","篮板","前场","后场","助攻","抢断","盖帽","失误","犯规","得分"]#数据
  8. rows =[];
  9. rows.append(header)for tr in table[0].find_all("tr",class_="sort"):
  10. row =[]for td in tr.find_all("td"):
  11. rank = td.get("rank")if rank !="LAL"and rank !=None:
  12. row.append(td.get_text())
  13. rows.append(row)return rows
  14. #写入csv文件,rows为数据,dir为写入文件路径defwriteCsv(rows,dir):withopen(dir,'w', encoding='utf-8-sig', newline='')as f:
  15. writer = csv.writer(f)
  16. writer.writerows(rows)#常规赛数据
  17. resKobe = getKobeList("season")
  18. rows = getRow(resKobe,"season")#print(rows)
  19. writeCsv(rows,"season.csv")print("season.csv saved")#季后赛数据
  20. resKobe = getKobeList("playoff")
  21. rows = getRow(resKobe,"playoff")#print(rows)
  22. writeCsv(rows,"playoff.csv")print("playoff.csv saved")#全明星数据
  23. resKobe = getKobeList("allstar")
  24. rows = getRow(resKobe,"allstar")#print(rows)
  25. writeCsv(rows,"star.csv")print("star.csv saved")

(二)、科比职业生涯数据分析

针对不同赛事以及不同时间,绘制科比的职业生涯得分情况,比如,绘制各个赛季科比的篮板数、助攻、得分情况分布,可以在一定程度上反映其在各个赛季的贡献程度。首先定义展示函数show_score(),传入不同赛事的名称,要展示的项,以及绘制线型等:

  1. # 篮板、助攻、得分defshow_score(game_name='season', item='篮板', plot_name='line'):# game_name: season, playoff, star# item: 篮板,助攻,得分# plot_name: line,bar
  2. file_name = game_name+'.csv'
  3. data = pd.read_csv(file_name)
  4. X= data['赛季'].values.tolist()
  5. X.reverse()if item=='all':
  6. Y1 = data['篮板'].values.tolist()
  7. Y2 = data['助攻'].values.tolist()
  8. Y3 = data['得分'].values.tolist()
  9. Y1.reverse()
  10. Y2.reverse()
  11. Y3.reverse()else:
  12. Y = data[item].values.tolist()
  13. Y.reverse()if plot_name=='line':if item=='all':
  14. plt.plot(X,Y1,c='r',linestyle="-.")
  15. plt.plot(X,Y2,c='g',linestyle="--")
  16. plt.plot(X,Y3,c='b',linestyle="-")
  17. legend=['篮板','助攻','得分']else:
  18. plt.plot(X,Y,c='g',linestyle="-")
  19. legend=[item]elif plot_name=='bar':#facecolor:表面的颜色;edgecolor:边框的颜色if item=='all':
  20. fig = plt.figure(figsize=(15,5))
  21. ax1 = plt.subplot(131)
  22. plt.bar(X,Y1,facecolor ='#9999ff',edgecolor ='white')
  23. plt.legend(['篮板'])
  24. plt.title('Kobe职业生涯数据分析:'+game_name)
  25. plt.xticks(rotation=60)
  26. plt.ylabel('篮板')
  27. ax2 = plt.subplot(132)
  28. plt.bar(X,Y2,facecolor ='#999900',edgecolor ='white')
  29. plt.legend(['助攻'])
  30. plt.title('Kobe职业生涯数据分析:'+game_name)
  31. plt.xticks(rotation=60)
  32. plt.ylabel('助攻')
  33. ax3 = plt.subplot(133)
  34. plt.bar(X,Y3,facecolor ='#9988ff',edgecolor ='white')
  35. legend=['得分']else:
  36. plt.bar(X,Y,facecolor ='#9900ff',edgecolor ='white')
  37. legend=[item]else:return
  38. plt.legend(legend)
  39. plt.title('Kobe职业生涯数据分析:'+game_name)
  40. plt.xticks(rotation=60)
  41. plt.xlabel('赛季')if item!='all':
  42. plt.ylabel(item)else:
  43. plt.ylabel('得分')
  44. plt.savefig('work/Kobe职业生涯数据分析_{}_{}.png'.format(game_name,item))
  45. plt.show()# 篮板、助攻、得分
  46. game_name ='season'for game_name in['season','playoff','star']:
  47. show_score(game_name=game_name, item='篮板', plot_name='bar')
  48. show_score(game_name=game_name, item='助攻', plot_name='bar')
  49. show_score(game_name=game_name, item='得分', plot_name='bar')
  50. show_score(game_name=game_name, item='篮板', plot_name='line')
  51. show_score(game_name=game_name, item='助攻', plot_name='line')
  52. show_score(game_name=game_name, item='得分', plot_name='line')
  53. show_score(game_name=game_name, item='all', plot_name='bar')
  54. show_score(game_name=game_name, item='all', plot_name='line')

根据上面定义的绘图函数,绘制Kobe在各种赛事中的相关数据,如下图3-1、3-2、3-3所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

输出部分结果如图3-4至3-8所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


总结

本系列文章内容为根据清华社初版的《机器学习实践》所作的相关笔记和感悟,其中代码均为基于百度飞浆开发,若有任何侵权和不妥之处,请私信于我,定积极配合处理,看到必回!!!

最后,引用本次活动的一句话,来作为文章的结语~( ̄▽ ̄~)~:

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。

在这里插入图片描述


本文转载自: https://blog.csdn.net/m0_54754302/article/details/126229168
版权归原作者 云曦智划 所有, 如有侵权,请联系我们删除。

“【机器学习】网络爬虫实战详解”的评论:

还没有评论