使用python,爬取网页评论

系统 187 0

使用python,爬取网页评论(实例:豆瓣《都挺好》)

python的第三方库丰富了python的功能,今天就用python的第三方库requests和bs4这两个库来实现对一个网页的爬取

操作环境

python3.7.2
requests库
bs4库

requests库和bs4库下载

如果你的电脑只用python3的版本使用以下方式下载:

pip install requests
pip install bs4

如果你的电脑中python3和python2的版本都存在:

python3 -m pip install
python2 -m pip install

这一步是最基本的,如果没有安装成功请先自行百度解决。

目标网站:

https://book.douban.com/subject/20492971/comments/hot

先查看网络源代码,观察网页源代码的结构和我们要爬取的内容,这次我们要爬取的是用户名、用户评论、有用数,评论的星数和日期。
通过观察我们发现我们所需的内容主要出现在这一部分:

            
              
                
                  Sofia
                
                
                
                
                  2013-06-30
                
              
              

《都挺好》=《回家》。强势母亲带来的家庭矛盾: 懦弱的儿子+强势的女儿。 纵容的宠爱是一种慢性毒药,慢慢侵蚀人的奋斗、拼搏精神和生存能力。 “穷养”的女儿被逼着成长,凌厉干练, 却失去了爱的能力——无论是爱人还是爱己。父母之爱要的就是一个平衡的点。

所以下一步就是如何将其爬取出来

爬取过程

将目标网页的所有内容爬取下来,再进行下一步的筛选

            
              def getHTMLText(url):
    try:
        r = requests.get(url,timeout=30)
        r.raise_for_status()
        r.enconding = "utf-8"
        return r.text
    except:
        return ""

            
          

现在我们要观察我们要爬去的内容具体在什么位置
soup.find_all()函数可以实现筛选的目的;
我们可以看到我们要的主要内容都在标签span class="comment-info“
使用soup.find_all(“span”, ‘comment-info’)来筛选:

            
              def fillBookdata(Bookdata,html):
    soup = BeautifulSoup(html, 'html.parser')
    commmentinfo = soup.find_all("span", 'comment-info') 
    pattern = re.compile('user-stars allstar(\d+) rating')
    p = re.findall(pattern, str(commmentinfo))
    comments = soup.find_all('span', 'short')
    for i in range(len(commmentinfo)):
        Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])

            
          

这里使用了正则表达式需要使用re库
正则表达式的使用可以参考别的文章,在此不做介绍。
现在写一个输出函数来显示我们的爬取结果

            
              def printList(Bookdata,num):
    for i in range(num):
        u = Bookdata[i]
        print("序号:{}\n用户名:{}\n评论内容:{}\n评分:{}星\n".format(i + 1,u[0], u[1],int(int(u[2])/10)))

            
          

运行结果如下:
使用python,爬取网页评论_第1张图片
使用python,爬取网页评论_第2张图片
与我们的爬取结果最比较可以发现我们目前爬取的内容都是正确的。
但这个只是第一页的内容如果我们要连续的爬取呢?
通过观察我们可以发现连续的网页存在一定的规律:
这是第一页https://book.douban.com/subject/20492971/comments/hot
这是第二页https://book.douban.com/subject/20492971/comments/hot?p=2
这是第三页https://book.douban.com/subject/20492971/comments/hot?p=3
由此我们可以改变输出函数即可:

            
              for i in range(3):
    print('第',i+1,'页')
    main('https://book.douban.com/subject/20492971/comments/hot?p='+str(i+1))

            
          

在运行一下:
使用python,爬取网页评论_第3张图片
第二页出错了!!!为什么呢?
具体错误:

            
              Traceback (most recent call last):
  File "E:\pythonwork\4-3-1.py", line 62, in 
              
                
    main('https://book.douban.com/subject/20492971/comments/hot?p='+str(i+1))
  File "E:\pythonwork\4-3-1.py", line 53, in main
    fillBookdata(uinfo1,html)
  File "E:\pythonwork\4-3-1.py", line 38, in fillBookdata
    Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
IndexError: list index out of range

              
            
          

再百度完错误后,我们查看一下第二页的源代码,我们可以发现不是所用的用户都给了星数:
使用python,爬取网页评论_第4张图片
下面的用户就没有给出评价,所以储存星数的列表的内容并没有达到20个,也就是后面的星数为空,所以弹出来错误;这个问题目前我还没有很好的解决方式,希望各位小主献计献策。
以下是我的不完美的解决方式:

            
              def fillBookdata(Bookdata,html):
    soup = BeautifulSoup(html, 'html.parser')
    commmentinfo = soup.find_all("span", 'comment-info')
    
    pattern = re.compile('user-stars allstar(\d+) rating')
    p = re.findall(pattern, str(commmentinfo))
    comments = soup.find_all('span', 'short')
    for i in range(len(commmentinfo)):
        #设置异常处理机制,发现空值的情况人为的给其加一个值0
        try:
            Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
        except IndexError:
            #添加一个0值
            Bookdata.append([commmentinfo[i].a.string, comments[i].string, '0'])
            #pass

            
          

但这样的添加方式不好,不能正确的匹配到了没有给星数的用户。如果有更完美的方式我会在后续的文章中发布。
附上现在的代码:

            
              import requests
from bs4 import BeautifulSoup
import bs4
import re

def getHTMLText(url):
    try:
        r = requests.get(url,timeout=30)
        r.raise_for_status()
        r.enconding = "utf-8"
        return r.text
    except:
        return ""


def fillBookdata(Bookdata,html):
    soup = BeautifulSoup(html, 'html.parser')
    commmentinfo = soup.find_all("span", 'comment-info')
    
    pattern = re.compile('user-stars allstar(\d+) rating')
    p = re.findall(pattern, str(commmentinfo))
    comments = soup.find_all('span', 'short')
    for i in range(len(commmentinfo)):
        #设置异常处理机制,发现空值的情况人为的给其加一个值0
        try:
            Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
        except IndexError:
            #添加一个0值
            Bookdata.append([commmentinfo[i].a.string, comments[i].string, '0'])
            #pass
'''

def fillBookdata(Bookdata,html):
    soup = BeautifulSoup(html, 'html.parser')
    commmentinfo = soup.find_all("span", 'comment-info') 
    pattern = re.compile('user-stars allstar(\d+) rating')
    p = re.findall(pattern, str(commmentinfo))
    comments = soup.find_all('span', 'short')
    for i in range(len(commmentinfo)):
        Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
'''        

def printList(Bookdata,num):
    for i in range(num):
        u = Bookdata[i]
        print("序号:{}\n用户名:{}\n评论内容:{}\n评分:{}星\n".format(i + 1,u[0], u[1],int(int(u[2])/10)))


def main(url):
    uinfo1 = []
    '''
    url = 'https://book.douban.com/subject/20492971/comments/hot'
    '''
    html = getHTMLText(url)
    fillBookdata(uinfo1,html)
    printList(uinfo1,20)
'''   
main('https://book.douban.com/subject/20492971/comments/hot')


'''
for i in range(3):
    print('第',i+1,'页')
    main('https://book.douban.com/subject/20492971/comments/hot?p='+str(i+1))

            
          

当然我们还有发布时间和有用数未实现,这两个都可以通过使用正则表达式来实现(有机会各位小主可以认真学习一下正则表达式)

            
              pattern1=re.compile('>(\d+)<')
#匹配时间的正则表达式
pattern2 = re.compile('>(\d{4}-\d{1,2}-\d{1,2})<')

            
          

修改一下输出函数即可实现一下的效果:
使用python,爬取网页评论_第5张图片
如有不足,还望见谅。希望各位小主给出更好的建议。


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请请扫描上面二维码支持博主1元、2元、5元等您想捐的金额吧,狠狠点击下面给点支持吧

发表我的评论
最新评论 总共0条评论