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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章