我的工具箱-第1个工具抖音视频解析下载

准备

网站的模板我用的是it-tool。里面包含了编程常用的工具。在这个基础上咱们开始做自己需要的工具
github地址是:https://github.com/angelofan/it-tools-zh_CN
大致内容是这样的。感兴趣的小伙伴可以自己下载研究一下。
在这里插入图片描述

预览

先看下咱自己做的抖音视频解析
在这里插入图片描述
前端项目的代码咱就不说了。都是一些常规操作。主要说下抖音视频获取的办法和我踩得坑。

分析和确认方案

思路

  1. 是直接找到抖音网页上的接口直接模拟请求获取数据
  2. 通过 selenium 模拟浏览器,获取html结果直接获取数据

探索

地址:https://v.douyin.com/iN3qDq61/ (抖音上的分享复制链接获取地址)
咱们先百度一波发现网上的地址都不能用。只能自己来一波了。

在这里插入图片描述
在这里插入图片描述
发现这个地址就是请求的接口,但是这个玩意请求参数太多,而且经过多次测试这个里面的参数获取的方式有点费劲。因为视频的链接是进过重定了2次,而且js是加密的不太好弄。
进过一番探索发现用浏览器用手机模式可以直接获取对应的数据。
在这里插入图片描述
这里的 RENDER_DATA 解密后会得到一个json

{
  "_location": "/share/video/7233468052229131557",
  "app": {
    "appName": "safari",
    "commonContext": {
      "appName": "safari",
      "host": "m.douyin.com",
      "isNotSupportWebp": false,
      "isSpider": false,
      "lastPath": "7233468052229131557",
      "renderInSSR": 1,
      "ua": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Mobile Safari/537.36",
      "webId": "7341415984303818255"
    },
    "host": "m.douyin.com",
    "isNotSupportWebp": false,
    "isSpider": false,
    "itemId": "7233468052229131557",
    "lastPath": "7233468052229131557",
    "query": {},
    "renderInSSR": 1,
    "ua": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Mobile Safari/537.36",
    "videoInfoRes": {
      "extra": {
        "logid": "202403031933523EB1646F5CF7EE23B16F",
        "now": 1709465632955
      },
      "filter_list": [],
      "item_list": [
        {
          "author": {
            "avatar_medium": {
              "uri": "100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b",
              "url_list": [
                "https://p3.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p9.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p6.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172"
              ]
            },
            "avatar_thumb": {
              "uri": "100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b",
              "url_list": [
                "https://p3.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p9.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p6.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172"
              ]
            },
            "card_entries": null,
            "favoriting_count": 0,
            "follow_status": 0,
            "followers_detail": null,
            "following_count": 0,
            "geofencing": null,
            "mix_info": null,
            "mplatform_followers_count": 0,
            "nickname": "罗弗官方旗舰店",
            "platform_sync_info": null,
            "policy_version": null,
            "sec_uid": "MS4wLjABAAAA_UQlh43aKCGkisLV8tW6pHWA2tbPa2sDLOiAK6Vz5GI",
            "short_id": "926481386",
            "signature": "这里是罗弗官方直播间,感谢您的关注!~\n坚持品质!用心服务!\n直播时间:9:00 开播✨☀️\n实力宠粉!力推好品!",
            "type_label": null,
            "unique_id": ""
          },
          "aweme_id": "7233468052229131557",
          "cha_list": null,
          "chapter_list": null,
          "comment_list": null,
          "create_time": 1684173032,
          "desc": "为了不让宝宝看电视玩手机,我又淘了好多粘土,给她一包能玩一下午,妥妥的哄娃神器#超轻粘土 #母婴好物",
          "geofencing": null,
          "group_id_str": "7233468052229131557",
          "image_infos": null,
          "images": null,
          "img_bitrate": null,
          "interaction_stickers": null,
          "label_top_text": null,
          "long_video": null,
          "music": {
            "author": "罗弗官方旗舰店",
            "cover_hd": {
              "uri": "1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b",
              "url_list": [
                "https://p3.douyinpic.com/aweme/1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p9.douyinpic.com/aweme/1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p6.douyinpic.com/aweme/1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172"
              ]
            },
            "cover_large": {
              "uri": "1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b",
              "url_list": [
                "https://p3.douyinpic.com/aweme/1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p9.douyinpic.com/aweme/1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p6.douyinpic.com/aweme/1080x1080/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172"
              ]
            },
            "cover_medium": {
              "uri": "720x720/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b",
              "url_list": [
                "https://p3.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p6.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172",
                "https://p9.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b.jpeg?from=116350172"
              ]
            },
            "cover_thumb": {
              "uri": "168x168/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b",
              "url_list": [
                "https://p3.douyinpic.com/img/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b~c5_168x168.jpeg?from=116350172",
                "https://p6.douyinpic.com/img/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b~c5_168x168.jpeg?from=116350172",
                "https://p9.douyinpic.com/img/aweme-avatar/tos-cn-i-0813_ad02b40232b94f8da187252b7b68882b~c5_168x168.jpeg?from=116350172"
              ]
            },
            "duration": 18,
            "mid": "7233468094868572965",
            "position": null,
            "status": 1,
            "title": "@罗弗官方旗舰店创作的原声一罗弗官方旗舰店"
          },
          "promotions": null,
          "risk_infos": {
            "content": "",
            "reflow_unplayable": 0,
            "type": 0,
            "warn": false
          },
          "statistics": {
            "aweme_id": "7233468052229131557",
            "collect_count": 7545,
            "comment_count": 210,
            "digg_count": 17536,
            "play_count": 0,
            "share_count": 1545
          },
          "text_extra": [],
          "video": {
            "bit_rate": null,
            "cover": {
              "uri": "tos-cn-v-c9e10a/oYSe4IBfEQ5NhKGEDbFliImIkqmYcnZaYBDgDA",
              "url_list": [
                "https://p6-sign.douyinpic.com/tos-cn-v-c9e10a/oYSe4IBfEQ5NhKGEDbFliImIkqmYcnZaYBDgDA~c5_300x400.webp?x-expires=1710673200&x-signature=CFXNxrYZgNjHm6n5zcR0H2CXJF8%3D&from=3213915784_large&s=PackSourceEnum_DOUYIN_REFLOW&se=false&sc=cover&biz_tag=aweme_video&l=202403031933523EB1646F5CF7EE23B16F",
                "https://p3-sign.douyinpic.com/tos-cn-v-c9e10a/oYSe4IBfEQ5NhKGEDbFliImIkqmYcnZaYBDgDA~c5_300x400.webp?x-expires=1710673200&x-signature=3AHv9EpqyVEarAl582IIf1Y%2BTTE%3D&from=3213915784_large&s=PackSourceEnum_DOUYIN_REFLOW&se=false&sc=cover&biz_tag=aweme_video&l=202403031933523EB1646F5CF7EE23B16F",
                "https://p9-sign.douyinpic.com/tos-cn-v-c9e10a/oYSe4IBfEQ5NhKGEDbFliImIkqmYcnZaYBDgDA~c5_300x400.webp?x-expires=1710673200&x-signature=M0%2BTP1Y6cAaORFBB3T8YGfogC24%3D&from=3213915784_large&s=PackSourceEnum_DOUYIN_REFLOW&se=false&sc=cover&biz_tag=aweme_video&l=202403031933523EB1646F5CF7EE23B16F",
                "https://p6-sign.douyinpic.com/tos-cn-v-c9e10a/oYSe4IBfEQ5NhKGEDbFliImIkqmYcnZaYBDgDA~c5_300x400.jpeg?x-expires=1710673200&x-signature=nkunvkyr5RlCTWExCp2cCME%2BA3g%3D&from=3213915784_large&s=PackSourceEnum_DOUYIN_REFLOW&se=false&sc=cover&biz_tag=aweme_video&l=202403031933523EB1646F5CF7EE23B16F"
              ]
            },
            "height": 640,
            "play_addr": {
              "uri": "v02033g10000chh71q7og65sct6i7380",
              "url_list": [
                "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v02033g10000chh71q7og65sct6i7380&ratio=720p&line=0"
              ]
            },
            "width": 360
          },
          "video_labels": null,
          "video_text": null
        }
      ],
      "status_code": 0
    },
    "webId": "7341415984303818255"
  }
}

在这里插入图片描述
这个就是这个地址对应的视频地址。然后根据前辈们的经验,把playwm 换成 play 就是无水印。但是这个时候又一个问题诞生了。就是这个地址不一定好用。有时候会404。这里鉴于pc版参数复杂。咱们直接用 selenium 模拟去。

确认方案

1.首先通过程序模拟手机浏览器,获取到对应的数据。
2.使用程序测试对应的 视频地址 是不是正常可以使用。
3.如果可以就直接返回,如果不行就使用 selenium 模拟一次(由于pc的比较复杂咱就是为了拿个地址不必要去在搞js逆向啥的)。
缺点也是明显的。如果遇到的视频地址404。再用 selenium 是比较慢的。不过也还好。个人可以接受

代码实现

package com.rtaksoft.suite.freeTool.api;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.rtaksoft.core.common.page.QueryResult;
import com.rtaksoft.core.common.tools.Format;
import com.rtaksoft.frameextend.struts.context.ServiceContext;
import com.rtaksoft.suite.apimanage.trigger.ApiQueryTriggerImpl;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.openqa.selenium.By;
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author lcc
 * @description 抖音去水印
 * @since 2024/2/29 下午9:09
 **/
public class DouyinAnalysis extends ApiQueryTriggerImpl {
    public DouyinAnalysis(ServiceContext serviceContext) {
        super(serviceContext);
    }

    @Override
    public QueryResult execute() throws Exception {
        Map apiParam = this.getApiParam();
        String dy_url = Format.formatStrNullForEmpty(apiParam.get("url"));

        Console.log("接收到的url:{}",dy_url);

        //兼容提取链接(抖音复制后可以直接解析)
        Pattern pattern = Pattern.compile("(?i)\\b((?:https?)://\\S+)");
        Matcher matcher = pattern.matcher(dy_url);
        while (matcher.find()) {
            dy_url = matcher.group();
            Console.log("解析到的url:{}",dy_url);
            break;
        }

        HttpRequest get = HttpUtil.createGet(dy_url);
        //模拟手机浏览器
        get.header("user-agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Mobile Safari/537.36");
        HttpResponse execute = get.execute();
        if (execute.getStatus() == 302) {
            String url = execute.header("Location");
            URI uri = new URI(url);
            String[] split = uri.getPath().split("/");
            String vid = split[split.length - 1];

            HttpRequest get1 = HttpUtil.createGet(url);
            get1.header("user-agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Mobile Safari/537.36");

            HttpResponse execute1 = get1.execute();
            if (execute1.getStatus() == 200) {
                //RENDER_DATA
                Element renderData = Jsoup.parse(execute1.body()).getElementById("RENDER_DATA");
                JSONObject data = new JSONObject(URLUtil.decode(renderData.html(), StandardCharsets.UTF_8));
                JSONArray item_list = data.getJSONObject("app").getJSONObject("videoInfoRes").getJSONArray("item_list");
                List<Map> arr = new ArrayList<>();
                for (int i = 0; i < item_list.size(); i++) {
                    JSONObject item = item_list.getJSONObject(i);
                    System.out.println(item.toStringPretty());
                    String video_nickname = item.getJSONObject("author").getStr("nickname");
                    String video_desc = item.getStr("desc");
                    String video_dow_url = item.getJSONObject("video").getJSONObject("play_addr").getJSONArray("url_list").getStr(0).replace("playwm", "play");
                    String video_cover_dow_url = item.getJSONObject("video").getJSONObject("cover").getJSONArray("url_list").getStr(0).replace("playwm", "play");
                    Console.log("视频作者名称:{}", video_nickname);
                    Console.log("视频介绍:{}", video_desc);
                    HttpRequest get2 = HttpUtil.createGet(video_dow_url);
                    HttpResponse execute2 = get2.execute();
                    if(execute2.getStatus() == 302){
                        video_dow_url = execute2.header("Location");
                    }else if(execute2.getStatus() == 404){
                        System.setProperty("webdriver.chrome.driver", "/data/gg/chromedriver-linux64/chromedriver");
                        // Instantiate a ChromeDriver class.
                        ChromeOptions options = new ChromeOptions();
                        options.addArguments("--remote-allow-origins=*");
                        options.setPageLoadStrategy(PageLoadStrategy.NORMAL);
                        options.setBinary("/data/gg/chrome-linux64/chrome");
                        options.addArguments("--headless");
                        options.addArguments("--no-sandbox");
                        options.addArguments("--disable-gpu");
                        options.addArguments("--disable-dev-shm-usage");
                        options.addArguments("window-size=1920x3000");
                        WebDriver driver = new ChromeDriver(options);

                        // Launch Website
                        driver.get(dy_url);

                        WebDriverWait webDriverWait = new WebDriverWait(driver, 10,1);
                        webDriverWait.until(new ExpectedCondition<WebElement>() {
                            @Override
                            public WebElement apply(WebDriver driver) {
                                return driver.findElement(By.tagName("xg-video-container"));
                            }
                        });

                        List<WebElement> elements = driver.findElements(By.xpath("//*[@id=\"douyin-right-container\"]/div[2]/div/div[1]/div[2]/div/xg-video-container/video/source"));
                        for (WebElement element : elements) {
                            String src = element.getAttribute("src");
                            //检查是否可访问
                            HttpRequest get3 = HttpUtil.createGet(src);
                            HttpResponse execute3 = get3.execute();
                            if (execute3.getStatus()!=404) {
                                video_dow_url = src;
                                break;
                            }
                        }
                        driver.close();
                    }
                    Console.log("视频地址:{}", video_dow_url);
                    Console.log("视频封面地址:{}", video_cover_dow_url);
                    HashMap data_ret = new HashMap();
                    data_ret.put("nickname",video_nickname);
                    data_ret.put("desc",video_desc);
                    data_ret.put("dow_url",video_dow_url);
                    data_ret.put("cover_dow_url",video_cover_dow_url);
                    arr.add(data_ret);
                }
                return new QueryResult(){{
                   setResultList(arr);
                   setTotalRecord(arr.size());
                }};
            }
        }
        return null;
    }
}

成品体验地址

抖音视频去水印(在线)

chromedriver 和 chrome 浏览器

服务器操作系统是centos(windows的同学安装自行百度把。我电脑是深度系统。)

下载地址在这里:https://googlechromelabs.github.io/chrome-for-testing/#stable

chromedriver安装

解压到某个目录即可

安装chrome浏览器。

由于上面下载的二进制包不能直接使用缺少依赖。使用下面的脚本直接安装即可
install.sh

#! /bin/bash


# Copyright 2017-present: Intoli, LLC
# Source: https://intoli.com/blog/installing-google-chrome-on-centos/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.


# What this script does is explained in detail in a blog post located at:
# https://intoli.com/blog/installing-google-chrome-on-centos/
# If you're trying to figure out how things work, then you should visit that!


# Require that this runs as root.
[ "$UID" -eq 0 ] || exec sudo "$0" "$@"


# Define some global variables.
working_directory="/tmp/google-chrome-installation"
repo_file="/etc/yum.repos.d/google-chrome.repo"


# Work in our working directory.
echo "Working in ${working_directory}"
mkdir -p ${working_directory}
rm -rf ${working_directory}/*
pushd ${working_directory}


# Add the official Google Chrome Centos 7 repo.
echo "Configuring the Google Chrome repo in ${repo_file}"
echo "[google-chrome]" > $repo_file
echo "name=google-chrome" >> $repo_file
echo "baseurl=http://dl.google.com/linux/chrome/rpm/stable/\$basearch" >> $repo_file
echo "enabled=1" >> $repo_file
echo "gpgcheck=1" >> $repo_file
echo "gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub" >> $repo_file


# Install the Google Chrome signing key.
yum install -y wget
wget https://dl.google.com/linux/linux_signing_key.pub
rpm --import linux_signing_key.pub


# A helper to make sure that Chrome is linked correctly
function installation_status() {
    google-chrome-stable --version > /dev/null 2>&1
    [ $? -eq 0 ]
}


# Try it the old fashioned way, should work on RHEL 7.X.
echo "Attempting a direction installation with yum."
yum install -y google-chrome-stable
if [ $? -eq 0 ]
then
    if installation_status; then
        # Print out the success message.
        echo "Successfully installed Google Chrome!"
        rm -rf ${working_directory}
        popd > /dev/null
        exit 0
    fi
fi


# Uninstall any existing/partially installed versions.
yum --setopt=tsflags=noscripts -y remove google-chrome-stable


# Install yumdownloader/repoquery and download the latest RPM.
echo "Downloading the Google Chrome RPM file."
yum install -y yum-utils
# There have been issues in the past with the Chrome repository, so we fall back to downloading
# the latest RPM directly if the package isn't available there. For further details:
# https://productforums.google.com/forum/#!topic/chrome/xNtfk_wAUC4;context-place=forum/chrome
yumdownloader google-chrome-stable || \
    wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
rpm_file=$(echo *.rpm)
echo "Downloaded ${rpm_file}"


# Install the RPM in a broken state.
rpm -ih --nodeps ${rpm_file}
rm ${rpm_file}


# Install font dependencies, see: https://bugs.chromium.org/p/chromium/issues/detail?id=782161
echo "Installing the required font dependencies."
yum install -y \
    fontconfig \
    fontpackages-filesystem \
    ipa-gothic-fonts \
    xorg-x11-fonts-100dpi \
    xorg-x11-fonts-75dpi \
    xorg-x11-fonts-misc \
    xorg-x11-fonts-Type1 \
    xorg-x11-utils


# Helper function to install packages in the chroot by name (as an argument).
function install_package() {
    # We'll leave the RPMs around to avoid redownloading things.
    if [ -f "$1.rpm" ]; then
        return 0
    fi

    # Find the URL for the package.
    url=$(repoquery --repofrompath=centos7,http://mirror.centos.org/centos/7/os/`arch` \
        --repoid=centos7 -q --qf="%{location}" "$1" | \
        sed s/x86_64.rpm$/`arch`.rpm/ | \
        sed s/i686.rpm$/`arch`.rpm/g | \
        sort -u
    )

    # Download the RPM.
    wget "${url}" -O "$1.rpm"

    # Extract it.
    echo "Extracting $1..."
    rpm2cpio $1.rpm | cpio -idmv > /dev/null 2>&1
}


# Install glibc/ld-linux from CentOS 7.
install_package glibc


# Make the library directory and copy over glibc/ld-linux.
lib_directory=/opt/google/chrome/lib
mkdir -p $lib_directory
cp ./lib/* $lib_directory/ 2> /dev/null
cp ./lib64/* $lib_directory/ 2> /dev/null


# Install `mount` and its mandatory dependencies from CentOS 7.
for package in "glibc" "util-linux" "libmount" "libblkid" "libuuid" "libselinux" "pcre"; do
    install_package "${package}"
done


# Create an `ldd.sh` script to mimic the behavior of `ldd` within the namespace (without bash, etc. dependencies).
echo '#!/bin/bash' > ldd.sh
echo '' >> ldd.sh
echo '# Usage: ldd.sh LIBRARY_PATH EXECUTABLE' >> ldd.sh
echo 'mount --make-rprivate /' >> ldd.sh
echo 'unshare -m bash -c "`tail -n +7 $0`" "$0" "$@"' >> ldd.sh
echo 'exit $?' >> ldd.sh
echo '' >> ldd.sh
echo 'LD=$({ ls -1 ${1}/ld-linux* | head -n1 ; } 2> /dev/null)' >> ldd.sh
echo 'mount --make-private -o remount /' >> ldd.sh
echo 'mount --bind ${1} $(dirname "$({ ls -1 /lib/ld-linux* /lib64/ld-linux* | head -n1 ; } 2> /dev/null)")' >> ldd.sh
echo 'for directory in lib lib64 usr/lib usr/lib64; do' >> ldd.sh
echo '    PATH=./:./bin:./usr/bin LD_LIBRARY_PATH=${1}:./lib64:./usr/lib64:./lib:./usr/lib mount --bind ${1} /${directory} 2> /dev/null' >> ldd.sh
echo 'done' >> ldd.sh
echo 'echo -n "$(LD_TRACE_LOADED_OBJECTS=1 LD_LIBRARY_PATH="${1}" "${LD}" "${2}")"' >> ldd.sh
chmod a+x ldd.sh


# Takes the executable as an argument and recursively installs all missing dependencies.
function install_missing_dependencies() {
    executable="${1}"
    # Loop through and install missing dependencies.
    while true
    do
        finished=true
        # Loop through each of the missing libraries for this round.
        while read -r line
        do
            # Parse the various library listing formats.
            if [[ $line == *"/"* ]]; then
                # Extract the filename when a path is present (e.g. /lib64/).
                file=`echo $line | sed 's>.*/\([^/:]*\):.*>\1>'`
            else
                # Extract the filename for missing libraries without a path.
                file=`echo $line | awk '{print $1;}'`
            fi

            if [ -z $file ]; then
                continue
            fi

            # We'll require an empty round before completing.
            finished=false

            echo "Finding dependency for ${file}"

            # Find the package name for this library.
            package=$(repoquery --repofrompath=centos7,http://mirror.centos.org/centos/7/os/`arch` \
                --repoid=centos7 -q --qf="%{name}" --whatprovides "$file" | head -n1)

            install_package "${package}"

            # Copy it over to our library directory.
            find . | grep /${file} | xargs -n1 -I{} cp {} ${lib_directory}/
        done <<< "$(./ldd.sh "${lib_directory}" "${executable}" 2>&1 | grep -e "no version information" -e "not found")"

        # Break once no new files have been copied in a loop.
        if [ "$finished" = true ]; then
            break
        fi
    done
}


# Install the missing dependencies for Chrome.
install_missing_dependencies /opt/google/chrome/chrome


if ! installation_status; then
    # Time for the big guns, we'll try to patch the executables to use our lib directory.
    yum install -y gcc gcc-c++ make autoconf automake
    echo "Linking issues were encountered, attempting to patch the `chrome` executable."
    wget https://github.com/NixOS/patchelf/archive/0.9.tar.gz -O 0.9.tar.gz
    tar zxf 0.9.tar.gz
    pushd patchelf-0.9
    ./bootstrap.sh
    ./configure
    make
    LD="$({ ls -1 ${lib_directory}/ld-linux* | head -n1 ; } 2> /dev/null)"
    ./src/patchelf --set-interpreter "${LD}" --set-rpath "${lib_directory}" /opt/google/chrome/chrome
    ./src/patchelf --set-interpreter "${LD}" --set-rpath "${lib_directory}" /opt/google/chrome/chrome-sandbox
    sed -i 's/\(.*exec cat.*\)/LD_LIBRARY_PATH="" \1/g' /opt/google/chrome/google-chrome
    popd > /dev/null
    echo "Attempted experimental patching of Chrome to use a relocated glibc version."
fi

# Clean up the directory stack.
rm -rf ${working_directory}
popd > /dev/null

# Print out the success status message and exit.
version="$(google-chrome-stable --version)"
if [ $? -eq 0 ]; then
    echo "Successfully installed google-chrome-stable, ${version}."
    exit 0
else
    echo "Installation has failed."
    echo "Please email contact@intoli.com with the details of your operating system."
    echo "If you're using using AWS, please include the AMI identifier for the instance."
    exit 1
fi

  • 29
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抖音视频批量下载工具有几种选择。一种是使用在线工具,如引用\[1\]中提到的链接,该链接提供了一个在线工具,可以帮助用户批量下载抖音视频。另一种选择是使用抖音大师,如引用\[2\]所述,抖音大师是一款专门为抖音用户打造的下载工具,可以帮助用户批量下载抖音视频,支持高清视频下载,并且能够自动识别视频标题和封面。还有一种选择是使用抖音批量下载助手,如引用\[3\]所述,这是一款电脑软件,可以帮助用户轻松下载无水印的抖音视频资源。该软件由吾爱网友使用Python自制分享,可以一次性批量下载多个短视频内容,并且在下载过程中会自动去除视频中的水印。以上是几种常用的抖音视频批量下载工具。 #### 引用[.reference_title] - *1* *2* [短视频资源批量获取方案](https://blog.csdn.net/qq_14945847/article/details/131157460)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [抖音无水印视频批量下载助手](https://blog.csdn.net/leslie_yu_/article/details/114098500)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值