使用CURL登录PHP不起作用

使用CURL登录PHP不起作用,php,curl,Php,Curl,我想登录bukalapak.com网站,但我遇到了问题,在执行此php后,我得到了一个空白页面,下面是我的代码: var_dump(login_bukalapak()); function login_bukalapak(){ $data_login = array( 'user_session[username]' => 'myusername', 'user_session[password]' => 'mypassword' );

我想登录bukalapak.com网站,但我遇到了问题,在执行此php后,我得到了一个空白页面,下面是我的代码:

var_dump(login_bukalapak());
function login_bukalapak(){
    $data_login = array(
        'user_session[username]' => 'myusername',
        'user_session[password]' => 'mypassword'
    );
    $url = "https://www.bukalapak.com/user_sessions";
    $ch = curl_init();    
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    $cookie = 'cookies.txt';
    $timeout = 30;

    curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout );
    curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
    curl_setopt ($ch, CURLOPT_POST, 1); 
    curl_setopt ($ch, CURLOPT_POSTFIELDS,$data_login);
    $result = curl_exec($ch);

    /*$url = "https://www.bukalapak.com/products/new?from=dropdown";
    curl_setopt ($ch, CURLOPT_POST, 0); 
    curl_setopt($ch, CURLOPT_URL, $url);
    $result = curl_exec($ch);*/

    curl_close($ch); 
    return $result;
}
我搞不清楚我刚才有没有返回空白,如何正确回答才能使它运行良好并返回成功登录?
谢谢。

你在这里做了很多错事

1:他们的登录系统对登录POST请求主体使用application/x-www-form-urlencoded编码,但您的代码尝试使用多部分/表单数据编码登录

2:他们的登录系统要求您在登录之前拥有一个预先存在的cookie会话,但是您的代码在发送登录请求之前没有获得cookie会话

3:他们使用CSRF令牌方案来保护他们的登录,您需要从页面获取CSRF令牌,并在发送登录请求之前将其添加到您的登录帖子字段中,称为
真实性\u令牌
(在他们的html中为
),您的代码在登录之前不会尝试获取和提取此令牌

4:您缺少一系列登录参数,即
utf8
user\u session[记住我]
come
按钮
,正如我前面所说,
authenticity\u token
-可能不需要所有这些参数,或者可能需要所有参数,但至少需要其中一些参数(
authenticity\u token
)100%肯定是必需的,只需将它们全部添加,除非您想浪费时间弄清楚哪些参数是必需的,哪些参数不是必需的,否则这可能不值得付出努力

5:您的代码缺少错误检查,如果设置设置有问题,curl_setopt返回bool(false);如果传输过程中出现问题,curl_exec返回bool(false)

考虑到这一点,下面是一个示例实现,我认为它可以使用真实的用户名/密码:

<?php
require_once ('hhb_.inc.php');
$hc = login_bukalapak ( "foo@bar.com", "password" );
var_dump ( $hc->exec ( 'https://www.bukalapak.com/' )->getStdOut () );
function login_bukalapak(string $username, string $password): \hhb_curl {
    $hc = new hhb_curl ( '', true );
    $html = $hc->exec ( 'https://www.bukalapak.com/' )->getStdOut ();
    $domd = @DOMDocument::loadHTML ( $html );
    $data_login = getDOMDocumentFormInputs ( $domd, true, false ) ['new_user_session'];
    // var_dump ( $data_login ) & die ();
    assert ( isset ( $data_login ['user_session[username]'], $data_login ['user_session[password]'] ), 'username/password field not found in login form!' );
    $data_login ['user_session[username]'] = $username;
    $data_login ['user_session[password]'] = $password;
    $url = "https://www.bukalapak.com/user_sessions";

    $html = $hc->setopt_array ( array (
            CURLOPT_URL => 'https://www.bukalapak.com/user_sessions',
            CURLOPT_POST => 1,
            CURLOPT_POSTFIELDS => http_build_query ( $data_login ) 
    ) )->exec ()->getStdOut ();
    //var_dump ( $html );
    $domd = @DOMDocument::loadHTML ( $html );
    $xp = new DOMXPath ( $domd );
    $loginErrorEles = $xp->query ( '//*[contains(@class,"__error") and not(contains(@class,"hidden"))]' );
    $loginErrors = '';
    foreach ( $loginErrorEles as $loginError ) {
        if (empty ( $loginError->textContent )) {
            continue;
        }
        $loginErrors .= trim ( $loginError->textContent );
    }
    if (! empty ( $loginErrors )) {
        throw new RuntimeException ( 'failed to log in: '.$loginErrors);
    }
    // assuming logged in successfully
    // note that its highly unreliable, they sometimes say "wrong username/password", and someitmes not, seemingly randomly.
    return $hc;
}
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false, bool $getElements = true): array {
    // :DOMNodeList?
    if (! $getOnlyFirstMatches && ! $getElements) {
        throw new \InvalidArgumentException ( '!$getElements is currently only implemented for $getOnlyFirstMatches (cus im lazy and nobody has written the code yet)' );
    }
    $forms = $domd->getElementsByTagName ( 'form' );
    $parsedForms = array ();
    $isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool {
        $parent = $decendant;
        while ( NULL !== ($parent = $parent->parentNode) ) {
            if ($parent === $ele) {
                return true;
            }
        }
        return false;
    };
    // i can't use array_merge on DOMNodeLists :(
    $merged = function () use (&$domd): array {
        $ret = array ();
        foreach ( $domd->getElementsByTagName ( "input" ) as $input ) {
            $ret [] = $input;
        }
        foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) {
            $ret [] = $textarea;
        }
        foreach ( $domd->getElementsByTagName ( "button" ) as $button ) {
            $ret [] = $button;
        }
        return $ret;
    };
    $merged = $merged ();
    foreach ( $forms as $form ) {
        $inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array {
            $ret = array ();
            foreach ( $merged as $input ) {
                // hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) );
                if ($input->hasAttribute ( "disabled" )) {
                    // ignore disabled elements?
                    continue;
                }
                $name = $input->getAttribute ( "name" );
                if ($name === '') {
                    // echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL;
                    continue;
                }
                if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) {
                    // echo "this input does not belong to this form.", PHP_EOL;
                    continue;
                }
                if (! array_key_exists ( $name, $ret )) {
                    $ret [$name] = array (
                            $input 
                    );
                } else {
                    $ret [$name] [] = $input;
                }
            }
            return $ret;
        };
        $inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax.
        $hasName = true;
        $name = $form->getAttribute ( "id" );
        if ($name === '') {
            $name = $form->getAttribute ( "name" );
            if ($name === '') {
                $hasName = false;
            }
        }
        if (! $hasName) {
            $parsedForms [] = array (
                    $inputs 
            );
        } else {
            if (! array_key_exists ( $name, $parsedForms )) {
                $parsedForms [$name] = array (
                        $inputs 
                );
            } else {
                $parsedForms [$name] [] = $tmp;
            }
        }
    }
    unset ( $form, $tmp, $hasName, $name, $i, $input );
    if ($getOnlyFirstMatches) {
        foreach ( $parsedForms as $key => $val ) {
            $parsedForms [$key] = $val [0];
        }
        unset ( $key, $val );
        foreach ( $parsedForms as $key1 => $val1 ) {
            foreach ( $val1 as $key2 => $val2 ) {
                $parsedForms [$key1] [$key2] = $val2 [0];
            }
        }
    }
    if ($getElements) {
        return $parsedForms;
    }
    $ret = array ();
    foreach ( $parsedForms as $formName => $arr ) {
        $ret [$formName] = array ();
        foreach ( $arr as $ele ) {
            $ret [$formName] [$ele->getAttribute ( "name" )] = $ele->getAttribute ( "value" );
        }
    }
    return $ret;
}

他们允许自动登录吗?@rlfm是的,他们不支持他们的服务条款says@rtfm真的吗?我在他们的TOS中找不到任何相关的部分,我只找到了一个基本上说“TOS也适用于bupalak应用程序”的部分(可能是指一些智能手机应用程序),当你说他们不允许时,你指的是哪一部分?从阅读TOS中我可以看出,他们根本没有任何关于它的政策。嗨,谢谢你的回答,我在HP Parse error中遇到了错误:语法错误,意外的“:”,期待“{'in':\hhb_curl'在直线上5@CSMMedia这是因为您试图在php5.x中运行它-这段代码是为PHP7编写的-我如何仅为特定文件PHP运行PHP7?@CSMMedia google it-一种方法是为*.PHP文件和*.PHP7文件设置不同的fpm处理程序,并让php5.6-fpm和PHP7.0-fpm同时运行,grea工作对于我来说,在nginx+php fpm-.php文件中,t作为php5执行,.php7文件作为php7执行