Php 通过web scrape访问网站

Php 通过web scrape访问网站,php,curl,web-scraping,Php,Curl,Web Scraping,在尝试进行web刮取时,我无法通过登录。我完全不知道为什么我不能,但这里是我正在使用的卷曲选项。如果有人看到问题,我将不胜感激 curl_setopt_array($curl, array( CURLOPT_URL => "https://www.rubies.com/customer/account/loginPost/", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURL

在尝试进行web刮取时,我无法通过登录。我完全不知道为什么我不能,但这里是我正在使用的卷曲选项。如果有人看到问题,我将不胜感激

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://www.rubies.com/customer/account/loginPost/",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HEADER => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => array('form_key' => "****", "login[username]" => "****", "login[password]" => "****", "persistent_remember_me" => 'on', "send" => ''),
    CURLOPT_FOLLOWLOCATION => 1,
    CURLOPT_COOKIEFILE => 'cookie.txt',
    CURLOPT_COOKIEJAR => 'cookie.txt',
    CURLOPT_HTTPHEADER => array(
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Host: www.rubies.com',
        'Content-Type: application/x-www-form-urlencoded',
        'Origin: https://www.rubies.com',
        'Referer: https://www.rubies.com/customer/account/',
        'Connection: keep-alive',
        'Cache-Control: no-cache',
        'Upgrade-Insecure-Requests: 1'
    ),
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLINFO_HEADER_OUT => true
));

我目前有硬编码的表单密钥,但我不确定是否需要根据登录更改表单密钥。帖子的回复是空的,但我被重定向了2次。一次转到帐户页面,然后返回登录。如果有人能告诉我发生了什么,我将不胜感激。我认为他们正在使用某种基本的身份验证系统。

使用fiddler2或其他数据包嗅探器来查看请求和响应的cURL流量。将其与使用浏览器的流量进行比较

您可能遗漏了或输入了错误的字段,或者遗漏了后续步骤,如设置cookie和发布其他数据


登录代码通常需要获取登录页面,刮取一次性令牌(随着每个页面请求的变化),然后作为第一步发布。这可能会触发脚本代码来设置cookie和/或自动提交其他数据。

您会犯一些错误

你对服务器说你的帖子正文是
application/x-www-form-urlencoded
编码的,但是你给
CURLOPT_POSTFIELDS
一个数组,所以你实际发送给服务器的是
多部分/表单数据
编码的。要让curl将post数据作为
application/x-www-form-urlencoded
,urlencode为
CURLOPT\u POSTFIELDS
的数据进行编码-具体来说,http\u build\u query将为您执行此操作。此外,在执行
多部分/表单数据
应用程序/x-www-form-urlencoded
时,完全不要设置内容类型标题,curl将自动为您执行此操作,具体取决于使用的编码。注意,您也不应该手动设置
用户代理
标题,而应该使用
CURLOPT_USERAGENT
。您也不应该设置主机的
Host
头,curl会自动生成,您比curl更容易出错。 另外,在这里你发送一个假的
Referer
头,一些网站可以检测到什么时候Referer是假的,只需设置
CURLOPT\u AUTOREFERER
,并发出一个真实的请求,就可以获得一个真实的Referer。另外,要实际登录到
https://www.rubies.com/customer/account/loginPost/
,您需要一个cookie会话和一个
表单密钥
代码,
表单密钥
可能与您的cookie会话绑定,并且可能是一种形式的CSRF令牌,但您没有提供获取这两种密钥的代码。除此之外,您可能还需要一个真正的
推荐人

使用hhb_curl from, 下面是一个示例代码,我认为可以使用真实的用户名/密码登录,不会出现上面列出的错误:

<?php
declare(strict_types = 1);
require_once ('hhb_.inc.php');
$hc = new hhb_curl ();

$hc->_setComfortableOptions ();
$hc->exec ( 'https://www.rubies.com/customer/account/login/' ); // << getting a referer, form_key (csrf token?), and a session.
$domd = @DOMDocument::loadHTML ( $hc->getResponseBody () );
$csrf = NULL;

// extract the form_key
foreach ( $domd->getElementsByTagName ( "form" ) as $form ) {
    if ($form->getAttribute ( "class" ) !== 'form form-login') {
        continue;
    }
    foreach ( $form->getElementsByTagName ( "input" ) as $input ) {
        if ($input->getAttribute ( "name" ) !== 'form_key') {
            continue;
        }
        $csrf = $input->getAttribute ( "value" );
        break;
    }
    break;
}
if ($csrf === NULL) {
    throw new \RuntimeException ( 'failed to extract the form_key token!' );
}

$hc->setopt_array ( array (
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query ( array (
                'form_key' => $csrf,
                'login' => array (
                        'username' => '???',
                        'password' => '???' 
                ),
                'persistent_remember_me' => 'on',
                'send' => ''  // ??
        ) ) 
) );

$hc->exec ( 'https://www.rubies.com/customer/account/login/' );
hhb_var_dump ( $hc->getStdErr (), $hc->getResponseBody () );

事实上,就我的经验而言,99%的时候,chrome的开发工具的网络标签就足够了:)(而且,当你说Fiddler不同意的时候,我通常首先使用chrome的F12来获取浏览器流量,因为它更容易阅读。但这不会显示流量的卷曲版本。