170行代码爬取《白蛇:缘起》短评数据

640?wx_fmt=jpeg

题图:《白蛇:缘起》海报

阅读文本大概需要 11 分钟。

在我的童年记忆中,电视台播放的动画片大多都是从日本、美国引进的。很多动画片算是银幕上的经典,例如:《变形金刚》系列、《猛兽侠》、《蜘蛛侠》、《七龙珠》、《名侦探柯南》、《灌篮高手》、《数码宝贝》等。

但是国产的精品动画篇确认寥寥无几,可能是当时我国动漫产业还处在起步阶段。一晃几十年过去了,现在的国产动漫算是强势崛起,这也涌现出《斗破苍穹》、《秦时明月》、《天行九歌》等优秀的动画片。

2019年1月11日,一部国产动画电影《白蛇:缘起》在全国热映,一经上映便是好评如潮。这部电影凭借惊艳的花屏,出色的配音取得猫眼 9.4 分、豆瓣 8.0 分的高分成绩。

既然是难得一见的精品,那么我去猫眼上爬爬网友的短评,看看网友们的观点。


01

分析页面

估计很多人经常光顾猫眼电影网,猫眼的反爬机制越来越严格,手段也越来越多。如果选择“刚正面”,爬取 PC 端的页面,可能总体收益不高。况且,PC 端的页面只有精彩短评,没有全部的网页评论数据。

640?wx_fmt=png

因此,我选择转移战场,从手机页面入手,看看是否有收获。将浏览器选择以手机模式浏览器,结果发现手机网页有全部的短评数据。点击“查看全部讨论”,继续抓包分析。

640?wx_fmt=png

随着鼠标滚动,自己浏览过几页短评数据之后,最终找到规律。

640?wx_fmt=png


640?wx_fmt=png


640?wx_fmt=png

页面请求的地址是:

 
 

http://m.maoyan.com/review/v2/comments.json?

后面携带一些参数:

 
 

movieId=1235560&  #电影id
userId=-1#默认用户id
offset=0#分片页数
limit=15#每个分片显示具体数值
ts=0#当前时间
type=3

然后 offset 的值以 15 间隔递增。

我格式化请求结果,确认能获取到短评内容、点赞数等。但是这个无法满足我的需求,我是想获取城市信息,后面想绘制地理热力图。而目前这个接口没有城市信息。

因此,我选择逛逛各大搜索引擎,试下碰碰运气。最后幸运女神帮了我一把,我找到别人已经挖掘到的猫眼短评接口。

 
 

http://m.maoyan.com/mmdb/comments/movie/1235560.json?_v_=yes&offset=1

其中 1235560 表示电影的 id,offset 代表页数。


02

爬虫制作

因为短评数据量可能会比较多,所以我选择用数据库来存储数据。后面方便进行数据导出、数据去重等。

自己从 json 数据结果中提取想要的数据,然后设计数据表并创建。

 
 

def create_database(self):
    create_table_sql = (
        "CREATE TABLE IF NOT EXISTS {} ("
        "`id` VARCHAR(12) NOT NULL,"
        "`nickName` VARCHAR(30),"
        "`userId` VARCHAR(12),"
        "`userLevel` INT(3),"
        "`cityName` VARCHAR(10),"
        "`gender` tinyint(1),"
        "`score` FLOAT(2,1),"
        "`startTime` VARCHAR(30),"
        "`filmView` BOOLEAN,"
        "`supportComment` BOOLEAN,"
        "`supportLike` BOOLEAN,"
        "`sureViewed` INT(2),"
        "`avatarurl` VARCHAR(200),"
        "`content` TEXT"
        ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4".format(self.__table)
    )

    try:
        self.cursor.execute(create_table_sql)
        self.conn.commit()
    except Exception as e:
        self.close_connection()
        print(e)

然后构造 Session 会话、请求头 headers 和 url 地址。

 
 

""" 构造会话 Session 抓取短评 """
session = requests.Session()
# 电影短评地址
movie_url = 'http://m.maoyan.com/mmdb/comments/movie/1235560.json?_v_=yes&offset={}'

headers = {
    'User-agent''Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Mobile Safari/537.36',
    'Accept-Encoding''gzip, deflate',
    'accept''text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Host''m.maoyan.com',
    'Accept-Language''zh-CN,zh;q=0.8',
    'Cache-Control''max-age=0',
    'Connection''keep-alive',
    'Upgrade-Insecure-Requests''1',
}

接着请求 url 地址并解析返回的 Json 数据。

 
 

offset = 1
while 1:
    print('============抓取第', offset, '页短评============')
    print('============>>>', movie_url.format(offset))
    response = session.get(movie_url.format(offset), headers=headers)
    if response.status_code == 200:
        """ 解析短评 """
        data_list = []
        data = {}
        for comment in json.loads(response.text)['cmts']:
            data['id'] = comment.get('id')
            data['nickName'] = comment.get('nickName')
            data['userId'] = comment.get('userId')
            data['userLevel'] = comment.get('userLevel')
            data['cityName'] = comment.get('cityName')
            data['gender'] = comment.get('gender')
            data['score'] = comment.get('score')
            data['startTime'] = comment.get('startTime')
            data['filmView'] = comment.get('filmView')
            data['supportComment'] = comment.get('supportComment')
            data['supportLike'] = comment.get('supportLike')
            data['sureViewed'] = comment.get('sureViewed')
            data['avatarurl'] = comment.get('avatarurl')
            data['content'] = comment.get('content')
            print(data)
            data_list.append(data)
            data = {}
        print('============解析到', len(data_list), '条短评数据============')
        self.insert_comments(data_list)
    else:
        # 抓取失败就先暂停抓取, 标记抓取页数, 过段时间再抓取
        print('>=== 抓取第 ', offset, ' 失败, 错误码为 ' + response.status_code)
        break
    offset += 1
    time.sleep(random.randint(1020))

完成解析数据工作之后,最后一步工作就是将数据插入到数据库中。

 
 

def insert_comments(self, datalist):
    """ 往数据库表中插入数据 """
    insert_sql = (
        "insert into "
        "{} (id, nickName, userId, userLevel, cityName, gender, score, "
        "startTime, filmView, supportComment, supportLike, sureViewed, avatarurl, content)"
        "values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)".format(self.__table))

    try:
        templist = []
        for comment in datalist:
            if comment.get('gender'is None:
                comment['gender'] = -1
            data = (comment.get('id'),
                    comment.get('nickName'),
                    comment.get('userId'),
                    comment.get('userLevel'),
                    comment.get('cityName'),
                    comment.get('gender'),
                    comment.get('score'),
                    comment.get('startTime'),
                    comment.get('filmView'),
                    comment.get('supportComment'),
                    comment.get('supportLike'),
                    comment.get('sureViewed'),
                    comment.get('avatarurl'),
                    comment.get('content'))
            templist.append(data)
        self.cursor.executemany(insert_sql, templist)
        self.conn.commit()
    except Exception as e:
        print('===== insert exception -->>> %s', e)

我因控制爬虫速率,暂时还没有完成爬取工作。至于爬取结果,详情见下篇文章关于电影短评的数据分析。

如果你觉得文章还不错,请大家点『好看』分享下。你的肯定是我最大的鼓励和支持。


推荐阅读:

分享一个爬取网站的小技巧

图表类型,你选对了吗?

账号认证那些事



不积跬步,无以至千里


640



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Python的requests和BeautifulSoup库爬取《西游记》第一回的代码: ```python import requests from bs4 import BeautifulSoup url = 'https://www.shicimingju.com/book/xiyouji/1.html' # 发送请求并获取响应内容 response = requests.get(url) html = response.text # 解析HTML soup = BeautifulSoup(html, 'html.parser') content_div = soup.find('div', class_='chapter_content') # 提取正文内容 content = '' for p in content_div.find_all('p'): content += p.text.strip() + '\n' # 输出结果 print(content) ``` 运结果为: ``` 话说天下大势,分久必合,合久必分。周末七国分争,并入于秦。及秦灭之后,楚、汉分争,又并入于汉。汉朝自高祖斩白蛇起义,一统天下,后来光武中兴,传至于今,一统乾坤。盖因暴秦之时,诸侯并起,吞吴、越,灭燕、赵,此并吞之法也。后来者,因难并力,兼及诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、历亮之任也。愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、历亮等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏。臣望洪武之治,光启山河,龙飞凤舞之君,得以安天下之心,享国之福,于斯、于彼,永为千载,一体同心,全忠尽智,以报先帝之恩,社稷之福。至于斟酌损益,则攸之、历亮之任也。''' ``` 这段代码首先使用requests库发送请求并获取响应内容,然后使用BeautifulSoup库解析HTML并找到正文内容所在的div标签,最后提取出正文内容并输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值