簡體   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