爬虫-爬取豆瓣短评
啥是爬虫?
按照一定的规则,自动地抓取互联网信息的程序。
为啥要用爬虫?
可以利用爬虫自动地采集互联网中的信息,采集回来后进行相应的存储或处理,在需要检索某些信息的时候,只需在采集回来的信息中进行检索
怎么用爬虫?
爬虫分为三个部分
1、解析网页
2、提取信息
3、保存信息
接下来将会用requests库来实现一个简单地爬虫
爬取豆瓣短评
首先我们需要安装requests
库
我们可以cmd指令进入python解释器,然后输入pip install requests
然后等待安装。
同样我们也可以打开pycharm在Terminal中输入相同的指令
安装比较慢的同学可以修改下载源也可以下载
链接:解决pip下载慢 提取码:9b7d
来解决
安装好了我们就可以来使用requests
库的功能了
首先我们访问豆瓣250选择自己感兴趣的电影这里我们选择了《肖申克的救赎》
打开全部短评
这样我们就得到了短评的链接我们先看第二页
https://movie.douban.com/subject/1292052/commentsstart=20&limit=20&sort=new_score&status=P
一、请求网页
拿到网址后我们就可以利用requests库的get方法来请求网页
url = "https://movie.douban.com/subject/1292052/comments?start=20&limit=20&sort=new_score&status=P"
response = requests.get(url)
print(response)
但是这样我们是访问不到的,因为站点知道了我们不是“正常人”。我们的应对方案就是尽可能的模拟浏览器的功能或行为。既然浏览器有请求头的发送,那么我们的程序自然也应该加上。这时候我们就要用到get中的请求头功能了。
headers = {'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 Edg/84.0.522.40'}
# user-Agent 可以自己设置也可以自己去网页network中查找
我们尝试再次访问
response = requests.get(url, headers=headers)
print(response, type(response))
----------------------
<Response [200]> <class 'requests.models.Response'>
请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 response.text
之时,Requests 会使用其推测的文本编码。你可以找出 Requests 使用了什么编码,并且能够使用 r.encoding 属性来改变它:如果你改变了编码,每当你访问 response.text
,Request 都将会使用 response.encoding
的新值。HTML 页面是可以设置编码信息的,可以查看该编码信息,然后设置 response.encoding
为相应的编码。这样就能使用正确的编码解析 response.text
了。而网页的编码可以在浏览器中去查看。
print(response.text) # 网页源码
print(response.encoding) # utf-8
我们得到了网页源码response.text那么我们就可以进行下一步我们先将第一步包装成函数
def getHtml(url):
response = requests.get(url, headers=headers)
htmldata = response.text
return htmldata
二、解析网页
我们得到了文本(text)模式的网页源码,那么我们就可以用正则表达式来解析它来提取我们要的数据
import re
模块在这里我们主要用四个内容
. | 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 . 。 | |
* | 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 *。 | |
? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 ?。 | |
( ) | 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。 |
简单来说.*?
就是匹配任意数量任意类型的字符()
就是问匹配到了吗?匹配到了就取出来…
在这里我们要选取的是短评在网页中他的一个代码格式是这样子的
<span class="short">关于希望最强有力的注释。</span>
这是其中一条评论,他在span
标签下两个> <
之间,注意我们要匹配的一定是唯一的,不然会匹配到别的内容
comment = re.findall('<span class="short">(.*?)</span>', htmldata) # findall查找全文
# 看网页源码我们看到评论都在这个格式里 所以findall能够全部匹配
同样我们也可以用正则得到名字
<h1>肖申克的救赎 短评</h1> # <h1>(.*?)</h1>
我们再用函数将第二步封装起来
# 提取信息 名字评论
def getComment(htmldata):
movies_name = re.findall('<h1>(.*?)</h1>', htmldata)
comment = re.findall('<span class="short">(.*?)</span>', htmldata)
return movies_name,comment
三、保存数据
这个比较简单了
def save():
with open(f"{str(movies_name)}.txt", "a", encoding="utf-8")as f:
f.write("%s\n" % str(comment))
当然你也可以保存成别的格式
总结:
简单地一个爬虫程序就编好了
再来回答一下为什么取第二页,我们来对比下其他页
https://movie.douban.com/subject/1292052/comments?start=0&limit=20&sort=new_score&status=P # 第一页
https://movie.douban.com/subject/1292052/comments?start=20&limit=20&sort=new_score&status=P # 第二页
https://movie.douban.com/subject/1292052/comments?start=40&limit=20&sort=new_score&status=P # 第三页
我们发现他只是 start 那里数据不一样 那我们可以通过修改 数值来爬取多页吗?
完整代码奉上
import requests
import re
# 获取网页源码
def getHtml(url):
response = requests.get(url, headers=headers)
htmldata = response.text
return htmldata
# 提取信息 名字评论
def getComment(htmldata):
movies_name = re.findall('<h1>(.*?)</h1>', htmldata)
comment = re.findall('<span class="short">(.*?)</span>', htmldata)
return movies_name, comment
# 保存文件
def save():
with open(f"{str(movies_name)}.txt", "a", encoding="utf-8")as f:
f.write("%s\n" % str(comment))
headers = {
'User-Agent1':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 Edg/84.0.522.40'
}
for i in range(0, 10):
movie_url = f"https://movie.douban.com/subject/1292052/comments?start={i * 20}&limit=20&sort=new_score&status=P"
htmldata = getHtml(movie_url)
movies_name, comment = getComment(htmldata)
save()
这样我们就得到了前十页的数据了