python 爬虫(五)json模块最全攻略(相关方法详解) + 使用正则抓取数据的案例(猫眼电影 + 股吧 + 药网)

爬虫精髓:使用.*?进行匹配获取内容

python小技巧: alt加回车键快速导包

一、json相关方法及用法


1. json的概念


  • 定义:JSON 的 全称是 JavaScript Object Notation,即 JavaScript 对象符号,它是一种轻量级、跨平台、跨语言的数据交换格式

  • 设计意图:把所有事情都用设计的字符串来表示,这样既方便在互联网上传递信息,也方便人进行阅读。

  • 发展:最早的时候,JSON 是 JavaScript 语言的数据交换格式,后来慢慢发展成一种语言无关的数据交换格式,这一点非常类似于 XML。

  • 使用范围:JSON 主要在类似于C 的编程语言中广泛使用,这些语言包括 C、C++、C#、Java、JavaScript、Perl、Python 等。JSON 提供了多种语言之间完成数据交换的能力,因此,JSON 也是一种非常理想的数据交换格式。

  • JSON 主要有如下两种数据结构(语法)
    (1)由 key-value 对组成的数据结构(对象)
                这种数据结构在不同的语言中有不同的实现。例如,在 JavaScript 中是一个对象;在 Python 中是一种 dict 对象;在 C 语言中是一个 struct;在其他语言中,则可能是 record、dictionary、hash table 等。
    (2)有序集合(数组)
               这种数据结构在 Python 中对应于列表;在其他语言中,可能对应于 list、vector、数组和序列等。

总结:上面两种数据结构在不同的语言中都有对应的实现,因此这种简便的数据表示方式完全可以实现跨语言。所以,JSON 可以作为程序设计语言中通用的数据交换格式。

可以简洁为以下几点:

  • json是一种通用的数据类型
  • 一般情况下接口返回的数据类型都是json
  • 长得像字典,形式也是key-value
  • 其实json是字符串
  • 字符串不能用key、value来取值,所以要先转换为字典才可以

2. json的操作


1. json.dumps()和json.loads()是将python中的list或dict转换成json语句(可以这么理解为操作数据)


(1) json.dumps()函数是将一个Python数据类型列表进行json格式的编码(可以这么理解,json.dumps()函数是将字典转化为字符串)


import json

# json.dumps()函数的使用,将字典转化为字符串
dict1 = {"age": "12"}
json_info = json.dumps(dict1)
print("dict1的类型:"+str(type(dict1)))
print("通过json.dumps()函数处理:")
print("json_info的类型:"+str(type(json_info)))

运行截图:
在这里插入图片描述


(2) json.loads()函数是将json格式数据转换为字典(可以这么理解,json.loads()函数是将字符串转化为字典)


import json

# json.loads函数的使用,将字符串转化为字典
json_info = '{"age": "12"}'
dict1 = json.loads(json_info)
print("json_info的类型:"+str(type(json_info)))
print("通过json.dumps()函数处理:")
print("dict1的类型:"+str(type(dict1)))

运行截图:
在这里插入图片描述


2. json.dump()和json.load()主要用来读写json文件函数(可以理解为操作文件)


(1)一般将获取到的内容放在json文件中


这就用到了json.dump将python的list或dict数据放入json文件中

格式:

json.dump(python的dict或list,fp'json文件')

例子:

with open('guba.json','w',encoding='utf-8') as fp:
        json.dump(info,fp)

运行截图:
在这里插入图片描述


(2)当我们要读取json文件的时候使用到json.load将json文件转换成python的list或dict


格式:

json.load(fp'json文件')

例子:

with open('guba.json','r') as fp:
    guba_list = json.load(fp)
    for one in guba_list:
        print(one)

运行截图:
在这里插入图片描述


总结:不管是dump还是load,带s的都是和字符串(数据)相关的,不带s的都是和文件相关的。


二、使用正则抓取数据案例


  • 总结:用正则筛选数据,有个原则:不断缩小筛选访问

1. 案例:猫眼电影


  • 需求:
  1. 电影名称
  2. 主演
  3. 上映时间
  4. 评分
  • 代码:
import requests,re,json



class Cat_moive():
    def __init__(self,url):
        self.url = url
        self.movie_list=[]
        self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'}
        ## 调用自己的parse方法
        self.parse()
    def parse(self):
        ## 爬取页面的代码
        # 1. 发送请求,获取响应
        # 分页
        for i in range(10):
            url = self.url+'?offset={}'.format(i*10)
            response = requests.get(url,headers = self.headers)
            # print(response.text)
            """
            1. 电影名称
            2. 主演
            3. 上映时间
            4. 评分
            """

            ## 用正则筛选数据,有个原则:不断缩小筛选访问
            dl_pattern = re.compile(r'<dl class="board-wrapper">(.*?)</dl>',re.S)
            dl_content = dl_pattern.search(response.text).group()
            # print(dl_content)
            dd_pattern = re.compile(r'<dd>(.*?)</dd>', re.S)
            dd_list = dd_pattern.findall(dl_content)
            # print(dd_list)
            for dd in dd_list:
                item = {}
                ## 拿电影名称
                movie_pattern = re.compile(r'title="(.*?)" class=', re.S)
                movie_name = movie_pattern.search(dd).group(1)
                # print(movie_name)
                ## 拿演员
                actor_pattern = re.compile(r'<p class="star">(.*?)</p>', re.S)
                actor = actor_pattern.search(dd).group(1).strip()
                # print(actor)
                ## 上映时间
                play_time_pattern = re.compile(r'<p class="releasetime">(.*?):(.*?)</p>')
                play_time = play_time_pattern.search(dd).group(2).strip()
                # print(play_time)

                ## 评分
                grade_pattern = re.compile(r'<i class="integer">(.*?)</i><i class="fraction">(.*?)</i>',re.S)
                grade1 = grade_pattern.search(dd).group(1)
                grade2 = grade_pattern.search(dd).group(2)
                grade = grade1+grade2
                # print(grade)

                item["movie_name"]=movie_name
                item["actor"]=actor
                item["play_time"]=play_time
                item["grade"]=grade
                self.movie_list.append(item)
        # print(self.movie_list)
        ## 将电影信息保存到json文件中
        with open ('movie.json','w',encoding='utf-8') as fp:
            json.dump(self.movie_list,fp)


if __name__ == '__main__':
    base_url = 'https://maoyan.com/board/4'
    Cat_moive(base_url)
    with open('movie.json', 'r') as fp:
        movie_list = json.load(fp)
    # print(movie_list)
    for item in movie_list:
        print(item)
  • 运行结果:
    在这里插入图片描述

2. 案例:股吧


  • 需求:
    1. 阅读数
    2. 评论数
    3. 标题
    4. 作者
    5. 更新时间
    6. 详情页的url
  • 代码:
import json

import requests,re

# 确定url
base_url = 'http://guba.eastmoney.com/default,99_%s.html'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'}

for i in range(1,13):
    response = requests.get(base_url %i,headers=headers)
    # print(response.text)
    """
    阅读数
    评论数
    标题
    作者
    更新时间
    详情页的url
    """
    ## 获取ul
    ul_pattern = re.compile(r'<ul class="newlist" tracker-eventcode="gb_xgbsy_ lbqy_rmlbdj">(.*?)</ul>',re.S)
    ul_content = ul_pattern.search(response.text)
    if ul_content:
        ul_content = ul_content.group()
    ## 获取所有li
    li_pattern = re.compile(r'<li>(.*?)</li>', re.S)
    li_list = li_pattern.findall(ul_content)
    # print(ul_content)
    info = []
    for li in li_list:
        item = {}
        reader_pattern = re.compile(r'<cite>(.*?)</cite>',re.S)
        info_list = reader_pattern.findall(li)
        # print(info_list)
        read_num = ''
        comment_num = ''
        ## 获取阅读数和评论数
        if info_list:
            read_num = info_list[0].strip()
            comment_num = info_list[1].strip()
        # print(read_num,comment_num)
        ## 获取标题
        title_pattern = re.compile(r'title="(.*?)" class="note"',re.S)
        title = title_pattern.search(li).group(1)
        # print(title)
        ## 获取作者
        author_pattern = re.compile(r'target="_blank"><font>(.*?)</font>',re.S)
        author = author_pattern.search(li).group(1)
        # print(author)
        ## 获取时间
        time_pattern = re.compile(r'<cite class="last">(.*?)</cite>',re.S)
        time = time_pattern.search(li).group(1)
        # print(time)
        ## 获取详情页
        datail_pattern = re.compile(r'</em> <a href="(.*?)" title=',re.S)
        datail_url = datail_pattern.search(li)
        if datail_url:
            datail_url ='http://guba.eastmoney.com' + datail_url.group(1)
        else:
            datail_url=''
        # print(datail_url)

        ##加入字典中
        item['title'] = title
        item['read_num'] = read_num
        item['comment_num'] = comment_num
        item['author'] = author
        item['time'] = time
        item['datail_url'] = datail_url
        info.append(item)


    # 保存成json文件
    with open('guba.json','w',encoding='utf-8') as fp:
        json.dump(info,fp)

## 查看json文件中的列表
with open('guba.json','r') as fp:
    guba_list = json.load(fp)
    for one in guba_list:
        print(one)
  • 运行结果:
    在这里插入图片描述

3. 将匹配正则函数封装成面向对象


(1)案例:股吧

  • 要求:
    “”"
    阅读数
    评论数
    标题
    作者
    更新时间
    详情页的url
    “”"
  • 代码:
import json
import requests,re
class Guba:
    def __init__(self,url):
        self.url = url
        ## 存放所有信息
        self.info = []
        self.parse()
    def get_content(self,url):
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'}

        response = requests.get(url,headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    def parse(self):
        for i in range(1, 13):
            content = self.get_content(self.url %i)
           
            ## 获取ul
            ul_pattern = re.compile(r'<ul class="newlist" tracker-eventcode="gb_xgbsy_ lbqy_rmlbdj">(.*?)</ul>', re.S)
            ul_content = ul_pattern.search(content)
            if ul_content:
                ul_content = ul_content.group()
            ## 获取所有li
            li_pattern = re.compile(r'<li>(.*?)</li>', re.S)
            li_list = li_pattern.findall(ul_content)
            # print(ul_content)
            for li in li_list:
                item = {}
                reader_pattern = re.compile(r'<cite>(.*?)</cite>', re.S)
                info_list = reader_pattern.findall(li)
                # print(info_list)
                read_num = ''
                comment_num = ''
                ## 获取阅读数和评论数
                if info_list:
                    read_num = info_list[0].strip()
                    comment_num = info_list[1].strip()
                # print(read_num,comment_num)
                ## 获取标题
                title_pattern = re.compile(r'title="(.*?)" class="note"', re.S)
                title = title_pattern.search(li).group(1)
                # print(title)
                ## 获取作者
                author_pattern = re.compile(r'target="_blank"><font>(.*?)</font>', re.S)
                author = author_pattern.search(li).group(1)
                # print(author)
                ## 获取时间
                time_pattern = re.compile(r'<cite class="last">(.*?)</cite>', re.S)
                time = time_pattern.search(li).group(1)
                # print(time)
                ## 获取详情页
                datail_pattern = re.compile(r'</em> <a href="(.*?)" title=', re.S)
                datail_url = datail_pattern.search(li)
                if datail_url:
                    datail_url = 'http://guba.eastmoney.com' + datail_url.group(1)
                else:
                    datail_url = ''
                # print(datail_url)

                ##加入字典中
                item['title'] = title
                item['read_num'] = read_num
                item['comment_num'] = comment_num
                item['author'] = author
                item['time'] = time
                item['datail_url'] = datail_url
                self.info.append(item)

if __name__ == '__main__':
    # 确定url
    base_url = 'http://guba.eastmoney.com/default,99_%s.html'
    g = Guba(base_url)

    # 保存成json文件
    with open('guba1.json','w',encoding='utf-8') as fp:
        json.dump(g.info,fp)

## 查看json文件中的列表
with open('guba1.json','r') as fp:
    guba_list = json.load(fp)
    for one in guba_list:
        print(one)
  • 运行结果:
    在这里插入图片描述

(2)案例:药网

  • 需求:
    1. 总价
    2. 描述
    3. 评论数量
    4. 详情页链接
  • 代码:
import json

import requests,re
class Yaowang:
    def __init__(self,url):
        self.url = url
        self.info = []
        self.parse()

    def get_content(self,url):
        headers={'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'}
        response = requests.get(url,headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    def parse(self):
        for i in range(1,51):
            content = self.get_content(self.url+'/categories/953710-j%s.html' %i)
            """
            总价,
            描述,
            评论数量,
            详情页链接
            """
            ul_pattern = re.compile(r'<ul id="itemSearchList" class="itemSearchList">(.*?)</ul>',re.S)
            ul_content = ul_pattern.search(content).group(1)
            li_list_pattern = re.compile(r'<li id="producteg_(.*?)</li>',re.S)
            li_list = li_list_pattern.findall(ul_content)

            if li_list:
                for li in li_list:
                    item = {}
                    total_pattern = re.compile(r'<span>(.*?)</span>',re.S)
                    total = total_pattern.search(li).group(1).strip()
                    # print(total)
                    description_pattern = re.compile(r' <span class=" list_lable_self"></span>(.*?)</a>',re.S)
                    description = description_pattern.search(li)
                    if description:
                        description = description.group(1).strip()
                    else:
                        description = ''
                    # print(description)
                    comment_pattern = re.compile(r'评论 <em>(.*?)</em>条',re.S)
                    comment = comment_pattern.search(li)
                    # print(comment)
                    if comment:
                        comment = comment.group(1)
                    else:
                        comment = ''
                    detail_pattern = re.compile(r' " href="//www.111.com.cn(.*?)"',re.S)
                    detail_url = detail_pattern.search(li).group(1)
                    detail_url = self.url + detail_url
                    # print(detail_url)
                    item['total']=total
                    item['description']=description
                    item['comment']=comment
                    item['detail_url']=detail_url
                    self.info.append(item)


if __name__ == '__main__':
    base_url = 'https://www.111.com.cn'
    yw = Yaowang(base_url)
    with open('yw.json','w',encoding='utf-8') as fp:
        json.dump(yw.info,fp)

with open('yw.json','r') as fp:
    info_list = json.load(fp)
    for one in info_list:
        print(one)

  • 运行结果:
    在这里插入图片描述

发布了107 篇原创文章 · 获赞 43 · 访问量 7067
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章