【Python学习】网络爬虫-爬取豆瓣电影评论
一、实现目标
编写一个爬虫,获取豆瓣网站上“庆余年 第二季”这部电视剧的短评,网站如下:
# https://movie.douban.com/subject/34937650/comments?sort=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> 标签中,查找span标签在网页中出现了100多次,而显然,该页只有二十条评论。也可以试试以 <p> 节点来定位,网页中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 + "\n")
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 + "\n")
print(f"第{page}页保存完毕")
执行结果如下
三、总结
本实例实现了庆余年的豆瓣电影评论爬取,使用了requests、bs4模块。
requests:是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。requests 模块比 urllib 模块更简洁。
bs4:全名 BeautifulSoup,是编写 python 爬虫常用库之一,主要用来解析 html 标签。
更多推荐
所有评论(0)