Python(六十六)json模块、抖音视频无水印提取

1. json模块

05_json模块、抖音视频无水印提取/01_json模块1.py:

"""

    爬虫中数据分类:
        结构化数据:
            json、xml
        非结构化数据:html
            处理方法:正则表达式、xpath、css选择器
    json模块是Python内置模块

"""

"""

    JSON的判断标准:
        1. JSON不允许key为元组,但是Python的字典允许
        2. JSON中没有单引号的存在
    
    json.dumps()转JSON格式的字符串
    
    NOT JSON:
        {'a': 'A', 'c': 'C', 'b': 'B', ('2', 1): '元组', 22: '数字'}
    YES JSON:
        {"a": "A", "c": "C", "b": "B", "22": "数字"}

"""

import json

dict2 = {
    "name":"Tom","age":23
}
print(str(dict2))   # 打印{'name': 'Tom', 'age': 23},虽然可以 但不是json格式,不是json类型

data1 = json.dumps(dict2)       # 转json格式的字符串
print(data1)        # 打印{"name": "Tom", "age": 23}
print(type(data1))      # 字符串类型<class 'str'>

print("------------")

data2 = json.dumps([])
print(data2)        # 打印[]
print(type(data2))      # 打印<class 'str'>

data3 = json.dumps(2)
print(type(data3))      # 打印<class 'str'>

data4 = json.dumps("3")
print(type(data4))      # 打印<class 'str'>

data = {
    "a":"A","c":"C","b":"B"
}
print("排序:",json.dumps(data,sort_keys=True))
print("缩进:",json.dumps(data,indent=3))
print("紧凑:",json.dumps(data,separators=(',',':')))      # 把, 换成,;把: 换成:。

data[('2',1)] = "元组"
print(data)     # 打印{'a': 'A', 'c': 'C', 'b': 'B', ('2', 1): '元组'}

data[22] = "数字"
# data[[1,2]] = "数组"      # 字典的key不能为数组
print(data)
print(json.dumps(data,skipkeys=True))        # skipkeys 跳过异常过滤
print(json.dumps(data,skipkeys=True,ensure_ascii=False))        # skipkeys:跳过异常过滤;ensure_ascii:解决编码问题。


with open("test.json","w",encoding='utf-8') as fp:
    # fp.write(str(data))      # 可以写入,但不是json格式,这里传的data是字典
    # fp.write(json.dumps(data,skipkeys=True,ensure_ascii=False))

    # 与fp.write()作用差不多
    json.dump(data,fp,skipkeys=True,ensure_ascii=False)

05_json模块、抖音视频无水印提取/02_json模块2.py:

"""

    总结:
        json.dumps() 将 Python对象编码成 JSON字符串,严格按照JSON格式进行转换:PythonDict -> jsonStr
        json.loads() 将 已编码的 JSON字符串解码为Python对象 jsonStr -> PythonDict
        json.dump() 和 json.load(),需要传入文件描述符,加上文件操作

"""

import json

dict2 = '{"name":"Tom","age":23}'       # 必须要是json格式的字符串
data1 = json.loads(dict2)       # 将字符串还原为Python——字典dict
print(data1)

with open("test.json",'r',encoding='utf-8') as fp:
    print(fp.read())    # {"a": "A", "c": "C", "b": "B", "22": "数字"}
    print(type(fp.read()))      # <class 'str'>
    fp.seek(0)      # 光标移动到最前面
    data2 = json.loads(fp.read())       # 转成了Python可以操作的字典
    print(data2['22'],type(data2))      # 打印:数字 <class 'dict'>
    fp.seek(0)
    print(json.load(fp))      # {'a': 'A', 'c': 'C', 'b': 'B', '22': '数字'}

2. jsonpath模块

05_json模块、抖音视频无水印提取/03_jsonpath.py:

"""

    pip install jsonpath
        用来解析多层嵌套的json数据:jsonpath是一种信息抽取库
        
"""
import jsonpath

data = {
    "price":666,
    "store":{
        "author":"Lonelyroots",
        "product":"washing_machine",
        "price":5.5,
        "book":[{
            "category":"reference",
            "author":"Nigel Rees",
            "title":"Sayings of the Century",
            "price":8.95
        },{
            "category":"reference",
            "author":"Nigel Rees",
            "title":"Sayings of the Century",
            "price":12.99
        },{
            "category":"fiction",
            "author":"Herman Melville",
            "title":"Moby Dick",
            "isbn": "0-553-21311-3",
            "price":8.99
        },{
            "category":"fiction",
            "author":"Nigel Rees",
            "title":"Sayings of the Century",
            "isbn":"0-395-19395-8",
            "price":22.99
        }],
        "bicycle":{
            "color":"red",
            "price":19.95
        }
    }
}

print(data['store']['book'][0]['price'])    # 打印8.95
print(jsonpath.jsonpath(data,'$..price'))   # 所有price节点,打印[666, 5.5, 8.95, 12.99, 8.99, 22.99, 19.95]
print(jsonpath.jsonpath(data,'$.store.book[*].price'))   # book的所有price节点,两个点(使用时表示不知道有多少层),打印[8.95, 12.99, 8.99, 22.99]
print(jsonpath.jsonpath(data,'$.price'))   # 打印第一层节点,打印[666]
print(jsonpath.jsonpath(data,'$.store.*'))   # 打印store下的所有节点
print(jsonpath.jsonpath(data,'$.store..price'))   # 打印[5.5, 8.95, 12.99, 8.99, 22.99, 19.95]
print(jsonpath.jsonpath(data,'$..book[3]'))   # 打印[{'category': 'fiction', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'isbn': '0-395-19395-8', 'price': 22.99}]
print(jsonpath.jsonpath(data,'$..book[(@.length-1)]'))   # 匹配倒数第一个book节点(写法一),打印[{'category': 'fiction', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'isbn': '0-395-19395-8', 'price': 22.99}]
print(jsonpath.jsonpath(data,'$..book[-1:]'))   # 匹配倒数第一个book节点(写法二),打印[{'category': 'fiction', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'isbn': '0-395-19395-8', 'price': 22.99}]
print(jsonpath.jsonpath(data,'$..book[:2]'))   # 匹配book的0与1节点,打印[{'category': 'reference', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'price': 8.95}, {'category': 'reference', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'price': 12.99}]
print(jsonpath.jsonpath(data,'$..book[?(@.isbn)]'))   # 匹配book中包含isbn的节点,打印[{'category': 'fiction', 'author': 'Herman Melville', 'title': 'Moby Dick', 'isbn': '0-553-21311-3', 'price': 8.99}, {'category': 'fiction', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'isbn': '0-395-19395-8', 'price': 22.99}]
print(jsonpath.jsonpath(data,'$..book[?(@.price<10)]'))   # 匹配book中price小于10的节点,打印[{'category': 'reference', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'price': 8.95}, {'category': 'fiction', 'author': 'Herman Melville', 'title': 'Moby Dick', 'isbn': '0-553-21311-3', 'price': 8.99}]

3. 抖音视频无水印提取

05_json模块、抖音视频无水印提取/04_抖音无水印视频提取.py:

"""
    
    抖音无水印视频提取:(分享链接)
        https://v.douyin.com/JcWgevN/
        https://v.douyin.com/JcWBkvA/

    通过分享链接进入,刷新抓取Media路由
    https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f670000c09rpp10r57bgg9sijlg&ratio=720p&line=0
    https://aweme.snssdk.com/aweme/v1/playwm/?video_id=vodeof6fo000co9tu3c8bl9edene3td0&ratio=720p&line=0
    
    分析1:
        我们通过直接访问分享链接返回的内容中,没有我们需要的数据
    分析2:
        【只要页面上有数据,且不在正常的页面中,那么这个数据肯定存在于某个请求中】
        上面得知,直接访问链接是没用的,所以我们需要利用抓包工具,抓取到一个json数据中有我们需要的数据
        https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=6923085141166361870
        https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=6923122237490924815
        从两个URL可以看出,只有items_ids是不一样的,由此可以推测可能是视频的唯一ID        
    分析3:
        上面URL中items_ids参数是未知的,所以我们需要从别的地方找到一样的items_ids
        在分析1中,我们可以发现,html返回的内容对我们没用,但是!!重定向之后的URL中有分析2中需要的参数
    分析4:
        获取到视频的JsonUrl之后,我们就可以获取json数据
        再从JSON数据中找到videoURL
    分析5:
        通过上面拿到视频URL之后,我们发现这个视频还是有水印的!!!
        但是!!!我们只要把URL中的 playwm 改成 play 就没有水印了,(之前抖音内部人员透露的,不然我们发现不了),如下方链接:
        Google访问不了,Firefox可以访问
        修改前(有水印):https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f670000c09rpp10r57bgg9sijlg&ratio=720p&line=0
        修改后(无水印):https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300f670000c09rpp10r57bgg9sijlg&ratio=720p&line=0

"""
from requests_html import HTMLSession
import re
from jsonpath import jsonpath
import json

session = HTMLSession()
shareUrl = "https://v.douyin.com/JcWgevN/"
response = session.get(url=shareUrl)
# print(response.text)      # html对我们没用,将运行结果复制粘贴到 文件04_抖音无水印提取视频.html
PageUrl = response.url     # 把重定向的路由拿出来
# print(PageUrl)      # https://www.douyin.com/video/6923085141166361870?previous_page=app_code_link
videoId = re.search('https://www.douyin.com/video/(.*?)\?previous_page=app_code_link',PageUrl).group(1)

JsonUrl = "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids={}".format(videoId)
# print(JsonUrl)

# jsonData = session.get(url=JsonUrl).text      # json形式的字典 <class 'str'>,将运行结果复制粘贴到 文件04_抖音无水印提取视频.json
# jsonData = json.loads(jsonData)     # Python Dict 类型:<class 'dict'>
# 等价于
jsonData = session.get(url=JsonUrl).json()      # 将已编码的JSON字符串解码为Python对象,Python Dict 类型:<class 'dict'>

# 在 04_抖音无水印提取视频.json 文件中Ctrl+F搜索视频Media路由的唯一id:v0300f670000c09rpp10r57bgg9sijlg
videoUrl = jsonpath(jsonData,'$..video.play_addr.url_list')[0][0]
# print(videoUrl)
videoTitle = jsonpath(jsonData,'$..item_list..desc')[0]
# print(videoTitle)
videoUrl = videoUrl.replace("playwm","play")

# 下载视频
headers = {
    'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                 'Chrome/98.0.4758.102 Mobile Safari/537.36 '
}
responseVideo = session.get(url = videoUrl,headers=headers)
with open('./video/'+videoTitle+'.mp4','wb') as f:
    f.write(responseVideo.content)
print("----------{}下载完成--------------".format(videoTitle))

文章到这里就结束了!希望大家能多多支持Python(系列)!六个月带大家学会Python,私聊我,可以问关于本文章的问题!以后每天都会发布新的文章,喜欢的点点关注!一个陪伴你学习Python的新青年!不管多忙都会更新下去,一起加油!

Editor:Lonelyroots

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容