JSoup - 无法从 Instagram 检索视频类型的标签

JSoup - Unable to retrieve tag of type video from Instagram

提问人:ecronin 提问时间:11/13/2023 更新时间:11/13/2023 访问量:35

问:

首先,让我说我是一名后端开发人员,并且可能已经有 15 年没有尝试解析 HTML 文档了,所以请耐心等待。另外,我真的不知道Instagram是如何运作的,这就是为什么我试图了解它。

我正在尝试从 Instagram 下载视频,并且该视频位于标签“视频”中。我一直在创建不同的方法来迭代 org.jsoup.nodes.Document 的子元素。似乎无论我做什么,我都无法识别标签。我尝试使用类方法 Document.children().select(*)。我想知道 Instagram 是否以某种方式“隐藏”了视频源。我真的不知道。

我还希望有一个名为 og:video 的元标签,但这个标签不存在(title、img 等存在)。我试着像这样访问它:

page.select(“meta[property=og:video]”).first().attr(“内容”);

这是开发工具的屏幕截图

在 instagramDownloader 类中,有两种递归方法可以遍历所有节点和元素,这两种方法都没有给我任何关于如何检索视频的线索。我确实在另一个堆栈溢出问题中找到了这种递归方法。我什至不知道如果我有 src URL,是否可以下载视频。

`

public class Application {

    public static void main(String[] args) {

        try {
            login();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void login() throws IGLoginException, InterruptedException, ExecutionException{

        IGClient client = IGClient.builder().username("myuser").password("mylogin").login();
        
        InstagramDownloader dl = new InstagramDownloader();
        dl.downloadVideo("https://www.instagram.com/reel/CzeWZCYJ09R/", "C:\\temp");
    }

public class InstagramDownloader {

    private Document page;
    private final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36";

  public void downloadVideo(String url, String targetDirectory){
        String videoUrl = "";

        Helpers.validateURL(url);
        try {
            page = Jsoup.connect(url).userAgent(USER_AGENT).get();
            getAllElements(page);
            getAllNodes(page);
            //videoUrl = ???
            
        } catch (IOException e){
            e.printStackTrace();
        }      
       download(videoUrl, targetDirectory);
    }

 public void getAllElements(Document doc) {
         Elements children = new Elements();
         recurseOverElements(doc.getAllElements(), children);

         for (Element element : children) {
             System.out.println(element.tagName());
         }
    }

 public Elements recurseOverElements(Elements elementList, Elements children){
        if(elementList.size() == 0)
            return children;

        for (Element element : elementList) {

            recurseOverElements(element.children(), children);
            children.add(element);
        }
        return children;
    }
    
    public void getAllNodes(Document doc) {
        List<Node> allNodesInDom = new ArrayList<>();
        recurseOverNodes(doc.childNodes(), allNodesInDom);

        for (Node node : allNodesInDom) {
            System.out.println(node.nodeName());
        }
   }
    
    public List<Node> recurseOverNodes(List<Node> nodeList, List<Node> allChildNodeList){
        if(nodeList.size() == 0)
            return allChildNodeList;

        for (Node node : nodeList) {
            recurseOverNodes(node.childNodes(), allChildNodeList);
            allChildNodeList.add(node);
        }
        return allChildNodeList;
    }

private void download(String url, String targetDirectory){
        String[] tempName = url.split("/");
        String filename = tempName[tempName.length-1].split("[?]")[0];

        try(InputStream inputStream = URI.create(url).toURL().openStream()){
            int x = inputStream.read();
            System.out.println("x" + x);
            HttpURLConnection conn = (HttpURLConnection)URI.create(url).toURL().openConnection();
            Path targetPath = new File(targetDirectory + File.separator + filename).toPath();
            Files.copy(inputStream, targetPath, StandardCopyOption.REPLACE_EXISTING);

            int BYTES_PER_KB = 1024;
            double fileSize = ((double)conn.getContentLength() / BYTES_PER_KB);
        } catch (IOException e){
            e.printStackTrace();
        }
}
Java Dom jsoup Instagram

评论

0赞 Hovercraft Full Of Eels 11/13/2023
您是否没有在浏览器的开发工具中查看 HTML,而是检查了代码可见的 HTML?它们可能非常不同。
0赞 Hovercraft Full Of Eels 11/13/2023
例如,您是否打印了 ?page
0赞 ecronin 11/13/2023
@HovercraftFullOfEels - 谢谢你的提示。page.html( 确实显示了从 Instagram 返回的 Json 数据。我怀疑我可能必须获取这些数据并对 Insta 进行 API 调用才能获取视频。

答:

0赞 rzwitserloot 11/13/2023 #1

我有个坏消息要告诉你:你可以把你的代码扔进垃圾桶。从根本上说,你的计划在这里永远不会奏效。

你遇到的问题,也是你现在几乎在任何事情上都会遇到的问题,是 JSoup 实际上无法解析现代网络。

问题很简单:你的浏览器下载的 HTML(即你提供给 JSoup 的东西)的内容几乎为零。取而代之的是,HTML 会导致一堆 javascript 运行,并且 javascript 会执行各种网络请求,并使用实际内容创建更多 HTML。

JSoup 只是一个 HTML 解析器。它不是 javascript 引擎。如果你想要一个 javascript 引擎,那真的很复杂,或多或少需要一个完整的浏览器:这是一项非常繁重的工作。如果你想研究一下,你可能想试试硒。因此,javascript 用其中的内容制作的所有 HTML 是什么?它不存在于 JSoup 看到的东西中,而且 JSoup 无法为您提供不存在的东西。

当您在浏览器中单击鼠标右键并选择“检查元素...”时从中你看到的是实时 DOM——它开始与从服务器下载的 HTML 页面相同,但可以通过它运行的 javascript 进行修改,在大多数现代网站上,它已经被 javascript 修改了很多,这就是简陋的帐篷和大教堂之间的区别。

相反,选择“显示来源”或仅用于获取实际 URL 并检查您想要的信息是否在那里。几率非常高,但事实并非如此。curl

如果不是,JSoup 不会帮助你

一般来说,网站都有用于此类事情的 API。这是适合这里工作的工具。不是“我会像浏览器一样工作并解析该视频 URL”。请注意,这绕过了审核,尤其是广告和用户管理,因此这些网站的构建者正在积极尝试与您作斗争。这并不意味着你的工作不可能,只是 [A] 非常困难,[B] 在某些司法管辖区是非法的(糟糕的司法管辖区,但是,美国很可能是其中之一。DMCA不是一部成文良好的法律),[C]是一个长期严重的维护问题。Instagram不会坐以待毙。今天行得通的东西明天可能就行不通了。特别是如果他们在日志中注意到您正在这样做并试图阻止您。

这就是 API 存在的原因。服务器构建者简化了他们支持和不支持的内容,使您更简单,添加他们需要的任何身份验证来满足他们拥有的任何法律和营销需求(API 密钥等),然后他们可以提供和支持稳定的东西,而不是在他们决定稍微重新设计他们的首页时破坏一半的网络。