解析document文档中script方式获取抖音无水印视频

查看 85|回复 8
作者:niwajiang   
思路分析

[ol]
  • 使用 playwright 模拟浏览器打开分享链接
  • 获取 播放页面 html 信息
  • 解析 播放页面的 video标签,video标签的src属性就是视频的地址
    [ol]
  • 这种模式会触发抖音的风控机制
    [/ol]
  • 解析页面 获取相关cookie
  • 使用cookie请求页面文档
  • 解析文档内容其中就有播放地址
    [/ol]

    playwright 入门使用介绍
    简单使用如下。这种模式会触发抖音的风控机制,出现验证码中间页。


    image-20230318171402213.png (152.56 KB, 下载次数: 0)
    下载附件
    2023-3-21 11:10 上传

    # 抖音分享链接
    share_url = 'https://v.douyin.com/SGGxvfM/'
    # 创建浏览器打开分享地址
    # 因为可能会触发抖音的风控机制,所以这里先设置为有头模式,当触发验证码中间页时,手动处理下
    browser = sync_playwright().start().chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto(share_url)
    # 获取标签及视频播放地址
    page.wait_for_load_state()
    video = page.wait_for_selector('video')
    print(video)
    source = video.query_selector_all('source')
    video_src = source[0].get_attribute("src")
    video_src = 'https:' + video_src
    print(video_src)
    file_name = 'result.mp4'
    print('开始下载视频...')
    response = requests.get(video_src, stream=True)
    with open(file_name, "wb") as file:
        file.write(response.content)
    print('下载完成')
    另辟出路
    因为会触发中间验证页,虽然也可以使用 playwright 处理验证码,但是速度慢,同时验证方式更改就得更改总之不好。
    背景信息
    分享短链地址 :https://v.douyin.com/SGGxvfM/
    重定向后的实际地址:https://www.douyin.com/video/7210719593298464003
    流程:抖音的短链经过重定向后才会得到实际地址
    中间过程就会拿到服务器写回的cookie信息
    实际地址的请求是个document类型的内容,重点来了:document里的script标签的ID是RENDER_DATA,type是application/json,把标签里内容解码一下果然是我们想要的内容。
    截图如下


    image-20230321100158808.png (249.5 KB, 下载次数: 0)
    下载附件
    2023-3-21 11:10 上传



    image-20230321100549151.png (579.19 KB, 下载次数: 0)
    下载附件
    2023-3-21 11:11 上传



    image-20230321100735851.png (898.79 KB, 下载次数: 0)
    下载附件
    2023-3-21 11:11 上传

    处理逻辑
    有了上面的背景信息,那处理逻辑也很简单了。
    [ol]
  • 使用 playwright 进行打开分享地址
  • 获取cookie信息
  • 请求实际地址内容
  • 获取script标签内容
  • 解析script标签内容里json信息并获取相关字段
    [/ol]
    import json
    import re
    import requests
    from playwright.sync_api import sync_playwright
    from bs4 import BeautifulSoup
    from urllib.parse import unquote
    share_url = 'https://v.douyin.com/SGGxvfM/'
    browser = sync_playwright().start().chromium.launch(headless=True)
    context = browser.new_context()
    page = context.new_page()
    page.goto(share_url)
    cookies = page.context.cookies()
    result_cookie = ''
    for item in cookies:
        if item['name'] == '__ac_nonce':
            # document_header['__ac_nonce'] = item['value']
            result_cookie = result_cookie + '__ac_nonce=' + item['value'] + ';'
        if item['name'] == '__ac_signature':
            result_cookie = result_cookie + '__ac_signature=' + item['value'] + ';'
    document_header = {
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'same-origin',
        'sec-ch-ua-platform': 'macOS',
        'sec-ch-ua': '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
        'sec-ch-ua-mobile': '?0',
        'upgrade-insecure-requests': '1',
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        'cookie': result_cookie
    }
    # print(page.url)
    url = page.url
    # url = 'https://www.iesdouyin.com/share/video/7210719593298464003/?region=CN&mid=7210720503894805308&u_code=33j73e481hda&did=MS4wLjABAAAAyWxE53gU-qg10uh4jIbo0XpO2_I8z5fpPlI_pBAlio7gocacNdKp0p4KSAydSgC_&iid=MS4wLjABAAAALt7iss0DroHh-NMLV6ZFi-4uYP-lTU-NqsBOH3GQxng6bxW6xVoJ7AHXunv0YjHv&with_sec_did=1&titleType=title&from_ssr=1&timestamp=1678941771&utm_campaign=client_share&app=aweme&utm_medium=ios&tt_from=copy&utm_source=copy'
    search_result = re.search('https://www.iesdouyin.com/share/video/(.+?)/', url)
    video_id = search_result.group(1)
    video_url = 'https://www.douyin.com/video/' + video_id + '?previous_page=app_code_link'
    video_detail_response = requests.get(video_url, headers=document_header)
    soup = BeautifulSoup(video_detail_response.text)
    encode_data = soup.find('script', {'id': 'RENDER_DATA'}).get_text()
    decode_data = unquote(encode_data)
    decode_data = json.loads(decode_data)
    video_url = decode_data['44']['aweme']['detail']['video']['playAddr'][0]['src']
    video_src = 'https:' + video_url
    print(video_src)
    file_name = 'result.mp4'
    print('开始下载视频...')
    response = requests.get(video_src, stream=True)
    with open(file_name, "wb") as file:
        file.write(response.content)
    print('下载完成')
    额外其他
    可以包装成接口对外使用了,上次发了试用的小程序,不符合版规被删帖了这次就不发了。

    地址, 下载次数

  • Jason584521   

    学到了感谢楼主!!!!
    wfghim   

    感谢楼主,我用c#写了一版,用python才写了一半。可以偷个懒了。
    [Python] 纯文本查看 复制代码import requests
    from urllib.parse import quote, unquote, urlencode
    import re
    smaillUrl="3.35 Ymd:/ 复制打开抖音,看看【潇湘晨报的作品】没有一口狗粮是白吃的!狗子下楼帮主人拿快递,主人:... https://v.douyin.com/Sa7ecJa/"
    matchObj = re.search(r'(https?.*?)(?=http|$||\\s|,)', smaillUrl, re.M | re.I)
    vidnum=''
    if (matchObj != None):
        obj1 = matchObj.group(1)
        obj1 = obj1.replace('\"', '')
        firstrequest = requests.get(obj1,verify=False)
        if (firstrequest.status_code == 200):
            vidnum = re.sub(r'\D', "", firstrequest.url)[0:19]
            print(vidnum,firstrequest.url)
    s=requests.options(
    url="https://www.douyin.com/video/"+vidnum,
    headers={
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69",
        "Connection":"keep-alive"
        })
    print(s.status_code)
    print((s.content))
    Simpleton   

    感谢分享
    wangL0   

    好强,学习了
    aa2923821a   

    谢谢 刚好需要,
    kerwenfly   

    playwright 不用图形化可以实现吗?
    Ninkror   

    牛牛牛感谢分享
    niwajiang
    OP
      


    kerwenfly 发表于 2023-3-21 11:59
    playwright 不用图形化可以实现吗?

    就是不用图形化
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部