2011-09-07 92 views
1

我有一個PHP腳本,它查找與CURL_MULTI函數一起下載的頁面上的鏈接。下載是好的,我得到的數據,但我的腳本隨機崩潰,當我遇到一個頁面被列爲非鏈接的網址。這是代碼:PHP strpos()崩潰腳本

$fishnof = strpos($nofresult, $supshorturl, 0); 
$return[0] = ''; $return[1] = ''; // always good to cleanset 

// Make sure we grabbed a link instead of a text url(no href) 
if ($fishnof !== false) { 
    $linkcheck = rev_strpos($nofresult,'href',$fishnof); 
    $endthis = false; 
    while($endthis !== true) { 
     if($linkcheck > ($fishnof - 25)){ // 19 accounts for href="https://blog. 25 just in case 
      $endthis = true; 
      break; 
     } 
     $lastfishnof = $fishnof; 
     $fishnof = strpos($nofresult,$supshorturl,$fishnof+1); 
     if($fishnof === false){$fishnof = $lastfishnof;$linkcheck = rev_strpos($nofresult,'href',$fishnof);$endthis = true;break;}// This is the last occurance of our URL on this page 
     if($linkcheck > $fishnof){$linkcheck = rev_strpos($nofresult,'href',$fishnof);$endthis = true;break;} // We went around past the end of the string(probably don't need this)  
     $linkcheck = rev_strpos($nofresult,'href',$fishnof); 
    } 
    if($linkcheck < ($fishnof - 25)){ // 19 accounts for href="https://blog. 25 just in case 
     $return[0] = 'Non-link.'; 
     $return[1] = '-'; 
     $nofresult = NULL; // Clean up our memory 
     unset($nofresult); // Clean up our memory 
     return $return; 
    } 
} 

這是自定義rev_strpos,這只是做一個反向strpos()

// Does a reverse stripos() 
function rev_strpos(&$haystack, $needle, $foffset = 0){ 
    $length = strlen($haystack); 
    $offset = $length - $foffset - 1; 
    $pos = strpos(strrev($haystack), strrev($needle), $offset); 
    return ($pos === false)?false:($length - $pos - strlen($needle)); 
} 

,如果:

$nofresult = ' 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
google.com Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
<a href="http://www.google.com">Google</a> Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text.'; 

$supshorturl = "google.com"; 

這應該找到位置在google.com的第二次發生時,它位於HTML href標記內。問題是,它並沒有在飛機墜毀前報告任何錯誤,我的錯誤設置:

ini_set("display_errors", 1); 
error_reporting(E_ALL & ~E_NOTICE); 
set_error_handler('handle_errors'); 

handle_errors()功能記錄在一個文件中的所有錯誤。但是,在腳本崩潰之前沒有報告錯誤。另外,我的curl_multi處理很多網址,有時它會在某個URL上崩潰,而有時它會在另一個網址上崩潰......我準備好拉出我的頭髮,因爲這看起來像是一個簡單的交易......但在這裏,我上午。另一點需要注意的是,如果我刪除了while循環,則不會崩潰,如果頁面首先在href標記中包含url,那麼它不會崩潰。請幫我把這件事情弄清楚。太感謝了!

+0

如何使用正則表達式來獲取網址? – yoda

+0

我需要在頁面上該URL的位置,而不是URL本身。 –

+0

問題是?您可以完美地使用回調來執行您想要的任何操作。 – yoda

回答

0

我認爲你正在做的比更難它需要。如果rev_strpos僅用於返回搜索字符串的最後一個實例,並且如果您不擔心案例,請改爲使用strripos

從PHP文件...

strripos — Find position of last occurrence of a case-insensitive string in a string

說明在一個字符串的字符串中最後一次出現的

int strripos (string $haystack , string $needle [, int $offset = 0 ]) 

查找位置。與strrpos()不同,strripos()是不區分大小寫的。

如果您需要區分大小寫,或者僅僅因爲某種原因想使用自己的函數,問題就出在您如何計算偏移量。特別是在這兩條線:

$offset = $length - $foffset - 1; 
$pos = strpos(strrev($haystack), strrev($needle), $offset); 

使用您的樣本「的一些文字...」並搜索「google.com」,如果我們不指定偏移它計算偏移量爲長度(500個字) - 偏移量(0字符) - 1.然後,您在500字符長度的字符串上使用strpos,字符串以偏移字符499開始。您永遠不會找到任何這種方式。

既然你正在逆轉你的草垛和你的針,你需要「扭轉」你的抵消。行更改爲:

$pos = strpos(strrev($haystack), strrev($needle), $length - $offset); 

(實際上,你應該改變你的前行計算$偏移,你希望它是,但你明白了吧...)

更新:

繼有關使用正則表達式的建議,這真是微不足道獲得位置:

function getOffsets($url, $baseRegex, $text){ 
    $results = array(); 
    $regex= str_replace('%URL%', $url, $baseRegex); 
    preg_match_all($regex, $text, $matches, PREG_OFFSET_CAPTURE); 

    foreach ($matches[0] as $match) 
     array_push($results, ($match[1] + strpos($match[0], $url))); 

    return $results; 
} 

$linkRegex = '/<a[^>]*href="[^"]*%URL%[^"]*"[^>]*>/i'; 
$linkLocations = getOffsets($url, $linkRegex, $text); 
//Array 
//(
// [0] => 395 
//) 

$anyRegex = '/%URL%/i'; 
$allLocations = getOffsets($url, $anyRegex, $text); 
$nonlinkLocations = array_diff($allLocations, $linkLocations); //all non-links 
//Array 
//(
// [0] => 188 
//) 

這真的應該比rev_strpos & while環噱頭更可取。

+0

感謝您花時間回答這個問題,但您的答案在兩方面都不正確。你推薦的函數「查找最後一次出現的字符串」。我需要它找到抵消的反向刺痛。 補償計算也不正確。由於您正在反向搜索並且給定的偏移量爲0,因此我們正在嘗試搜索過去一個刺痛的開始。數學是正確的。 –

+0

@Serj我的歉意,我可能不明白你的「找到一個反向偏移字符串」的願望。但是,我很確定你的數學不正確。如果你使用你的示例值,你可以用一個500字符的乾草堆搜索一個10字符的針,但是你從499開始。「strpos」搜索的字符串已經被顛倒了,但是它沒有向後搜索,所以它贏得了'當它從字符串的末尾開始時,找不到任何東西。使用'strripos'(或者我建議的修改後的'rev_strpos')確實在偏移395處找到'google.com',這正是它所在的位置。 – Farray

+0

(續)如果您正在查找從「針」文本末端到偏移量的距離,那麼一旦找到起始位置就足夠簡單了。 – Farray

0

問題是這樣的解析錯誤

$nofresult = " 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
google.com Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
<a href="http://www.google.com">Google</a> Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text."; 

...應該是

$nofresult = " 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
google.com Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text. 
<a href=\"http://www.google.com\">Google</a> Some text.Some text. 
Some text.Some text.Some text.Some text.Some text.Some text."; 
+0

$ nofresult實際上是我用multi_curl下載的數據它包含的文本不是由我設置的。 –

+1

@SerjSagan:這是提問者最大的問題。他們不能模擬任何行爲而沒有解析錯誤;) – genesis