近几年来,每逢春节,在贺岁片中,总有一匹黑马杀出,还记得去年杀出的黑马是《红海行动》,而今年,让我们眼前一亮的贺岁片便是《流浪地球》,也使得今年被称为“中国科幻电影元年”。
自大年初一上映以来,《流浪地球》口碑爆棚,排片和票房都逆势上扬。大年初二《流浪地球》票房环比大涨37.5%,大年初三的排片占比也已居榜首。在采访著名演员吴孟达时,甚至表态说:在拍摄之前,甚至不相信这个剧本是中国人写的。
先看看官方出品的“终极版”预告片感受下:
《流浪地球》预告片(终极版)https://www.zhihu.com/video/1083046516335316992相信短短2分钟的预告片,已经激发了你的激情,接下来,就和少帅一起,携手探索同一片天空下的朋友们对这部片子的感受。
说起影评,几乎所有人在脑海中浮现的第一个传送门便是“豆瓣电影”,废话不多说,带大家用Python撸一把豆瓣影评。
文末有代码福利哦(*^ワ^*)
本文分为两块,网络爬虫(上)、数据分析(下),采用的主要环境如下:
- 编程语言:Python 3.7 版本
- 开发环境:Pycharm(迷人的PY)
- 浏览器:Chrome
- 分析环境:Mircosoft Power BI、词云
- 数据存储:数据库Sqlite 3
- 第三方包:requests、PyQuery、WordCloud、jieba
第一部分 网络爬虫
这次网络爬虫的地址是:豆瓣电影
跳转到详情页后,首先映入我们眼帘的便是下面这个情况:
流浪地球 - 豆瓣电影我们直接就能感受到的以下几点:
- 豆瓣总体评分为7.9分,截止当前将近百万人进行评价;
- 主要星级为4星,占比40.2;其次为5星,占比30.7%;这两项之和已经超过了70%;
- 电影类型为:科幻/灾难,好于86%的科幻片,好于89%的灾难片。
我们再向下翻,找到短评的部分,截止发文时,已经有46万多条短评了,这也是我们本次爬虫的数据来源。
《流浪地球》- 豆瓣电影“短评”直接点击“更多短评”,查看所有短评。
对于每条短评,可获得以下信息:网友昵称、评分(星级)、发布日期、有用数量、短评内容
每条评论内容上述短评对应的网页代码如下:
<div class="comment-item" data-cid="1655519383">
<div class="avatar">
<a title="沙雕电影" href="https://www.douban.com/people/185573840/">
<img src="https://img3.doubanio.com/icon/u185573840-2.jpg" class="" />
</a>
</div>
<div class="comment">
<h3>
<span class="comment-vote">
<span class="votes">32488</span>
<input value="1655519383" type="hidden"/>
<a href="javascript:;" class="j a_vote_comment" onclick="">有用</a>
</span>
<span class="comment-info">
<a href="https://www.douban.com/people/185573840/" class="">沙雕电影</a>
<span>看过</span>
<span class="allstar40 rating" title="推荐"></span>
<span class="comment-time " title="2019-02-05 00:24:35">
2019-02-05
</span>
</span>
</h3>
<p class="">
<span class="short">一个悲伤的故事:太阳都要毁灭,地球都要流浪了,我国的校服还是这么丑......</span>
</p>
</div>
</div>
确定完每条短评我们要抓取的信息情况后,直接翻到最后一页,点击“后页”,分析网址的变化情况,便于抓到所有短评,可以看出,网址变化如下:
https://movie.douban.com/subject/26266893/comments?status=P
https://movie.douban.com/subject/26266893/comments?start=20&limit=20&sort=new_score&status=P
https://movie.douban.com/subject/26266893/comments?start=40&limit=20&sort=new_score&status=P
https://movie.douban.com/subject/26266893/comments?start=60&limit=20&sort=new_score&status=P
不难看出,每页评论的内容都是一个新的网址,其中,https://movie.douban.com/subject/26266893/comments为《流浪地球》短评的主要网址,后面依次的四个参数所代表的含义如下:
- status:状态(一共有两个值:【P】看过;【F】想看)
- start:每页评论开始条数
- limit:每页显示多少条评论(此参数不论修改为多少,都会只显示20条短评)
- sort:类型(一共有两个值:【new_score】热门;【time】最新)
不过,经过多次尝试,在未登录的情况下,翻到参数start=220的时候,页面就没有短评数据了,也就是说,我们最多只能抓取200条短评。
不过,在登录状态下,我们可以一直翻页到start=480的时候,页面就会提示没有短评数据了。为了获得更多短评数据,本次抓取就需要登录了。
到现在,我们在抓取前的准备就齐活了,接下来就需要直接上代码、开撸了。同时,考虑到最终要把所有的数据存储到数据库中,我们需要以下五大步骤:
- 根据抓取数据,建立数据库、数据表;
- 将短评网址发送给服务器,获取网页数据;
- 构造解析函数,提取我们需要的信息;
- 整理数据,将数据存储到数据库中;
- 根据网址规则,构造所有短评网址,循环上述步骤。
※考虑到豆瓣的反扒措施,我们还需要注意一定要设立睡眠时间函数,限制抓取频率。※
打开迷人的Pycharm,根据上述需求依次构造函数,代码分别如下:
首先需要引入所有相关包:
from urllib.parse import urlencode
from urllib3.exceptions import RequestError
import requests
from pyquery import PyQuery as pq
import random
import time
import sqlite3
1.建立数据库earth_data.db,数据表earth_data:
def create_table():
try:
conn=sqlite3.connect('earth_data.db')
print('连接数据库成功!')
cur = conn.cursor()
create_sql = '''
CREATE TABLE earth_data (
id integer primary key autoincrement not null,
data_cid integer,
nick_name character,
write_date character,
score character,
votes integer,
short character
);
'''
cur.execute(create_sql)
print('创建表成功!')
conn.commit()
except sqlite3.Error as e:
print('创建表出错!')
finally:
cur.close()
conn.close()
print('数据库已关闭!')
2.构建一条短评网址,发送给服务器,并获取所有网页信息(这里在构造headers时,出于保密,需要填写你们自己的cookie值):
def get_one_page(url):
try:
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Cookie': '', #你自己的cookie值
'Host': 'movie.douban.com',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}
response = requests.get(url=url, headers=headers)
if response.status_code == 200:
return response.text
else:
return None
except RequestError as e:
return None
3.构造解析函数,从上述网页信息中,提取我们需要的信息内容:
def parse_one_page(html):
infos = []
html = pq(html)
comments = html('#comments').children()
for comment in comments.items():
data_cid = comment('.comment-item').attr('data-cid')
nick_name = comment('.comment-info').text()
write_date = comment('.comment-time ').attr('title')
score = comment('.comment-info .rating').attr('title')
votes = comment('.votes').text()
short = comment('.short').text()
info = {
'data_cid':data_cid,
'nick_name':nick_name,
'write_date':write_date,
'score':score,
'votes':votes,
'short':short
}
if data_cid == None:
continue
else:
infos.append(info)
return infos
4.将解析出来的数据,存储到数据库中:
def write_data(infos):
try:
conn = sqlite3.connect('earth_data.db')
cur = conn.cursor()
print('写入连接数据库成功!')
write_sql = "insert into earth_data (data_cid, nick_name, write_date, score, votes, short) values (?, ?, ?, ?, ?, ?);"
for info in infos:
cur.execute(write_sql, (info['data_cid'], info['nick_name'], info['write_date'], info['score'], info['votes'], info['short']))
conn.commit()
print('写入数据成功!')
except sqlite3.Error as e:
print(e)
finally:
cur.close()
conn.close()
print('写入关闭数据库成功!')
5.最后一步,在主函数中,建立所有短评的网址:
def main():
create_table()
base_url = 'https://movie.douban.com/subject/26266893/comments?'
for page in range(0, 481, 20):
queries = {
'start': page,
'limit': '20',
'sort': 'new_score',
'status': 'P'
}
url = base_url + urlencode(query=queries)
html = get_one_page(url=url)
infos = parse_one_page(html=html)
print(infos)
write_data(infos=infos)
time.sleep(random.random()*15)
print('正在打印{}页'.format(page))
if __name__ == '__main__':
main()
这样,所有爬虫部分的代码便写完了,接下来要做的便是运行代码,看着输出所有数据到数据库中。
运行过程中,可以看到以下输出语句:
连接数据库成功!
创建表成功!
数据库已关闭!
……
……
……
写入连接数据库成功!
写入数据成功!
写入关闭数据库成功!
正在打印480页
Process finished with exit code 0
截止到现在,在分析电影《流浪地球》所需要的数据便全部下载并存储到数据库中了,下一篇文章,我们将继续以这些数据为核心,与朋友们一起,共同领略别样的风采!
上述完整代码及数据,已经上传至代码仓库GitHub了,具体地址见下方传送门,欢迎大家下载,如果感觉还不错,可以送给少帅一颗星,毕竟“赠人玫瑰,手留余香”。
sanshaoshuai/The-Wandering-Earthgithub.com最后感谢大家的关注,少帅也将尽快将后面关于数据分析的部分写出来,不见不散。如果喜欢这篇文章,希望左下方能给个“大拇哥”哦!