【问题标题】:Accessing a web site via web scrape通过网络抓取访问网站
【发布时间】:2023-03-17 23:11:01
【问题描述】:

在尝试网络抓取 Rubies 时,我无法通过登录。我完全不知道为什么我不能,但这里是我正在使用的 cURL 选项。如果有人看到问题,我将不胜感激!

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 次。一次到帐户页面,然后返回登录。如果有人能告诉我发生了什么,我将不胜感激。我认为他们正在使用某种基本的身份验证系统。

【问题讨论】:

    标签: php curl web-scraping


    【解决方案1】:

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

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

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

    【讨论】:

    • 实际上,关于网站,根据我的经验,在 99% 的情况下,chrome 的开发工具的“网络”选项卡就足够了 :)(如果不是,如您所说,Fiddler)
    • 同意,我主要首先使用 Chrome 的 F12 来处理浏览器流量,因为它更易于阅读。但这不会显示流量的 cURL 版本。
    【解决方案2】:

    你犯了几个错误。

    您对服务器说您的 POST 正文是 application/x-www-form-urlencoded 编码的,但是您给 CURLOPT_POSTFIELDS 一个数组,所以您实际上发送到服务器的内容是 multipart/form-data 编码的。让 curl 以application/x-www-form-urlencoded 发送帖子数据,对CURLOPT_POSTFIELDS 的数据进行urlencode - 具体来说,使用数组,http_build_query 将为您执行此操作。此外,在执行multipart/form-dataapplication/x-www-form-urlencoded 时使用POST,根本不要设置内容类型标头,curl 会自动为您执行此操作,具体取决于使用的编码。在那一点上,您也不应该手动设置User-Agent 标头,而应使用CURLOPT_USERAGENT。而且您也不应该设置 Host 标头,curl 会自动生成它,而且您比 curl 更有可能犯错误。 还有,这里你发送一个假的Referer header,有些网站可以检测到referer是假的,设置CURLOPT_AUTOREFERER比较安全,然后发出一个真实的请求,从而获得一个真实的referer。此外,要实际登录 https://www.rubies.com/customer/account/loginPost/ ,您需要一个 cookie 会话和一个 form_key 代码,form_key 可能与您的 cookie 会话相关联,并且可能是一种 CSRF 令牌,但您没有提供代码获取任何一个。最重要的是,您可能需要一个真实的referer

    使用来自 https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php 的 hhb_curl , 这是我认为可以使用真实用户名/密码登录的示例代码,不会出现我上面列出的错误:

    <?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 () );
    

    编辑:修复了一个 url,原来的代码肯定行不通,但现在应该可以了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 2019-03-31
      • 1970-01-01
      • 1970-01-01
      • 2017-10-16
      • 1970-01-01
      相关资源
      最近更新 更多