php 以编程方式登录 Instagram

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26003063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 18:06:08  来源:igfitidea点击:

Instagram login programmatically

phpcookiesinstagrammessages

提问by Rens

I'm trying to programmatically login to Instagram via my own website because I want to retrieve direct messages from Instagram (this requires a login as it is not supported in the Instagram API (yet)). But the Instagram login page requires cookies to login.

我正在尝试通过我自己的网站以编程方式登录 Instagram,因为我想从 Instagram 检索直接消息(这需要登录,因为 Instagram API(尚)不支持它)。但是 Instagram 登录页面需要 cookie 才能登录。

I keep getting the message that the page could not be loaded and that I might need to enable cookies.

我不断收到无法加载页面并且我可能需要启用 cookie 的消息。

Is there any way possible to login programmatically via PHP to Instagram?

有什么方法可以通过 PHP 以编程方式登录到 Instagram?

This is what I have so far.

这是我到目前为止。

$ch = curl_init('https://instagram.com/accounts/login/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
$result = curl_exec($ch);
preg_match_all('/^Set-Cookie:\s*([^\r\n]*)/mi', $result, $ms);
$cookies = array();
foreach ($ms[1] as $m) {
   list($name, $value) = explode('=', $m, 2);
   $cookies[$name] = $value;
}

$ccode  = substr($cookies['ccode'], 0, 2);
$mid    = array_shift(explode(';', $cookies['mid']));
$csfrtoken = array_shift(explode(';', $cookies['csrftoken']));

$header = array();
$header[] = 'Accept: */*';
$header[] = 'Accept-Encoding: gzip,deflate';
$header[] = 'Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4';
$header[] = 'Connection: keep-alive';
$header[] = 'Content-Length: 46';
$header[] = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8';
$header[] = 'X-Instagram-AJAX: 1';
$header[] = 'X-Requested-With: XMLHttpRequest';

$ch = curl_init('https://instagram.com/accounts/login/ajax/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'username=*****&password=*****&intent=');
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36');
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/test.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).'/test.txt');
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_COOKIE, 'mid='.$mid.'; ccode='.$ccode.'; csrftoken='.$csfrtoken.';');
curl_setopt($ch, CURLOPT_ENCODING, '');

$response = curl_exec($ch);

采纳答案by Vaha

My great respect to @Fatih K?sa for his code, very good job. I have tried this code, but for now it doesn't work, probably, because of some Instagram server-side changes. I have played 2 days with his code and force it to work with my small changes. Very important part of this code is that Instagram accepts only post form with curl referrer which contains the cookies data (csrftoken and mid). Also important part is that you must use https://www.instagram.com/accounts/login/?force_classic_login, only with WWW and to remove after cookies creation the strings about curl info:

我非常尊重@Fatih K?sa 的代码,非常好。我已经尝试过这段代码,但现在它不起作用,可能是因为 Instagram 服务器端的一些更改。我已经用他的代码玩了 2 天,并强制它与我的小改动一起工作。这段代码非常重要的部分是 Instagram 只接受包含 cookie 数据(csrftoken 和 mid)的带有 curl 引用的帖子表单。同样重要的部分是您必须使用https://www.instagram.com/accounts/login/?force_classic_login,仅用于 WWW 并在创建 cookie 后删除有关 curl 信息的字符串:

#Netscape HTTP Cookie File

#Netscape HTTP Cookie 文件

#http://curl.haxx.se/docs/http-cookies.html

#http://curl.haxx.se/docs/http-cookies.html

#This file was generated by libcurl! Edit at your own risk.

#这个文件是libcurl生成的!编辑风险自负。

Here is working code, enjoy!

这是工作代码,享受!

$username = "yourname";
$password = "yourpass";
$useragent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/50.0.2661.102 Chrome/50.0.2661.102 Safari/537.36";
$cookie=$username.".txt";

@unlink(dirname(__FILE__)."/".$cookie);

$url="https://www.instagram.com/accounts/login/?force_classic_login";

$ch  = curl_init();        

$arrSetHeaders = array(
    "User-Agent: $useragent",
    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language: en-US,en;q=0.5',
    'Accept-Encoding: deflate, br',
    'Connection: keep-alive',
    'cache-control: max-age=0',
);

curl_setopt($ch, CURLOPT_HTTPHEADER, $arrSetHeaders);         
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__)."/".$cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__)."/".$cookie);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

$page = curl_exec($ch);
curl_close($ch);          

// try to find the actual login form
if (!preg_match('/<form data-encrypt method="POST" id="login-form" class="adjacent".*?<\/form>/is', $page, $form)) {
    die('Failed to find log in form!');
}

$form = $form[0];

// find the action of the login form
if (!preg_match('/action="([^"]+)"/i', $form, $action)) {
    die('Failed to find login form url');
}

$url2 = $action[1]; // this is our new post url
// find all hidden fields which we need to send with our login, this includes security tokens
$count = preg_match_all('/<input type="hidden"\s*name="([^"]*)"\s*value="([^"]*)"/i', $form, $hiddenFields);

$postFields = array();

// turn the hidden fields into an array
for ($i = 0; $i < $count; ++$i) {
    $postFields[$hiddenFields[1][$i]] = $hiddenFields[2][$i];
}

// add our login values
$postFields['username'] = $username;
$postFields['password'] = $password;   

$post = '';

// convert to string, this won't work as an array, form will not accept multipart/form-data, only application/x-www-form-urlencoded
foreach($postFields as $key => $value) {
    $post .= $key . '=' . urlencode($value) . '&';
}

$post = substr($post, 0, -1);   

preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $page, $matches);

$cookieFileContent = '';

foreach($matches[1] as $item) 
{
    $cookieFileContent .= "$item; ";
}

$cookieFileContent = rtrim($cookieFileContent, '; ');
$cookieFileContent = str_replace('sessionid=; ', '', $cookieFileContent);

$oldContent = file_get_contents(dirname(__FILE__)."/".$cookie);
$oldContArr = explode("\n", $oldContent);

if(count($oldContArr))
{
    foreach($oldContArr as $k => $line)
    {
        if(strstr($line, '# '))
        {
            unset($oldContArr[$k]);
        }
    }

    $newContent = implode("\n", $oldContArr);
    $newContent = trim($newContent, "\n");

    file_put_contents(
        dirname(__FILE__)."/".$cookie,
        $newContent
    );    
}

$arrSetHeaders = array(
    'origin: https://www.instagram.com',
    'authority: www.instagram.com',
    'upgrade-insecure-requests: 1',
    'Host: www.instagram.com',
    "User-Agent: $useragent",
    'content-type: application/x-www-form-urlencoded',
    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language: en-US,en;q=0.5',
    'Accept-Encoding: deflate, br',
    "Referer: $url",
    "Cookie: $cookieFileContent",
    'Connection: keep-alive',
    'cache-control: max-age=0',
);

$ch  = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__)."/".$cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__)."/".$cookie);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $arrSetHeaders);     
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);        

sleep(5);
$page = curl_exec($ch);


preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $page, $matches);
$cookies = array();
foreach($matches[1] as $item) {
    parse_str($item, $cookie1);
    $cookies = array_merge($cookies, $cookie1);
}
var_dump($page);      

curl_close($ch);  

回答by Filype

It looks like you were headed in the right direction, in your example, it seems that you get an authenticated response but a consequent request to an authenticated page does not work as expected.

看起来您朝着正确的方向前进,在您的示例中,您似乎获得了经过身份验证的响应,但随后对经过身份验证的页面的请求未按预期工作。

I suspect that instagram is actively preventing this by running a check with an Ajax call or something similar.

我怀疑 Instagram 通过使用 Ajax 调用或类似方法运行检查来积极防止这种情况发生。

As an alternative you can look at something like zombie.js.

作为替代,您可以查看诸如zombie.js 之类的内容

This is a headless virtual browser where you can visit pages and interact with the elements on it, but you cant view them.

这是一个无头虚拟浏览器,您可以在其中访问页面并与其上的元素进行交互,但您无法查看它们。

A simple example using zombie.jsis as follows:

一个使用zombie.js的简单例子如下:

var Browser = require('zombie');
var browser = Browser.create();

browser.visit('https://instagram.com/', function() {
  browser.wait(10000, function(){
    browser.fill('input[name="username"]', 'myusername');
    browser.fill('input[type="password"]', 'mypasswd');
    browser.pressButton('Log in', function() {
      browser.visit('https://instagram.com/accounts/edit/', function() {
        console.log(browser.html());
      });
    });

  });

});

Hope it helps.

希望能帮助到你。

回答by Serhii

@Vaha's code stopped working

@Vaha 的代码停止工作

change

改变

$cookieFileContent = str_replace('sessionid=; ', '', $cookieFileContent);

for

为了

$cookieFileContent = str_replace('sessionid=""; ', '', $cookieFileContent);

and the code will work

代码将起作用



define('USERNAME', "");
define('PASSWORD', "");
define('USERAGENT', "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36");
define('COOKIE', USERNAME.".txt");

function login_inst() {

    @unlink(dirname(__FILE__)."/!instagram/".COOKIE);

    $url="https://www.instagram.com/accounts/login/?force_classic_login";

    $ch  = curl_init(); 

    $arrSetHeaders = array(
        "User-Agent: USERAGENT",
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language: en-US,en;q=0.5',
        'Accept-Encoding: deflate, br',
        'Connection: keep-alive',
        'cache-control: max-age=0',
    );

    curl_setopt($ch, CURLOPT_HTTPHEADER, $arrSetHeaders);         
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__)."/!instagram/".COOKIE);
    curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__)."/!instagram/".COOKIE);
    curl_setopt($ch, CURLOPT_USERAGENT, USERAGENT);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $page = curl_exec($ch);
    curl_close($ch);  

    //var_dump($page);

    // try to find the actual login form
    if (!preg_match('/<form method="POST" id="login-form" class="adjacent".*?<\/form>/is', $page, $form)) {
        die('Failed to find log in form!');
    }

    $form = $form[0];

    // find the action of the login form
    if (!preg_match('/action="([^"]+)"/i', $form, $action)) {
        die('Failed to find login form url');
    }

    $url2 = $action[1]; // this is our new post url
    // find all hidden fields which we need to send with our login, this includes security tokens
    $count = preg_match_all('/<input type="hidden"\s*name="([^"]*)"\s*value="([^"]*)"/i', $form, $hiddenFields);

    $postFields = array();

    // turn the hidden fields into an array
    for ($i = 0; $i < $count; ++$i) {
        $postFields[$hiddenFields[1][$i]] = $hiddenFields[2][$i];
    }

    // add our login values
    $postFields['username'] = USERNAME;
    $postFields['password'] = PASSWORD;   

    $post = '';

    // convert to string, this won't work as an array, form will not accept multipart/form-data, only application/x-www-form-urlencoded
    foreach($postFields as $key => $value) {
        $post .= $key . '=' . urlencode($value) . '&';
    }

    $post = substr($post, 0, -1);   

    preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $page, $matches);

    $cookieFileContent = '';

    foreach($matches[1] as $item) 
    {
        $cookieFileContent .= "$item; ";
    }

    $cookieFileContent = rtrim($cookieFileContent, '; ');
    $cookieFileContent = str_replace('sessionid=""; ', '', $cookieFileContent);

    $oldContent = file_get_contents(dirname(__FILE__)."/!instagram/".COOKIE);
    $oldContArr = explode("\n", $oldContent);

    if(count($oldContArr))
    {
        foreach($oldContArr as $k => $line)
        {
            if(strstr($line, '# '))
            {
                unset($oldContArr[$k]);
            }
        }

        $newContent = implode("\n", $oldContArr);
        $newContent = trim($newContent, "\n");

        file_put_contents(
            dirname(__FILE__)."/!instagram/".COOKIE,
            $newContent
        );    
    }

    $arrSetHeaders = array(
        'origin: https://www.instagram.com',
        'authority: www.instagram.com',
        'upgrade-insecure-requests: 1',
        'Host: www.instagram.com',
        "User-Agent: USERAGENT",
        'content-type: application/x-www-form-urlencoded',
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language: en-US,en;q=0.5',
        'Accept-Encoding: deflate, br',
        "Referer: $url",
        "Cookie: $cookieFileContent",
        'Connection: keep-alive',
        'cache-control: max-age=0',
    );

    $ch  = curl_init();
    curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__)."/!instagram/".COOKIE);
    curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__)."/!instagram/".COOKIE);
    curl_setopt($ch, CURLOPT_USERAGENT, USERAGENT);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $arrSetHeaders);     
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_REFERER, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);  
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    sleep(5);
    $page = curl_exec($ch);

    /*
    preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $page, $matches);
    COOKIEs = array();
    foreach($matches[1] as $item) {
        parse_str($item, COOKIE1);
        COOKIEs = array_merge(COOKIEs, COOKIE1);
    }
    */
    //var_dump($page);      
    curl_close($ch);  

}

回答by Fatih K?sa

You can use classic login form with 'force_classic_login' parameter.

您可以使用带有“force_classic_login”参数的经典登录表单。

<?php
    $username = "username";
    $password = "password";
    $useragent = "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13";
    $cookie=$username.".txt";

    $url="https://instagram.com/accounts/login/?force_classic_login";

    $ch  = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__)."/".$cookie);
    curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__)."/".$cookie);
    curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

    $page = curl_exec($ch);

    // try to find the actual login form
    if (!preg_match('/<form method="POST" id="login-form" class="adjacent".*?<\/form>/is', $page, $form)) {
        throw Instagram_Manager('Failed to find log in form!');
    }

    $form = $form[0];

    // find the action of the login form
    if (!preg_match('/action="([^"]+)"/i', $form, $action)) {
        throw Instagram_Manager('Failed to find login form url');
    }

    $url2 = $action[1]; // this is our new post url
    // find all hidden fields which we need to send with our login, this includes security tokens
    $count = preg_match_all('/<input type="hidden"\s*name="([^"]*)"\s*value="([^"]*)"/i', $form, $hiddenFields);

    $postFields = array();

    // turn the hidden fields into an array
    for ($i = 0; $i < $count; ++$i) {
        $postFields[$hiddenFields[1][$i]] = $hiddenFields[2][$i];
    }

    // add our login values
    $postFields['username'] = $username;
    $postFields['password'] = $password;

    $post = '';

    // convert to string, this won't work as an array, form will not accept multipart/form-data, only application/x-www-form-urlencoded
    foreach($postFields as $key => $value) {
        $post .= $key . '=' . urlencode($value) . '&';
    }

    $post = substr($post, 0, -1);

    // set additional curl options using our previous options
    curl_setopt($ch, CURLOPT_URL, "https://instagram.com/".$url2);
    curl_setopt($ch, CURLOPT_REFERER, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
   $page = curl_exec($ch);

    // connect to profile edit page
    $url="https://instagram.com/accounts/edit/";
    curl_setopt($ch, CURLOPT_URL, $url);
    echo curl_exec($ch);    
?>