美文网首页
2020-07-16--爬虫数据提取--json

2020-07-16--爬虫数据提取--json

作者: program_white | 来源:发表于2020-07-16 16:19 被阅读0次

    json

    现在的网站服务器一般都是用json数据响应到客户端浏览器的,所以,我们发送请求后可以直接获取服务器响应回来的json数据,从而达到爬取数据的效果。
    对于爬取出来的数据要进行数据提取,也就是提取出我们想要的数据。

    数据分类

    服务器响应回来的数据一般分为两种:

    • 非结构化数据: html , 文本等 处理方法:正则表达式,xpath语法
    • 结构化数据:json,xml等 处理方法:转换为python数据类型

    json

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互。
    json格式

    json对象
    {"key":"value"}
    json数组
    [{"key":"val"},{"key":"val"}]
    

    json类型与pytohn数据类型的转换

    把json格式字符串转化为python字典类型很简单,所以爬虫中,如果我们能够找到返回json数据格式字符串的url,就会尽量使用这种url 如何找到返回json的url呢? 1、使用浏览器/抓包工具进行分析 wireshark(windows/linux),tcpdump(linux) 2、抓包手机app的软件

    json和python转换方法

    1. json.loads()
    把Json格式字符串解码转换成Python对象

    2. json.dumps()
    实现python类型转化为json字符串,返回一个str对象 把一个Python对象编码转换成Json字符串

    3. json.dump()
    将Python内置类型序列化为json对象后写入文件

    4. json.load()
    读取文件中json形式的字符串元素 转化成python类型

    实例

    import json
    
    '''
    
    dict与json的互转:
    json.dumps(dict) : dict to json   
    json.loads(json) : json to dict
    
    '''
    dict_obj = {'name':'lizhao','age':'20'}
    print(dict_obj,type(dict_obj))          #<class 'dict'>    字典
    
    json_obj = json.dumps(dict_obj)         #dict to json
    
    print(json_obj,type(json_obj))         #<class 'str'>   json字符串
    
    dict_obj1 = json.loads(json_obj)        #json to dict
    
    print(dict_obj,type(dict_obj))         #<class 'dict'>    字典
    
    
    '''
    dict与json的文件操作
    json.dump(dict) : 将dict转为json类型存入指定文件
    json.load(文件名) : 读出json类型文件的数据,转为dict类型
    
    '''
    dictObj = {'name':'zhansan','age':'22'}
    
    f = open('data.json','w',encoding='utf-8')         #创建json类型的文件
    json.dump(dictObj,f,ensure_ascii=False)         #将dict转为json类型写入指定json文件
    f.close()
    
    t = open('data.json','r',encoding='utf-8')
    jsonObj = json.load(t)
    print(type(jsonObj),jsonObj)                #<class 'dict'> {'name': 'zhansan', 'age': '22'}
    

    data.json:

    {"name": "zhansan", "age": "22"}
    

    结果:

    爬取豆瓣电视信息

    进入豆瓣的电影页面后。会发起多个ajax请求,每个ajax请求请求不同的内容,标签,电影信息,电视信息等。

    请求电影信息的ajax请求,返回 json数据类型:


    爬取前50个电影信息:
    代码:

    import requests
    import json
    
    #请求url
    xurl = 'https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start=0'
    #请求头
    xheader  ={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
    }
    
    resp = requests.get(url=xurl,headers=xheader)
    
    resp_json_dict = resp.json()
    print(resp_json_dict)          #dict对象
    
    
    
    #遍历输出
    for item in resp_json_dict['subjects']:
        print(item['title']+'---'+item['rate'])
    
    
    #保存到文件
    with open('douban.json', 'w', encoding='utf-8') as f:
        # 将dict对象
        json.dump(resp_json_dict['subjects'],f,ensure_ascii=False)
    

    结果:

    爬取都把所有的电影信息(url变换)

    在上一步中我们爬取了豆瓣电影的电影信息,但是也只是爬取了第一页的50个数据,那么如果要爬取所有的数据怎么实现呢?

    也就是在爬取完第一个url后,切换到下一页的url,再次发送请求,得到数据。

    首先分析url:

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

    通过观察:参数page_limit:每一页的电影数量,page_start:每页第一个的编号。
    通过实验得到该网站最多有500个电影数据,也就是page_start最大值为450.

    import requests
    import json
    import time
    
    class Douban:
    
        def __init__(self):
            # 定义当前页码
            self.start_page=0
            # 定义当前请求url
            self.url=f'https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start={self.start_page}'
            self.header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
    
        def go(self):
            
            movie_all_list = []          #定义存储所有电影的列表
            
            for i in range(10):                   #循环多次发出请求
                resp = requests.get(url=self.url,headers=self.header)        #发送第一次请求
                print(self.start_page)            
                # print(resp.json())
                resp_list = resp.json()['subjects']            #获取每次请求的数据(直接获取列表)
                # print(resp_list)
    
                movie_all_list+=resp_list                  #存到总列表
    
                time.sleep(1)           #休眠一秒,防止察觉
    
                self.start_page += 50            #修改start_page,切换到下一页电影页
                #修改新的url
                self.url=f'https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start={self.start_page}'
            
            #打印获取到的列表
            print(movie_all_list)
            print(type(movie_all_list))
            print(len(movie_all_list))
    
            #保存文件
            with open('douban_all.json','w',encoding='utf-8') as f:
                json.dump(movie_all_list,f,ensure_ascii=False)
    
    
    if __name__ == '__main__':
        douban = Douban()
        douban.go()
    

    结果:

    爬取电影名称以及每个电影的导演

    爬取电影名称以及每个电影的导演,并保存到文件中。
    代码:

    import requests
    import time
    import re
    
    
    class Movie:
        def __init__(self,t,m,d):
            self.title=t
            self.moveurl=m
            self.dor=d
        def __str__(self):
    
            return f'电影:{self.title},导演:{self.dor}'
    
    
    
    class Douban:
        def __init__(self):
            # 定义当前页码
            self.start_page=0
            # 定义当前请求url
            self.url=f'https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start={self.start_page}'
            self.header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
            # self.wfile = open('')
    
        def download(self):
            '''
            在循环中发送第一次请求,休眠1秒
            如果返来的数据不为空,那么获取数据,取出subjects的值
            然后遍历该值,每次请求其中的url,并使用正则获取导演名
            最后实例化Movie类
            将movie对象转为字符串存入文件中
            :return:
            '''
            while True:
                resp=requests.get(url=self.url,headers=self.header)
    
                time.sleep(0.5)
    
                if resp:
    
                    pdata=resp.json()['subjects']
    
                    for it in pdata:             #遍历每一个电影信息
                        p=requests.get(url=it['url'],headers=self.header)        # 取出url在发起请求
    
                        t=re.findall('rel="v:directedBy">(.*?)</a>',p.text)       #获取请求中的导演(使用正则匹配)
    
                        movie=Movie(it['title'],it['url'],t)             #经三个数据实例化movie对象
    
                        print(movie)
    
                        #保存文件
                        with open('movie.txt','a',encoding='utf-8') as f:
                            f.write(str(movie))
                            f.write("\n")
    
    
    
                    self.start_page +=50
                    self.url = f'https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start={self.start_page}'
                else:
                    break
    
    
    if __name__ == '__main__':
        dou=Douban()
        dou.download()
    

    结果:

    这里没有加载完,因为数据量太大。

    相关文章

      网友评论

          本文标题:2020-07-16--爬虫数据提取--json

          本文链接:https://www.haomeiwen.com/subject/fbkphktx.html