每天30分钟 一起来学习爬虫——day12(数据存储 之 json &csv,实例:爬取All IT eBook)


json

什么是json

JSON是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度,

那么,JSON到底是什么?

JSON就是一串字符串 只不过元素会使用特定的符号标注。

{} 双括号表示对象
[] 中括号表示数组
“” 双引号内是属性或值
: 冒号表示后者是前者的值(这个值可以是字符串、数字、也可以是另一个数组或对象)

所以 {"name": "Michael"}可以理解为是一个包含nameMichael的对象

[{"name": "Michael"},{"name": "Jerry"}]就表示包含两个对象的数组

这里有个图看看
在这里插入图片描述

python处理json格式用到的函数

import josn
json.dumps() #将列表或字典转化为json格式的**字符串**。
json.loads() #把json格式的字符串转化为python对象
json.dump()  #将列表或字典转化为json格式的字符串并且写入到文件中。
json.load()	 #从文件中把json格式的字符串转化为python对象
  1. json字符串 转换为 字典,列表

    import json
    
    ## 标准的json格式字符串
    data = '[{"name":"爬虫","age":"100"},{"name":"张三","age":"19"}]'
    list_data = json.loads(data)
    print(data)
    print(type(data))
    print(list_data)
    print(type(list_data))
    '''
    [{"name":"爬虫","age":"100"},{"name":"张三","age":"19"}] 
    <class 'str'>
    [{'name': '爬虫', 'age': '100'}, {'name': '张三', 'age': '19'}]
    <class 'list'>
    # 打印出来好像就长了点,没啥区别,要看看类型
    '''
    
  2. 列表 转换 json字符串

    
    lt = [
        {'name': '位符', 'age': 23},
        {'name': '士大夫', 'age': 53},
        {'name': '对对对', 'age': 253},
        {'name': 'l的发r', 'age': 24}
    ]
    str_lt = json.dumps(lt)
    print(lt)
    print(type(lt))
    print(str_lt)
    print(type(str_lt))
    '''
    [{'name': '位符', 'age': 23}, {'name': '士大夫', 'age': 53}, {'name': '对对对', 'age': 253}, 	{'name': 'l的发r', 'age': 24}]
    <class 'list'>
    [{"name": "\u4f4d\u7b26", "age": 23}, {"name": "\u58eb\u5927\u592b", "age": 53}, 		{"name": "\u5bf9\u5bf9\u5bf9", "age": 253}, {"name": "l\u7684\u53d1r", "age": 24}]
    <class 'str'>
    '''
    
  3. 写入文件

    '''
    ## 看看以前的写法
    lt2 = [
        {'name': '位符', 'age': 23},
        {'name': '士大夫', 'age': 53},
        {'name': '对对对', 'age': 253},
        {'name': 'l的发r', 'age': 24},
    ]
    with open ('json2.josn','w')  as f:
        f.write(json.dumps(lt2))
    '''
    ## 但这个太麻烦了,我们现在用json 
    json.dump(lt2, open('json3.josn', 'w', encoding='utf8'))
    
    
  4. 读取json文件

    
    obj = json.load(open('json3.json', 'r', encoding='utf8'))
    print(type(obj))
    print(obj)
    '''
    <class 'list'>
    [{'name': '位符', 'age': 23}, {'name': '士大夫', 'age': 53}, {'name': '对对对', 'age': 253}, 	{'name': 'l的发r', 'age': 24}]
    '''
    
    

json 小伙伴们应该都有了解,下面看CSV


CSV

什么是CSV:

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)

通俗点讲,有点像 Excel

操作

首先呢,这个csv 它不用安装,系统自带的 直接 import csv 就可以用啦 ~~~

import json
import csv
## 不用安装,自带的。
##使用是 我们要生成一个csv写入器
csv.writer() ##传入json文件
writerow()# 写入表头,传入的是字典或列表
writerows()# 写入内容

json文件转csv文件

把json 文件转换成 csv,注意啊,这里必须是标准json格式的文件,上面学json的时候我们生成过一个,就用那个改一改用吧。

在这里插入图片描述

  1. 分别读取json,创建csv文件
import json
import csv
json_fp=open('json_csv.josn','r')
csv_fp = open('csv1.csv','w')
  1. 提出表头
# json转化为python列表
data_list = json.load(json_fp)
# 提出表头,按我这个文件,返回的是一个列表,里面元素是字典
sheet_title=data_list[0].keys()
print(sheet_title)
## 也可以自己写表头
# sheet_title={"姓名","年龄"}
  1. 提出内容
sheet_data = []
for data in data_list:
    sheet_data.append(data.values())
  1. 写入csv文件
# 生成csv写入器
writer = csv.writer(csv_fp)
# 写入表头
writer.writerow(sheet_title)
# 写入内容
writer.writerows(sheet_data)
# 关闭两个文件
json_fp.close()
csv_fp.close()

这样就转好了啊,打开看看

在这里插入图片描述不要着急,不要着急,我们看看啊,
我这里是因为,VS Code 和我系统的编码不太一样,我们可以改一下Excel 的编码

文件另存为
在这里插入图片描述
或者在工具里

在这里插入图片描述
点击web选项

在这里插入图片描述
其实不要在VS Code 里打开,直接在电脑上打开就是正常的,VS Code 自动把编码格式转换了,然后保存起来了,所以下次在电脑上打开的时候就乱码了呢

在这里插入图片描述
我们可以看一下电脑默认的编码,打开 cmd 输入 chcp ,然后查找对应的地区编码

在这里插入图片描述
编码问题就说这么多,不同电脑不太一样,可以试一试然后就知道了。



实例:爬取 All IT eBooks

就是这个网站 ,好多书 All IT eBooks,国外的网站爬取的时候,速度超级慢,,我都想要睡着了。我们就爬取一下 书名,作者,简介,链接就好了

先看看这个网站

在这里插入图片描述

在这里插入图片描述
也是封装个类来爬取:

  1. 首先发送请求,获取响应,注意我们要爬取多页,所以需要拼接url
  2. 解析网页内容,这里我用xpath解析,伙伴们也可以试试bs4
  3. 保存数据,保存为 json 和 csv (都保存看看)

为了保证代码的完整,,代码后面放图图~~

import requests
import json
from lxml import etree
import csv
import time


class bookSpider(object):
    def __init__(self):
        self.base_url = 'http://www.allitebooks.org/page/{}'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
        }
        self.book_all_list = [] # 用于存放所有的书,每个书是一个字典,然后放在这个列表里
   
    # 得到所有的url ,这里我就爬两页,
    def get_url_list(self):
        urllist = []
        for i in range(1, 3):
            url = self.base_url.format(i)
            urllist.append(url)
        return urllist
    
    # 发送请求
    def send_request(self, url):
        data = requests.get(url, headers=self.headers).content.decode('utf8')
        return data
        # 这里我先用字节类型,然后再编码为utf8,为什么我不直接用text()这个方法呢,等会再说

    # 解析数据
    def parse_data(self, data):
        tree = etree.HTML(data)
        book_all = tree.xpath('//div/article')
        # 看看我的截图,每一本书的信息全部都在article里保存,所以我先获取每一页所有书
        # 为了保证代码的完整性,截图放下面了
        j=1
        for book in book_all:# 再通过xpath解析详细内容,方便保存
            book_dict = {}
            print('第 %d 本书开始解析'%j)
            # 书名
            book_dict['book_title'] = book.xpath('.//h2/a/text()')[0]
            # 书的详情页链接
            book_dict['book_link'] = book.xpath('.//h2/a/@href')[0]
            # 图书的封面图片
            book_dict['book_img'] = book.xpath('.//a/img/@src')[0]
            # 作者,有的书有多个作者
            book_author = book.xpath('.//h5/a/text()')
            authors = ' , '.join(book_author)
            book_dict['author'] = authors
            # 简介
            book_dict['book_summary'] = book.xpath('.//p/text()')[0]
            # 放到列表里
            self.book_all_list.append(book_dict)
            ## print(self.book_all_list)
            j=j+1

    # 保存数据
    def save_data(self):
    	# 写入json 文件 
        json.dump(self.book_all_list, open('book.json', 'w', encoding='utf8'))
        # 打开csv文件
        fp = open('book.csv', 'w', encoding='utf8')
        # 提出表头
        sheet_title = self.book_all_list[0].keys()
        # 提出内容
        sheet_data = []
        for book in self.book_all_list:
            sheet_data.append(book.values())
        # csv 写入器
        writer = csv.writer(fp)
        # 写入表头
        writer.writerow(sheet_title)
        # 写入内容
        writer.writerows(sheet_data)
        # 关闭
        fp.close()

    # 调用跑一下
    def run(self):
        urllist = self.get_url_list()
        for url in urllist:
            data = self.send_request(url)
            self.parse_data(data)

        self.save_data()


if __name__ == "__main__":
    bookSpider().run()

这样就爬完了,速度巨慢,,,哭了,我们看一看啊

先看看我xpath 的解析

在这里插入图片描述

在这里插入图片描述好了,剩下的就不一 一截图了,都是这个样子的,
但是,这里注意一下,我代码是通过book 又进行了 xpath 的解释,这个时候,就拿上图标题为例,我们路径的要写 .//h2/a/text() 双斜杠前的 代表的是从当前节点开始,如果没有 则是跨节点,会全局查找,数据就比较乱,思路不清晰,有时候可能没有问题,但我们还算习惯把它写精确一些,

刚才代码里还说 先用字节类型,然后再编码为utf8,为什么我不直接用text(),也是一样,text()的编码方式是计算机猜的,不是确定的,所以我们自己给它规定好,减少出错。

还有两个作者的问题,使用join() 方法后也解决了

在这里插入图片描述

现在看看结果吧

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

这个英文什么的有点长,放到csv中反而不太好看,(哭—),今天讲的还算比较多的

就到这里吧,明天我们学习一下MongoDB 这个数据库。(emmmm,具体的明天说吧)



又到了卑微的要赞环节,如果觉得可以学到些什么的话点个赞再走吧,欢迎各位路过的大佬评论指正,有问题也欢迎各位小伙伴们评论,私聊。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值