静态页面的爬取十分简单,直接浏览器在页面上右键,选择“查看源代码”,然后利用相关的库和正则表达式就能把想要的内容直接爬取。
下面展示个我拿来解决问题的实例。
背景
游戏王线上战队联盟有很多战队,HX是其中比较出名的一个队伍。HX战队每天都会和其他战队进行友谊赛,每一场都会有3个以上的队员出战。
每到月底,HX都会统计每个队员的个人胜率。这也是令每个统计员头疼的地方,因为每个月都有两三百场友谊赛,每场都有3个以上的人。甚至有时候。。
好在我们的战报都会上传到YGO论坛里面,可以直接爬取。
实现思路
首先打开论坛,搜索自己战队的战报,会得到一连串的结果。查看无误。
然后右键查看网页源代码。发现这是个很简单的静态页面,所有的战报内容全部显示在代码里。还好这部分的HTML写得还不算复杂,很快就能定位到其中的标签。接下来就是常规的用正则表达式提取了。
但很明显的,战报不只是在一个页面里,那如何实现翻页呢。一般是观察url的规律,然后通过循环来实现翻页。下面就是url,虽然不知道它全部的意思,但还是能知道“groupname=”后面是战队名称,“page=”后面的数字代表页数。
代码部分
思路已经有了,接下来就是用实现实现了。
import requests
import re
import pandas as pd
win=[]#记录赢的
lose=[]#记录输的
novel=open('%s.txt'%'战报','w',encoding='utf-8')
yeshu=11
for t in range(1,yeshu):
url="https://rep.ygobbs.com/index.php?c=search&groupname=%s"%"HX"+"&a=sub&page=%s"%t
res = requests.get(url)
res.encoding = res.apparent_encoding
html = res.text #这样html就是代码文本了
#利用正则表达式提取需要的部分
dl = re.findall(r'<div class="panel-body">(.*?)</div>', html, re.S)
for zhanbao in dl:
novel.write(zhanbao)
novel.write('\n')
#下面是清洗数据
zhanbao = zhanbao.replace('<br>', '')
zhanbao = zhanbao.lower() # 变小写,容易搞
all = zhanbao.split() # 以空格分隔
以上已经把战报提取出来,并一一以空格作为分隔符将元素分开并保存进列表里。然后是统计胜率。所作工作是把所有人的胜场和败场都算出来,然后以csv文件输出。
right = 0 # 判断hx是否在右边,默认不是
flag=1
i=0
while(flag):
if (all[i]=='vs' ): # 通过判断vs后面的元素,判断hx的位置
if(all[i+1]=='hx'):
flag=0
right=1
else:
flag=0
i=i+1
while i < len(all):
name = all[i]
if (name[0] != ':' and name[0] != '1' and name[0] != '2' and name[0] != '0'): # 把所有非人情况排除,就能保证判断的是人
if (right):
point = all[i - 1] # 对于hx队员在右边的情况,上一个就是他的比分了,非hx成员的上一个会是id
if (point[-1] == '2'): # 是2就代表赢了
win.append(name)
elif (point[-1] == '0' or point[-1] == '1'):
lose.append(name)
else:
if (i == len(all) - 1):
break
point = all[i + 1] # 对于hx队员在左边的情况,下一个就是他的比分了,非hx成员的下一个会是对面的id
if (point[0] == '2'): # 是2就代表赢了
win.append(name)
elif (point[0] == '0' or point[0] == '1'):
lose.append(name)
i = i + 1
print("finish") # 完成一次,输出
print(len(win))
print(len(lose))
wins={}
for key in win:
wins[key]=wins.get(key,0)+1
loses={}
for key in lose:
loses[key]=loses.get(key,0)+1
print("下面是合并的")
winwin = pd.Series(wins)
loselose= pd.Series(loses)
states_df = pd.DataFrame({'胜场':winwin,'败场':loselose})
states_df=states_df.fillna(value=0)#用0填补空值
print(states_df)
states_df.to_csv('胜率统计.csv', sep=',', header=True, index=True, encoding="utf_8_sig")
后面统计的部分写得有些粗糙,就不详细说了。后续可能还会优化。如果有大佬能针对这部分给点意见就更好了。
附吐槽:本来队里战报都是发在QQ群空间的,爬的是动态页面的数据。但后来群空间关了,被迫无奈只能爬论坛的静态页面2333。