繁体   English   中英

如何在PHP中使用cURL抓取的网站上正确跟踪所有重定向?

[英]How can I properly follow all redirects on sites I am trying to scrape with cURL in PHP?

我正在使用cURL尝试抓取不在服务器上的ASP站点,并使用以下选项自动跟踪遇到的重定向:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

但它并没有正确遵循网站发送回的所有重定向:它会将一些重定向URL相对于我的服务器和PHP脚本的路径,而不是相对于网站的服务器和网站页面应相对的路径。 有什么方法可以在cURL中设置基本路径或服务器路径,以便我的脚本可以正确地跟踪通过其他网站抓取时遇到的相对重定向?

例如:如果我在他们的网站身份验证,然后尝试访问“ https://www.theirserver.com/theirapp/mainForm/securepage.aspx在“”与我的脚本https://www.myserver.com/php/ myscript.php “,那么在某些情况下,他们的网站会尝试将其重定向回其登录页面,但这会引起一个大问题,因为重定向会将我的cURL客户端发送到” https://www.myserver.com/php/ mainForm / login.aspx ”,即相对于我服务器上脚本的'/mainForm/login.aspx',而不是相对于正确的“ https://www.theirserver.com/theirapp/mainForm/login.aspx ”的相对位置到我在其服务器上抓取的网站。

我希望cURL的FOLLOWLOCATION选项能够根据我正在访问的网页的“ Location:”标头正确地遵循相对重定向,但似乎没有,而且也没有。 既然这似乎行不通,最好是我想要一种方法来告诉cURL服务器或其看到的所有相对重定向的基本路径,因此我可以只使用FOLLOWLOCATION 如果不是,那么我需要找出一些代码来完成FOLLOWLOCATION工作,但是这可以让我指定一个基本路径来处理这些相对URL。

我看到了几个类似的问题,这些问题涉及使用cURL遵循相对路径,但是没有一个答案可以很好地解决这个问题,因为我不拥有网站的服务器,也不知道可能会出现每个重定向。 实际上,对于类似问题,我所见的任何答案都似乎都没有理解,一个人可能正在尝试抓取外部网站,并且希望他们在抓取该网站时遇到的任何相对重定向都只是相对于该网站。

编辑:这是有问题的代码:

$urlLogin = "https://www.theirsite.com/theirApp/MainForm/login.aspx"
$urlSecuredPage = "https://www.theirsite.com/theirApp/ContentPages/content.aspx"
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $urlLogin);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; MSIE 9.0;   Windows NT 6.1; Trident/5.0; yie8)");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);

// GET login page
$data=curl_exec($ch);

// Read ASP viewstate and eventvalidation fields
$viewstate = parseExtract($data,$regexViewstate, 1);
$eventval = parseExtract($data, $regexEventVal, 1);

//set POST data
$postData = '__EVENTTARGET='.$eventtarget
      .'&__EVENTARGUMENT='.$eventargument
      .'&__VIEWSTATE='.$viewstate
      .'&__EVENTVALIDATION='.$eventval
      .'&'.$nameUsername.'='.$valUsername
      .'&'.$namePassword.'='.$valPassword
      .'&'.$nameLoginBtn.'='.$valLoginBtn;

// POST authentication
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_URL, $urlLogin);   
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);     
$data = curl_exec($ch);

/****************************************************************** 
 GET secure page  (This is where a redirect fails... when getting
 the secure page, it redirects to /mainForm/login.aspx relative to my 
 script, instead of /mainForm/login.aspx on their site.
*****************************************************************/
curl_setopt($ch, CURLOPT_POST, FALSE);
curl_setopt($ch, CURLOPT_URL, $urlSecuredPage);   
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile);     
$data = curl_exec($ch);

echo $data;  // Page Not Found

您可能会遇到作为JavaScript重定向的重定向。

要找出那里是什么:

这将为您提供更多信息。

curl_setopt($ch, CURLOPT_FILETIME, true); 

您应该设置失败失败:

curl_setopt($ch, CURLOPT_FAILONERROR,true);

您可能还需要查看所有Request和Response标头:

  curl_setopt($ch, CURLOPT_HEADER, true);
  curl_setopt($ch, CURLINFO_HEADER_OUT, true);

您缺少的最大的东西是curl_getinfo($ch);
它具有有关所有重定向和标头的信息。

您可能要关闭: CURLOPT_FOLLOWLOCATION

并单独执行每个请求。 您可以从curl_getinfo("redirect_url")获取重定向位置

或者,您可以将CURLOPT_MAXREDIRS设置为成功重定向的数量,然后对问题重定向位置进行单独的curl请求

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

当您获得响应时,如果没有卷曲错误,请获取resposne标头

  $data = curl_exec($ch);
  if (curl_errno($ch)){
      $data .= 'Retreive Base Page Error: ' . curl_error($ch);
      echo $data;
  }
  else {
    $skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE)); 
    $responseHeader = substr($data,0,$skip);
    $data= substr($data,$skip);
    $info = curl_getinfo($ch);
    $info = var_export($info,true);
   }
   echo $responseHeader . $info . $data;

网页抓取网页的更好方法是使用2个PHP程序包= Guzzle + DomCrawler。

通过这种组合,我进行了很多测试,得出的结论是,这是最佳选择。

在这里 ,您将找到实现的示例。

如果您有任何问题,请告诉我! ;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM