【问题标题】:Get instagram's video media source using oembed endpoints使用 oembed 端点获取 instagram 的视频媒体源
【发布时间】:2014-07-03 21:52:40
【问题描述】:

背景

我有一段 (jQuery) ajax 代码已经愉快地工作了大约 9 个月,直到最后几周左右。

此代码使用 Instagram 的 embedding endpoints,它允许我从普通 Instagram 链接(如 http://instagram.com/p/BUG/)中获取媒体源(图像或视频),无论用户是谁,并且无需需要 access_token .

简化示例:

var URL = "http://api.instagram.com/oembed?url=http://instagram.com/p/BUG/";
$(document).ready(function () {
    $.ajax({
        url: URL,
        dataType: "jsonp",
        cache: false,
        success: function (response) {
            console.log(response.url);
        },
        error: function () {
            console.log("couldn't process the instagram url");
        }
    });
});

在上面的代码中,response.url 将返回完整的媒体 URL 源,如:

http://photos-a.ak.instagram.com/xxxx/1234_123456123_123456_n.jpg // image or
http://distilleryvesper3-15.ak.instagram.com/b0c957463548362858_101.mp4 // video

然后我可以使用返回的 URL 将媒体文件嵌入到我的网页中。

注意

由于我们的想法是获取任何 Instagram 链接的 URL 源,而与用户无关,因此不能使用 media endpoints


问题

Instagram 的 oembed 端点允许您获取 json 响应,在过去几周之前它的结构是这样的:

{
    "provider_url" : "http:\/\/instagram.com\/",
    "media_id" : "123456789_123456789",
    "title" : "the title",
    "url" : "http:\/\/photos-a.ak.instagram.com\/hphotos-ak-xfp1\/12345678_123456789012345_1234567890_n.jpg",
    "author_name" : "{the user name}",
    "height" : 640,
    "width" : 640,
    "version" : "1.0",
    "author_url" : "http:\/\/instagram.com\/{the user name}",
    "author_id" : 123456789,
    "type" : "photo",
    "provider_name" : "Instagram"
}

您可能已经注意到,我的 ajax 代码对属性名称 url 特别感兴趣,它包含完整的媒体 URL。

注意json 回复(与今天一样)对于 Instagram 图片仍然有效,然而,如果原始 Instagram 的链接是视频,让我们使用真实的例如:http://instagram.com/p/mOFsFhAp4f/ (CocaCola(c)) json 响应不再返回任何 url 键。

似乎在引入web embeds 之后,Instagram 已决定在他们的(oembed)json 响应中仅对视频的 html 属性替换键 url,其中包含要嵌入的 iframe,如下所示:

{
    ...

    "html" : "\u003ciframe src=\"http:\/\/instagram.com\/p\/BUG\/embed\" width=\"616\" height=\"716\" frameborder=\"0\" scrolling=\"no\" allowtransparency=\"true\"\u003e\u003c\/iframe\u003e",

    ...
}

...当然,这会破坏我的代码,因为 response.url 未定义。


问题

Instagram json 响应发生变化后如何获取完整视频的 URL?

很遗憾,我在 Instagram 的开发者网站上找不到任何合适的文档或更改日志(他们有很棒的 AP​​I,但文档很差。)

注意问题是关于 Instagram API (v1) 嵌入端点而不是 jQuery 或 ajax 问题。

我正在寻找(可能是未记录的)Instagram 的 API 选项、端点、oembed 或其他(不需要access_token),它允许我检索到媒体视频的直接链接(最好在 json 响应之后)无论用户...或愿意考虑一个不太老套的解决方法,都脱离了正常的 Instagram 链接。

【问题讨论】:

  • 我看到BUG 键是shortcode 键。你改了吗?
  • @MortezaN.Alamdari :如果您知道我的意思,请查看Instagram documentationBUG 是媒体 ID 的简码(可以是 mOFsFhAp4f 中的任何 instagram.com/p/mOFsFhAp4f
  • 为什么不检查媒体类型,然后决定是否需要response.urlresponse.html
  • @Jashwant :当然可以,但response.htmliframe。我正在寻找的应该看起来像http://distilleryvesper3-15.ak.instagram.com/b0c957463548362858_101.mp4。你能从iframe 中得到它吗? (当然没有 Firebug,但来自应用程序;)如果是这样,请发布您的答案。
  • 您不想使用embed 链接并想要一个带有mp4 链接的网址? This code 不适合你。对吧?

标签: jquery ajax instagram endpoints oembed


【解决方案1】:

这可能不是最佳或最佳答案,但我相信这会暂时解决您的问题,因此您可以考虑解决此问题:

感谢whateverorigin.org 服务,我们能够获取跨源json,其中包含您可能请求的所有数据,您所要做的就是将返回的对象转换为字符串,然后使用正则表达式获取您需要的任何数据。

var myvideourl="http://instagram.com/p/mOFsFhAp4f/"
$.ajaxSetup({
    scriptCharset: "utf-8", //maybe "ISO-8859-1"
    contentType: "application/json; charset=utf-8"
});

$.getJSON('http://whateverorigin.org/get?url=' + 
    encodeURIComponent(myvideourl) + '&callback=?',
    function(data) {

        var xx=data.contents
        var dataindex=xx.search('<meta property="og:video" content=')
        var end=xx.indexOf('/>', dataindex);
        var yy=xx.slice(dataindex,end+2)
        var metaobject=$.parseHTML(yy)
        alert(metaobject[0].content)
        console.log(metaobject[0].content)
});

这是一个例子:

JS Fiddle Demo

对我来说效果很好,但只在可口可乐视频上试过,没有在其他链接上试过。

【讨论】:

  • 美丽。具有讽刺意味的是,我已将 whateverorigin.org 用于其他解决方案,包括此答案 stackoverflow.com/a/24559815/1055987,但对于这种特定情况,我并没有想到。我不愿意使用第三方服务,因为它们可能随时停止工作。好消息是whateverorigin 是开源的,所以我可以自己托管服务以满足客户的需求。感谢您的回答,在授予任何赏金之前,我只需要做出一些考虑并等待其他可能的答案;)
  • 好的没问题,只是希望我能帮上忙,祝你找到最佳答案:)
  • 另一种可能会或可能不会下降的替代方案是https://cors-anywhere.herokuapp.com/
【解决方案2】:

更新 [2015 年 3 月]:有关此解决方案的扩展和更新版本,请访问 http://www.picssel.com/build-a-simple-instagram-api-case-study/


@ProllyGeek 的 answer 提供了一个很好的解决方法来抓取 Instagram 视频页面(当之无愧的赏金),但是它依赖于 whateverorigin.org 第三方服务,除非服务最终变得不可用。

由于最近在生产环境中已经发生在我身上,我不得不寻找更可靠的替代方案,因此我决定使用 php 的 file_get_contents 从自己托管的 PHP 模块中抓取视频链接。

我基本上遵循@ProllyGeek 提出的相同逻辑,但翻译成 PHP 所以:

getVideoLink.php 模块:

<?php
header('Content-Type: text/html; charset=utf-8');
function clean_input($data){
    $data = trim($data);
    $data = stripslashes($data);
    $data = strip_tags($data);
    $data = htmlspecialchars($data);
    return $data;
};
$instalink = clean_input( $_GET['instalink'] );    
if (!empty($instalink)) {
    $response = clean_input( @ file_get_contents( $instalink ) );
    $start_position = strpos( $response ,'video_url&quot;:&quot;' ); // the start position
    $start_positionlength = strlen('video_url&quot;:&quot;'); // string length to trim before
    $end_position = strpos($response ,'&quot;,&quot;usertags'); // the end position
    $mp4_link = substr( $response, ( $start_position + $start_positionlength ), ( $end_position - ( $start_position + $start_positionlength ) ) );
    echo $mp4_link;
};
?>

当然,您可能需要手动分析响应以了解您要查找的内容。

然后从我的主页对 PHP 模块进行 AJAX 调用:

var instaLink = "http://instagram.com/p/mOFsFhAp4f/"; // the Coca Cola video link
jQuery(document).ready(function ($) {
    $.ajax({
        url: "getVideoLink.php?instalink="+instaLink,
        dataType : "html",
        cache : false,
        success : function (data) {
            console.log(data); // returns http://distilleryvesper3-15.ak.instagram.com/b0ce80e6b91111e3a16a122b8b9af17f_101.mp4
        },
        error : function () {
            console.log("error in ajax");
        }
    });
}); // ready 

假设您的主机支持 php 使用此方法。


编辑 [2014 年 11 月 19 日]

我已修改 getVideoLink.php 模块(现为 getInstaLinkJSON.php)以实际从特定 Instagram 媒体链接获取 JSON 信息喜欢http://instagram.com/p/mOFsFhAp4f/

这比仅仅抓取视频的 URL 有用得多,也可以用于图像。

新的 getInstaLinkJSON.php 代码:

<?php
function clean_input($data){
    $data = trim($data);
    $data = strip_tags($data);
    return $data;
};
// clean user input
function clean_input_all($data){
    $data = trim($data);
    $data = stripslashes($data);
    $data = strip_tags($data);
    $data = htmlspecialchars($data);
    return $data;
};
$instaLink = clean_input_all( $_GET['instaLink'] );

if( !empty($instaLink) ){
    header('Content-Type: application/json; charset=utf-8');
    $response = clean_input( @ file_get_contents($instaLink) );
    $response_length = strlen($response);
    $start_position = strpos( $response ,'window._sharedData = ' ); // the start position
    $start_positionlength = strlen('window._sharedData = '); // string length to trim before
    $trimmed = trim( substr($response, ( $start_position + $start_positionlength ) ) ); // trim extra spaces and carriage returns
    $jsondata = substr( $trimmed, 0, -1); // remove extra ";" added at the end of the javascript variable 
    echo $jsondata;
} elseif( empty($instaLink) ) {
    die(); //only accepts instaLink as parameter
}
?>

我正在清理用户的输入和file_get_contents() 响应,但是我不会从最后一个中删除 斜杠HTML 字符,因为我将返回一个 JSON 响应。

然后是AJAX调用:

var instaLink = "http://instagram.com/p/mOFsFhAp4f/"; // demo
jQuery.ajax({
    url: "getInstaLinkJSON.php?instalink=" + instaLink,
    dataType : "json", // important!!!
    cache : false,
    success : function ( response ) {
        console.log( response ); // returns json
        var media = response.entry_data.DesktopPPage[0].media;

        // get the video URL
        // media.is_video : returns true/false

        if( media.is_video ){
            console.log( media.video_url ); // returns http://distilleryvesper3-15.ak.instagram.com/b0ce80e6b91111e3a16a122b8b9af17f_101.mp4
        }
    },
    error : function () {
        console.log("error in ajax");
    }
});

编辑 [2020 年 5 月 20 日]

当前工作的 PHP

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");
function clean_input($data){
    $data = trim($data);
    $data = strip_tags($data);
    return $data;
};
// clean user input
function clean_input_all($data){
    $data = trim($data);
    $data = stripslashes($data);
    $data = strip_tags($data);
    $data = htmlspecialchars($data);
    return $data;
};
$instaLink = clean_input_all( $_GET['instaLink'] );

if( !empty($instaLink) ){
    header('Content-Type: application/json; charset=utf-8');
    $response = clean_input( @ file_get_contents($instaLink) );
    $response_length = strlen($response);
    $start_position = strpos( $response ,'window._sharedData = ' ); // the start position
    $start_positionlength = strlen('window._sharedData = '); // string length to trim before
    $trimmed = trim( substr($response, ( $start_position + $start_positionlength ) ) ); // trim extra spaces and carriage returns
    $jsondata = substr( $trimmed, 0, -1); // remove extra ";" added at the end of the javascript variable 
    $jsondata = explode('window.__initialDataLoaded', $jsondata);
    echo substr(trim($jsondata[0]), 0, -1);
} elseif( empty($instaLink) ) {
    die(); //only accepts instaLink as parameter
}
?>

【讨论】:

  • 我现在将您的答案用于我自己的问题:D 对这个解决方案表示赞赏;)
  • @ProllyGeek :从那以后我已经改进了代码,我想我很快就会发布更新;)
  • 请尽快完成 :)
  • @ProllyGeek : 我对修剪方法做了进一步的调整
  • 我不确定他们是否从那时起改变了它,但这段代码对我不起作用——即使是更新的版本。 $jsondata 变量返回了一堆 html &lt;script&gt; 标记,这意味着它不是有效的 JSON。我不得不稍微不同地修剪它:$pos1 = strpos($response,'window._sharedData = '); $trim1 = trim(substr($response, ($pos1 + 21))); $pos2 = strpos($trim1,"&lt;/script&gt;"); $trim2 = trim(substr($trim1,0,$pos2-1)); $jsondata = json_decode($trim2);
【解决方案3】:

我不是 jQuery 专家。撇开语法错误不谈,这有什么用吗?

var publicUrl = "http://instagram.com/p/dAu7UPgvn0"; //photo
var publicUrl = "http://instagram.com/p/mOFsFhAp4f"; //video


var URL = "http://api.instagram.com/oembed?url="+publicUrl;

$(document).ready(function () {
    $.ajax({
        url: URL,
        publicurl: publicUrl,
        dataType: "jsonp",
        cache: false,
        success: function (response) {
            success: function (response) {
                var mediaSrc;
                if (response.type === 'photo') {
                    mediaSrc = response.url;
                } else {
                    mediaSrc = $(publicurl).find('div.Video vStatesHide Frame').src;
                }
                console.log(mediaSrc);
            }
        },
        error: function () {
            console.log("couldn't process the instagram url");
        }
    });
});

【讨论】:

  • 这与我的回答类似 :) $(publicurl).find('div.Video vStatesHide Frame').src 不正确。你可以像我一样使用[0].src,也可以使用attr('src')
  • @Jashwant 我确定是 ;)。但与您的方法不同,我不建议依赖 api 返回。这更像是网络报废,因为操作人员非常渴望获得实际来源。
  • 你不能这样刮。请参阅 Prolly 的回答。
  • Instagram 已将类型删除为 photovideo,现在它为类型字段返回 rich
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2017-11-09
  • 1970-01-01
  • 1970-01-01
  • 2018-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多