python3爬虫系列07之动态网页Json 数据,爬虫要怎么搞?

可紊 提交于 2019-11-27 09:01:26

python3爬虫系列07之动态 Json 数据,要怎么搞?

1.前言

经过 python爬虫实战系列 中的 python3爬虫系列06之整体架构式:根据关键词爬取百度图片 相关学习,现在我们已经会一些基本的静态html页面的爬虫了。

接下来开始一些更复杂和实战例子;

在前面我们玩了好多静态的 HTML ,想必你应该知道怎么去爬这些数据了,但还有一些常见的动态数据,比如:商品的评论数据,实时的直播弹幕,各类影片的评分等等…

这些数据是会经常发生改变的,因此很多网站就会用到 Json 来传输这些数据
那么遇到 Json 我们应该怎么办呢

首先要知道python怎么在json格式中获取到想要的数据:

python 的 json 模块有两个主要的函数:

将 python 对象转化为 json格式: json.dumps()

将json数据转化为python对象: json.loads()

具体使用操作可以参考:

python对json对象或json数组操作以及读写各类txt,csv,html,xls文件的工具类

2.动态网页requests+json爬虫:根据输入词爬取豆瓣热门影片

好了,不吹牛皮了,说半天不如实战。

环境:

  • Python版本 :3.6
  • 爬取网页模块:requests
  • 分析网页模块:json
  • 保存CSV文件

要知道 动态网页指的是网页的内容通过js动态加载出来的数据。那么分析一顿是免不了的啦。

2.1 网页分析

本次爬虫的目标是豆瓣电影和电视剧页面

豆瓣电影的选电影页

URL如下:

https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0

一打开这个页面我们可以看到,其下方有一个【加载更多】。。

这就是动态加载的,所以我们无法直接通过get方法获取网页内容。
在这里插入图片描述

所以,当我们点击加载更多时,可以通过开发者工具(浏览器里面按F12打开) Network选项中的XHR 来获取动态加载的js。
在这里插入图片描述

查看请求,然后haders里面有个url:

在这里插入图片描述

打开获取到的连接:

https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0

可以看到返回的是json数据:
在这里插入图片描述
观察可以发现,不同页的连接的规律,是page_limitpage_start,两个参数。也就是说,我们可以通过控制这两个参数来动态变化页面的内容,比如翻页。

这里我们就可以尝试构造一个连接,让它从第一个电影开始,并显示200个:

https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=200&page_start=0

打开验证就知道了,

电影的:在这里插入图片描述

电视剧的也一样:

https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0

在这里插入图片描述

然后随便复制一下这个页面里面的一段json数据。

打开浏览器,在线解析一下这个json:
(你随便百度一下json在线解析就可以了)
在这里插入图片描述
通过这个json,我们假设需要的数据内容是:

  1. 评分rate
  2. 电影名称title
  3. 电影的豆瓣链接url
  4. 封面图片的地址cover

OK,分析完毕,就开始整代码了。在这里插入图片描述

2.2 撸码环节

因为动态页面中,我们看到请求返回的是json数据,而且有了对应的URL地址,所以就不需要再使用什么beautifulsoup 解析器了。

直接将响应的json字符串,转为python的字典对象操作就好了。

热门电影的爬虫:

rowCount 是对应的条数。

# 热门电影
def douban_movie(rowCount):
    url='https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0'

    # 解决出现403拒绝访问
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                             'Chrome/51.0.2704.63 Safari/537.36'}
    # 使用request模块打开并获取网页内容
    response = requests.get(url,headers = headers,verify=False,timeout=30)
    print(response.text)   # 报错:json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
                    # 解决:以后在使用json时,最好先输出一下参数,检查一下是否符合格式?
    content = response.content

    # json格式转为字典
    result = json.loads(content)
    print(content,result)

    # 获取相关信息并存入列表的字典中
    movie_list = []
    mos = result['subjects']
    for i in range (0,len(mos)):
        mo = {}
        mo['rate']=mos[i]['rate']
        mo['cover']=mos[i]['cover']
        mo['url']=mos[i]['url']
        mo['title']=mos[i]['title']
        movie_list.append(mo)       # 列表存放字典
    return movie_list

热门电视剧的爬虫:

rowCount 是对应的条数。

# 热门电视剧
def douban_tv(rowCount):
    url='https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0'
    print(url)
    # 解决出现403拒绝访问
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                             'Chrome/51.0.2704.63 Safari/537.36'}
    # 使用request模块打开并获取网页内容
    response = requests.get(url, headers=headers, verify=False, timeout=30)   # 禁止重定向
    content = response.text
    print(content)
    # 返回的是json,那么就直接解码转为字典。不需要解析器bs了
    result = json.loads(content)
    tvs = result['subjects']

    tv_list = []        # 创建一个列表
    for i in range (0,len(tvs)):
        tv={}             # 创建一个字典
        tv['rate']=tvs[i]['rate']            # 评分
        tv['title']=tvs[i]['title']          # 电影名称
        tv['cover'] = tvs[i]['cover']  # 封面图片的地址
        tv['url'] = tvs[i]['url']  # 电影的豆瓣链接
        tv_list.append(tv)               # 列表存放字典
    return tv_list

其实是差不多的,甚至可以简化到一个函数去共用。

然后就是保存一下爬取的数据:

# 保存为csv文件
def output_csv(datalist):
    print(type(datalist),len(datalist))  # <class 'list'> 100
    import csv
    # 准备好存储的csv文件
    csv_file = open("douban_data.csv", 'w', newline='', encoding='utf-8-sig')  # 解决中文乱码问题
    writer = csv.writer(csv_file)
    writer.writerow(['评分', '作品名称', '豆瓣链接','封面图片'])
    for data in datalist:
        writer.writerow([data['rate'], data['title'],data['url'],data['cover']])
    csv_file.close()

最后呢调用传参:

if __name__=="__main__":
    category = input('请输入爬取的类别代号(电视剧:0,电影:1):')
    rowCount = input('请输入爬取的条数:')
    if category=='0':
        print('爬取电视剧中,请稍后...')
        result = douban_tv(rowCount)
    elif category=='1':
        print('爬取电影中,请稍后...')
        result = douban_movie(rowCount)
    else:
        print('输入错误,暂不支持,请重试...')

   # 持久化保存
    # for i in result:
    #     print(i)
    output_csv(result)

    print("爬虫完毕,文件已生成。快去查看吧")

整个源码:

#!/usr/bin/python3

#@Readme : 豆瓣热门电影/电视剧-不需登录的动态网页爬虫-ajax加载的
# 目标: https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0
# 返回的是json数据,那么就不需要解析器了。直接转字典就好了。

import requests
import json

# 热门电视剧
def douban_tv(rowCount):
    url='https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0'
    print(url)
    # 解决出现403拒绝访问
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                             'Chrome/51.0.2704.63 Safari/537.36'}
    # 使用request模块打开并获取网页内容
    response = requests.get(url, headers=headers, verify=False, timeout=30)   # 禁止重定向
    content = response.text
    print(content)
    # 返回的是json,那么就直接解码转为字典。不需要解析器bs了
    result = json.loads(content)
    tvs = result['subjects']

    tv_list = []        # 创建一个列表
    for i in range (0,len(tvs)):
        tv={}             # 创建一个字典
        tv['rate']=tvs[i]['rate']            # 评分
        tv['title']=tvs[i]['title']          # 电影名称
        tv['cover'] = tvs[i]['cover']  # 封面图片的地址
        tv['url'] = tvs[i]['url']  # 电影的豆瓣链接
        tv_list.append(tv)               # 列表存放字典
    return tv_list

# 热门电影
def douban_movie(rowCount):
    url='https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0'

    # 解决出现403拒绝访问
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                             'Chrome/51.0.2704.63 Safari/537.36'}
    # 使用request模块打开并获取网页内容
    response = requests.get(url,headers = headers,verify=False,timeout=30)
    print(response.text)   # 报错:json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
                    # 解决:以后在使用json时,最好先输出一下参数,检查一下是否符合格式?
    content = response.content

    # json格式转为字典
    result = json.loads(content)
    print(content,result)

    # 获取相关信息并存入列表的字典中
    movie_list = []
    mos = result['subjects']
    for i in range (0,len(mos)):
        mo = {}
        mo['rate']=mos[i]['rate']
        mo['cover']=mos[i]['cover']
        mo['url']=mos[i]['url']
        mo['title']=mos[i]['title']
        movie_list.append(mo)       # 列表存放字典
    return movie_list

# 保存为csv文件
def output_csv(datalist):
    print(type(datalist),len(datalist))  # <class 'list'> 100
    import csv
    # 准备好存储的csv文件
    csv_file = open("douban_data.csv", 'w', newline='', encoding='utf-8-sig')  # 解决中文乱码问题
    writer = csv.writer(csv_file)
    writer.writerow(['评分', '作品名称', '豆瓣链接','封面图片'])
    for data in datalist:
        writer.writerow([data['rate'], data['title'],data['url'],data['cover']])
    csv_file.close()

if __name__=="__main__":
    category = input('请输入爬取的类别代号(电视剧:0,电影:1):')
    rowCount = input('请输入爬取的条数:')
    if category=='0':
        print('爬取电视剧中,请稍后...')
        result = douban_tv(rowCount)
    elif category=='1':
        print('爬取电影中,请稍后...')
        result = douban_movie(rowCount)
    else:
        print('输入错误,暂不支持,请重试...')

   # 持久化保存
    # for i in result:
    #     print(i)
    output_csv(result)

    print("爬虫完毕,文件已生成。快去查看吧")

运行一下,爬取结果:
电视剧
在这里插入图片描述
电影
在这里插入图片描述
…东西是动态的,如果你想抓其他的类型,比如综艺啊,纪录片啊什么的,就是多加一个方法即可。


代码对应的介绍已经写在了注释中,不明白可以评论留言。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!