【Python学习】网络爬虫-爬取豆瓣电影评论

一、实现目标

编写一个爬虫,获取豆瓣网站上"庆余年 第二季"这部电视剧的短评,网站如下:

https://movie.douban.com/subject/34937650/commentssort=new_score\&status=P

二、实现步骤

我们在Google Chrome浏览器中复制粘贴下面的链接,先看看网页内容,打开网页后可以看到,《庆余年 第二季》这部电视剧的相关短评,就在标注的红色方框内。这就是我们今天要获取的内容。

想要获取网页中的短评,首先要获取网页 HTML 代码,再把短评从中提取出来。

2.1 获取网页源码

获取网页中的 HTML 代码,我们可以使用 requests模块的 get 方法来实现。

复制代码
# 使用import导入requests模块
import requests

# 将豆瓣电影评论URL地址,赋值给变量url
url = "https://movie.douban.com/subject/34937650/comments?sort=new_score&status=P"

# 使用requests发起GET请求,赋值给response
response = requests.get(url)

# 使用print输出response.status_code
print(response)

这里执行后返回的状态码是418,这意味我们的爬虫被服务端发现了,因为我们用的是 requests 发起的请求,而不是浏览器。

我们需要加上User-Agent参数,伪装成一个浏览器。User-Agent参数值的获取方法也很简单,在chome浏览器中右键检查,在网络功能中可以看到客户端访问服务的请求,在请求头中包括本机的User-Agent参数,直接拿来用即可,如下图。

将User-Agent参数的值以字典的形式的存储在headers参数中,然后在请求时带上headers参数。

复制代码
# 使用import导入requests模块
import requests

# 将豆瓣电影评论URL地址,赋值给变量url
url = "https://movie.douban.com/subject/34937650/comments?sort=new_score&status=P"
# 将User-Agent以字典键对形式赋值给headers
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"}

# 使用requests发起GET请求,赋值给response
response = requests.get(url, headers=headers)

# 使用print输出response.status_code
print(response)

然后响应状态码就变成了 200 ,这说明我们请求成功了。

那么得到的网页内容在那能看到呢?网页的内容我们可以使用.text属性可以获取。但这个内容很长,不好分析,我们可以用切片的方法,先输出前1000个字符。

2.2 解析源码获取数据

上一步获取到网页 HTML 代码。接下来,就需要解析网页,从网页中提取想要的数据。解析网页我们使用 BeautifulSoup解析,这里就不需要做切片了,我们要解析整个网页内容。我们先导入 BeautifulSoup,并创建一个 BeautifulSoup 对象:

复制代码
# 从bs4中导入BeautifulSoup
from bs4 import BeautifulSoup

# 使用BeautifulSoup()传入变量html和解析器lxml,赋值给soup
soup = BeautifulSoup(html, "lxml")

# 使用print输出soup
print(soup)

接下来就要需要从 soup 中提取出短评所在的标签节点,我们可以使用 BeautifulSoup 中的find_all()函数,它可以查询所有符合条件的元素,并组成一个列表。

在这里,find_all() 函数中传入的参数内容是什么呢?我们需要去网页中找到短评所在的节点。定位方法如下图:

仔细观察发现,所有的评论都在标签中,查找span标签在网页中出现了100多次,而显然,该页只有二十条评论。也可以试试以

节点来定位,网页中p标签出现的次数也大于20。那么我们该定位哪个节点,才能提取评论呢?

多对照几条评论我们发现,短评所在的节点都是类似的它们都有一样的标签和属性,如下图所示。

在 HTML 中,span 标签的作用是用来组合文档中的行内元素。class 属性的作用是用来给标签分类。class="short"也就代表着,这里标签的内容是短评。

在网页中属性需要使用(点).属性值来定位。例如,图中我们在检索框中输入.short进行搜索,就能看到该页中class="short"属性出现的次数为20次,这些就是我们想要的内容。

那么,就定位到了提取评论的节点class="short"。以属性为查询条件就需要在 find_all() 中,传入 class="short"。由于 class 在 Python 里是一个关键字,所以后面需要加一个下划线,即class_="short"。

复制代码
# 使用find_all()查询soup中class="short"的节点,赋值给content_all
content_all = soup.find_all(class_="short")

如下图,我们获得了一个带标签的短语列表。

标签对我们来说没有用,我们需要去掉它,拿到标签里的内容, 访问.string获取每个节点中标签的内容。由于 find_all() 返回的是一个列表,我们不能直接访问 .string 属性。需要使用for 循环遍历列表 content_all。

复制代码
for content in content_all:
    # 使用.string获取标签里的内容
    contentString = content.string
     
    # 使用print打印评论    
    print(contentString)

如下图,我们就获得了第一页的20条评论

2.3 保存评论

为保存评论,我们在前面定义一个 comments 列表,用于临时存储评论内容,在最后使用with open() 将 comments 列表的中的评论写入本地的.txt文件中。

复制代码
# 定义一个列表,保存评论
comments = []

......

    # 保存评论到新的列表中
    comments.append(contentString)


# 保存评论到txt文件中
with open("D:/学习资料/Python/VSCode/yequbiancheng/网络爬虫/豆瓣评论_庆余庆.txt", "a", encoding='utf-8') as fp:
    # 将评论逐个写入txt文件中
    for comment in comments:
        fp.write(comment + "
")
print("保存完毕")

结果如下图

2.4 优化代码获取更多评论

现在我们获得了第一页的20条评论,可我们需要获得更多评论。我们点击后页,把每一页的URL地址拿出来对比一下。

通过对比第一页的URL,我们发现除了第一页,其它都有两个共同的参数start和limit,很明显start表示的该页第一条评论的编号,limit是该页的评论条数。

我们对URL进行一下改造,将limit设置为100,表示获取100条,使用 for 循环连续获取 5 页的评论。

复制代码
for page in range(5):
    # 将豆瓣电影评论URL地址,赋值给变量url
    url = f"https://movie.douban.com/subject/34937650/comments?start={page*100}&limit=100&status=P&sort=new_score"

完整的代码如下:

复制代码
# 使用import导入requests模块
import requests
# 从bs4中导入BeautifulSoup
from bs4 import BeautifulSoup


# 使用for循环,获取前10页的评论
for page in range(5):

    # 定义一个列表,保存评论
    comments = []
    # 将豆瓣电影评论URL地址,赋值给变量url
    url = f"https://movie.douban.com/subject/34937650/comments?start={page*100}&limit=100&status=P&sort=new_score"
    # 将User-Agent以字典键对形式赋值给headers
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"}

    # 使用requests发起GET请求,赋值给response
    response = requests.get(url, headers=headers)

    # 使用.text属性获取网页的内容,并赋值给html
    html = response.text

    # 使用BeautifulSoup()传入变量html和解析器lxml,赋值给soup
    soup = BeautifulSoup(html, "lxml")

    # 使用find_all()查询soup中class="short"的节点,赋值给content_all
    content_all = soup.find_all(class_="short")

    for content in content_all:
        # 使用.string获取标签里的内容
        contentString = content.string
        
        # 保存评论到新的列表中
        comments.append(contentString)

    # 保存评论到txt文件中
    with open("D:/学习资料/Python/VSCode/yequbiancheng/网络爬虫/豆瓣评论_庆余庆.txt", "a", encoding='utf-8') as fp:
        # 将评论逐个写入txt文件中
        for comment in comments:
            # 写入评论并回车
            fp.write(comment + "
")
    print(f"第{page}页保存完毕")

执行结果如下

三、总结

本实例实现了庆余年的豆瓣电影评论爬取,使用了requests、bs4模块。

requests :是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。requests 模块比urllib模块更简洁。

bs4 :全名BeautifulSoup,是编写 python 爬虫常用库之一,主要用来解析 html 标签。

相关推荐
默子昂4 分钟前
ollama 自定义ui
开发语言·python·ui
abcy0712134 分钟前
Python中使用FastAPI和HDFS进行异步文件上传
python·fastapi
abcy0712136 分钟前
flask hdfs 异步上传图文教程csdn
python·flask
袁小皮皮不皮15 分钟前
1.HCIP BFD 学习笔记(优化版)
服务器·网络·笔记·网络协议·学习·智能路由器·ip
在放️25 分钟前
Python 爬虫 · PyQuery 模块基础
爬虫·python
装不满的克莱因瓶40 分钟前
【自动驾驶领域】学习 Cityscapes 数据集——城市街景语义理解的标准基准
人工智能·pytorch·python·深度学习·学习·机器学习·自动驾驶
吴卫斌1 小时前
波动率控制仓位系列(一):满仓轮动的“过山车”困境
大数据·python·股票·量化交易
如此这般英俊1 小时前
手搓Claude Code-第三章 permission
人工智能·python·语言模型
TE-茶叶蛋1 小时前
TF-IDF 与 BM25 深度解析:从理论到项目实战
python·django·tf-idf
xcbrand1 小时前
湖南VI设计公司排名
大数据·人工智能·python