美文网首页
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