最近在学python网络爬虫,想爬一些网站练练手,正好楼主是湖人球迷,又是虎扑的忠实用户,于是就想到可以爬取湖区的当天的前几页评论,制作一个词云来分析一下湖区当天的热点话题。
爬虫采取的技术路线是request库+BeautifulSoup库。
我查看了虎扑网页源代码:<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
发现虎扑的网页是采用utf-8的编码方式,而且虎扑的评论是静态内嵌在网页源码中的,并不是利用js动态生成的,于是楼主决定采用request+BeautifulSoup库来爬取虎扑的评论,首先安装BeautifulSoup库,用管理员权限打开cmd,输入pip install BeautifulSoup
,安装完环境后就可以开始动手了。
1观察理解虎扑的网页结构
首先,我们先观察虎扑湖人区首页的网页代码,因为我们打算挨个爬取湖人区前三页的帖子,所以我们首先得获取每个帖子的url链接,不难发现虎扑的帖子的url链接都是由如下形式组成的https://bbs.hupu.com/24517474.html
,由一个公共的开头https://bbs.hupu.com/
加上一个8位数字组成的帖子地址可以确定一个帖子的url链接。
其次,我们需要选出湖区帖子的url,但一个网页除了帖子的链接还有其他的链接,我们需要把他们区分开,不难发现,每个虎扑帖子的8位数字地址都在如下的<a/>
标签内
<a href="/24514408.html" class="truetit" target="_blank">[流言板]詹姆斯:波普最后有很好的出手机会,要接受结果</a>
但与其他链接不同的是,它class的属性为"truetit",利用这一点我们可以用BeautifulSoup函数爬取帖子的链接地址。
2动手爬取帖子的标签号
先定义一个函数getHTMLText获取网页的源代码:
import requests
import re
from bs4 import BeautifulSoup
# import time
def getHTMLText(url, code = "utf-8"):
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = code
return r.text
except:
return""
利用request库获取网页的源代码,由于我们已经知道了网站的编码方式为’utf-8’,所以就不用request库中的apparent_coding函数,这样可以节约运行时间。当我们获得了网页源代码之后,就可以用BeautifulSoup库来检索网页中的内容
我们定义函数getNoteList:
def getNoteList(lst, NotelstUrl):
# 找到帖子的标签号
# 虎扑的帖子的格式是https://bbs.hupu.com/\d{8}.html
html = getHTMLText(NotelstUrl)
soup = BeautifulSoup(html,'html.parser')
a = soup.find_all('a', class_="truetit")
for i in a:
try:
href = i.attrs['href']
lst.append(re.findall(r"\d{8}", href)[0])
except:
continue
虎扑帖子的标签号为8位数字组成,我们可以利用正则表达式匹配链接中的8位数字。找到网页中所有的帖子的标签号,虎扑湖区每一页大概有60个左右的帖子,我们将其保存到lst数组中去。
3 爬取每个帖子里的帖子内容以及JRs的评论
通过观察网页源代码,楼主发现帖子中的评论内容是存放在<table>
标签的子标签<td>
中的字符串:
<table class="case" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
球哥防守速度比较快善于突破的小个后卫还是有点吃亏的,毕竟自己属于高个控卫
<br />
</td>
</tr>
</tbody>
</table>
如上所示,评论存放在class属性为"case"的<table>
标签中,但这只是其中最为普通的一种情形,在爬取过程中我发现了<td>
标签中会有一些其他的多余信息,这导致了爬取的评论中有很多与评论无关的信息。
<table class="case" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<blockquote><p><b>引用 @<a class="u" target="_blank" href="https://my.hupu.com/150298188533347" >jkuioy</a> 发表的</b>:<br>奥古斯丁上一次好像也是这么一波打晕湖人的....不懂是沃顿没针对还是针对没效果....</p></blockquote><br>上一次沃顿一开始给投不给突,遇掩护全部绕后,结果富尼耶,奥古斯丁噼里啪啦一通投,沃顿一看不行了,换策略贴投手,结果一碰掩护一突一个准,内线完全被打爆。这次完全是自己作,其实魔术今天并不准,坚持防守策略完全可以赌他们投不开。
<br /><small class="f999"><a style="color:#999" href="https://mobile.hupu.com/?_r=bbsvia9" target="_blank">发自虎扑Android客户端</a></small>
<br />
</td>
</tr>
</tbody>
</table>
如上述标签中<td>
标签的子标签<br>
有一些与评论无关的信息,如发自虎扑Android客户端,此时就需要我们对网页的源代码做预处理,删除其中无关信息。即利用BeautifulSoup库中的extract()函数,将我们不需要的标签统统删除。
于是,我们定义getNoteComments函数,爬取并将评论存放到txt文件中:
def getNoteComments(Notelst, NoteUrl, fpath):
# Notelst保存了每个帖子的具体的url地址
# NoteUrl是所有帖子的url链接的公共开头
count = 0
pages =['1','2','3','4','5','6','7','8','9']
for Notelink in Notelst:
for page in pages:
url = NoteUrl +Notelink+'-'+page+'.html'
html = getHTMLText(url)
try:
if html== "":
continue
soup = BeautifulSoup(html,'html.parser')
[s.extract() for s in soup('br')]
[s.extract() for s in soup('blockquote')]
[s.extract() for s in soup('small')]
[s.extract() for s in soup('div', class_="subhead")]
# 删除来自类似于手机客户端的无效信息
# 删除引用别人评论的重复评论
# 删除标题中的引用信息
# 删除修改评论等额外不需要的信息
table = soup.find_all('table', class_='case')
lst =[]
for i in table:
try:
text = i.find('td').text
lst.append(text)
except:
continue
with open(fpath,'a',encoding='utf-8') as f:
for i in lst:
f.write(str(i)+'\n')
# time.sleep(5)
except:
continue
我们主要是爬取每个帖子前9页的相关评论,虎扑网页每一页帖子的网址是
https://bbs.hupu.com/24517474-i.html
其中i代表着帖子的第几页,用getHTMLText得到源代码之后,我们用extract函数删除不需要的信息。
最后将爬取得到的评论写入txt中。
最后,主函数如下:
def main():
Page =['1','2','3']
# 爬取前三页的当天有关的热帖
Notelist=[]
# Notelist 保存虎扑湖人区每个帖子的url链接
for i in Page:
try:
print("正在爬取{}页的帖子".format(i))
Noteurl ='https://bbs.hupu.com/lakers-'+i
# 爬取虎扑湖人区前9页的帖子的url链接
getNoteList(Notelist, Noteurl)
getNoteComments(Notelist, "https://bbs.hupu.com/", 'D:/NoteComments11-23.txt')
except:
continue
最后爬取的评论效果如下