当前位置: 首页 > 知识库问答 >
问题:

我如何像其他网站一样绕过YouTube API嵌入限制?

施鸿
2023-03-14

我正在开发一个java程序,可以在嵌入式播放器中播放YouTube视频。问题是,大多数音乐视频都无法播放,我遇到了以下错误:“此视频包含(媒体公司名称)的内容。某些网站限制播放。”

我尝试在Chrome加载相同的URL,结果相同。https://www.youtube.com/embed/TMZi25Pq3T8

然而,经过一些研究,我很快就修复了它,安装了一个允许我添加HTTP请求头的Chrome扩展,并添加了一个遵循此结构的Referer头。”https://www..com“并使其工作。

所以我想一定是这样。为了将请求头添加到我的JavaFX WebView/WebEngine中,我添加了以下代码:

URI uri = URI.create("https://www.youtube.com/embed/TMZi25Pq3T8");
List<String> cookies = new ArrayList<>();
cookies.add("User-Agent=BDM/v0.92");
cookies.add("Referer=https://www.youtube.com");
Map<String, List<String>> headers = new LinkedHashMap<String, List<String>>();
headers.put("Set-Cookie", cookies);
try {
    CookieHandler.getDefault().put(uri, headers);
} catch (IOException ex) {
    ex.printStackTrace();
}
System.out.println(webView.getEngine().getUserAgent());
webView.getEngine().load(uri.toString());

仍然没有成功,同样的错误消息

我正在使用的网站通过他们的API Discogs提取发布数据,它也可以播放“受限”视频。我错过了什么?

后期编辑:进一步澄清:

我想为我犯的错误道歉:

  1. 线路<代码>系统。出来println(webView.getEngine()。getUserAgent()) 不打印“BDM/v0.92”,正如我首先所说,它打印默认的JavaFX用户代理,“Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/538.19(KHTML,像Gecko)JavaFX/8.0 Safari/538.19”。这导致了第二个
  2. 正如Roman Nazarenko指出的那样,我把Cookie和请求头混淆了

这就引出了一个真正的问题:如何为JavaFX WebEngine发送HTTP请求头?唯一的选择是通过调用webView来设置用户代理。getEngine()。setUserAgent(“myUserAgent”)

我在这里找到了一个黑客,但这对我不起作用:https://twitter.com/codingfabian/status/524942996748652544

谢谢

共有1个答案

欧盛
2023-03-14

我设法解决了这个问题,通过使用javhelp和本教程如何仪器Java代码。

正如我在问题中所说,YouTube播放器需要一个Referer标头来播放一些视频(如VEVO、Sony music Enternation等拥有的音乐视频)。

我所做的是从JavaFX的WebEngine使用的URLLoader类中截取prepareConnection方法,并将指令插入方法体的顶部:

c.setRequestProperty("Referer", "https://www.discogs.com");

(同样,请按照教程了解所有说明)

(注意:尽管上面的教程很好地解释了概念,但它并没有真正触及MANIFEST. MF文件的角色和结构,因此请查看此链接以获取有关此方面的更多信息)

这是我的两门课:

MyJavaAgent。Java语言

package com.busytrack.discographymanager.headerfixagent;
import java.lang.instrument.Instrumentation;
public class MyJavaAgent {
public static void premain(String agentArgument, Instrumentation instrumentation) {
    ClassTransformer transformer = new ClassTransformer();
    instrumentation.addTransformer(transformer);
    }
}

ClassTransformer.java

package com.busytrack.discographymanager.headerfixagent;
import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class ClassTransformer implements ClassFileTransformer {
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        byte[] byteCode = classfileBuffer;
        if (className.equals("com/sun/webkit/network/URLLoader")) {
            try {
                ClassPool classPool = new ClassPool(true);
                CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
                CtMethod method = ctClass.getDeclaredMethod("prepareConnection");
                String src = "$1.setRequestProperty(\"Referer\", \"https://www.discogs.com\");"; // Confused about there being "$1" instead of "c"? Please read below
                method.insertBefore(src);
                byteCode = ctClass.toBytecode();
                ctClass.detach();
            }  catch (Exception e) {
                e.printStackTrace();
            }
        }   
        return byteCode;
    }
}

这就是为什么我使用“$1”来访问方法参数,而不是“c”:

语句和块可以引用字段和方法。如果该方法是使用-g选项编译的,它们还可以引用它们插入的方法的参数(以在类文件中包含局部变量属性)。否则,它们必须通过下面描述的特殊变量0美元、1美元、2美元、...访问方法参数。虽然允许在块中声明新的局部变量,但不允许访问方法中声明的局部变量。

整个javassist教程都可以在这里找到。

打包两个类和清单后。MF文件放在一个单独的JAR中,将其导入IDE(我使用的是Eclipse),并添加以下VM参数:

-javaagent:./(your-jar-name).jar

在Eclipse中,可以添加如下VM参数:

right click on your project -> Run As -> Run Configurations... -> open the Arguments tab -> insert your VM argument -> Apply

我希望这对其他人有所帮助。我知道我在这个问题上花了几天时间。我不知道这是否是最好的方法,但它确实适合我。尽管如此,我还是想知道为什么没有一种简单的方法来为JavaFX的WebEngine设置请求头。。。

稍后编辑:

我发现了一种更干净、更简单的方法来动态加载Java代理,而不需要创建单独的JAR、清单文件、导入它们、在启动时传递-javaagent VM参数等等。

我使用了ea代理加载程序(JAR下载链接)。

在IDE中导入JAR,并将MyJavaAgent类(具有premain方法的类)更改为:

package com.busytrack.discographymanager.headerfixagent;
import java.lang.instrument.Instrumentation;
public class MyJavaAgent {
    public static void agentmain(String agentArgument, Instrumentation instrumentation) {
        ClassTransformer transformer = new ClassTransformer();
        instrumentation.addTransformer(transformer);
    }
}

我在MainClass中的主要方法如下所示:

public static void main(String[] args) {
    AgentLoader.loadAgentClass(MyJavaAgent.class.getName(), null); // Load the MyJavaAgent class
    launch(args); // Start the JavaFX application
}

我希望能够动态加载代理,因为使用静态方法需要为所有平台创建单独的启动器,并在启动时传递-javaagent参数。现在,我可以像往常一样从eclipse导出一个可运行的JAR,代理将自动加载(不需要VM参数)。感谢BioWare提供此工具!:D

 类似资料:
  • 所以我使用YouTube API来搜索视频。在我的搜索中,我包括以下参数:type=video,videoembeddeble=true,videoSyndicated=true。但我得到的结果仍然无法在我的网站上播放。我正在做的一个例子是 https://www.googleapis.com/youtube/v3/search?part=snippet 但是结果仍然给我一个错误,当嵌入时指出 此

  • 问题内容: 我有一个带有angular的应用程序,我需要使用这个库http://www.jointjs.com/,所以我下载了joint.min.js和joint.min.css并将它们的路由放置在index.html中,但是我不知道要在app.js中放入什么来注入它,而我一直在从角度获取注入错误。这可能不是这样做的方法吗?我搜索了很多,但是没有找到任何方法。我将不胜感激,在此先感谢您! 问题答案

  • 我正在尝试使用promise与我的异步函数。根据我的理解,promise应该是缓解回调地狱。然而,我的代码似乎仍然嵌套得很深。 我是否遗漏了一些关于promise的东西(是否可以重写以使其更易读/更通俗),或者promise有时就像回调一样嵌套? 在本例中,我正在构建一个函数,该函数调用API从某个社交媒体帐户检索好友列表。如果初始调用由于身份验证错误而失败,我知道我必须首先进行身份验证,然后再次

  • 问题内容: 我知道如何在同一包中的结构中嵌入其他结构,但是如何在其他包的结构中嵌入结构? dog.go main.go 当我运行main.go时,它告诉我一个错误: 问题答案: @simon_xia是正确的,看来您 可能 对Go有点陌生。 首先,欢迎来到社区!! 现在,请扩展一下他的评论… Go并未提供成员/方法的公共/私有范围,而是具有Exporting的概念。因此,如果要允许从另一个包访问方法

  • 问题内容: 我想启动一个将使用ajax push的应用程序,但是应该正确配置Web服务器,而且我不知道如何在服务器端组件上启动。 我想从dojo的cometd开始,然后阅读一些博客,说activeMQ较旧,并且是ajax push上的标记载体,但是还有另一个博客说,很难设置并使其工作。 现在,在开始之前我很困惑,请告诉我我的方式:)配置Ajax推送环境的最佳方法是什么? 思南 问题答案: 在斯洛文

  • 问题内容: 我网站的合法用户有时会通过API请求对服务器进行锤击,从而导致不良结果。我想建立一个限制,即每5秒不超过一个API调用或每分钟不超过n个调用(尚未知道确切的限制)。显然,我可以将每个API调用记录在数据库中,并对每个请求进行计算,以查看它们是否超出限制,但是每个请求上的所有这些额外开销都无法达到目的。我可以使用哪些其他耗费资源较少的方法来建立限制?我正在使用PHP / Apache /