1

CURL_MULTI 関数でダウンロードするページ上のリンクを探す PHP スクリプトがあります。ダウンロードは正常に行われ、データは取得されますが、URL が非リンクとしてリストされているページに遭遇すると、スクリプトがランダムにクラッシュします。これはコードです:

$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";

これにより、HTML の href タグ内にある google.com の 2 番目の出現位置が検出されます。問題は、クラッシュの前にエラーが報告されないことです。私のエラー設定:

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

私のhandle_errors()関数はすべてのエラーをファイルに記録します。ただし、スクリプトがクラッシュする前にエラーは報告されません。また、curl_multi は多くの URL を処理し、特定の URL でクラッシュすることもあれば、別の URL でクラッシュすることもあります。午前。もう 1 つの注意点は、while ループを削除してもクラッシュしないことです。また、ページの URL が最初に href タグに含まれていてもクラッシュしません。このことを理解するのを手伝ってください。どうもありがとう!

4

2 に答える 2

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.";
于 2011-09-07T04:38:51.733 に答える
0

必要以上に難しくしていると思います。Ifrev_strposは検索文字列の最後のインスタンスを返すためだけに必要であり、 case を気にしない場合strriposは代わり に使用してください。

PHPドキュメントから...

strripos — 文字列内で大文字と小文字を区別しない文字列が最後に出現した位置を見つける

説明

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

文字列内で文字列が最後に出現する位置を検索します。strrpos() とは異なり、strripos() は大文字と小文字を区別しません。

大文字と小文字を区別する必要がある場合、または何らかの理由で独自の関数を使用したい場合、問題はオフセットの計算方法にあります。具体的には、次の 2 行で:

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

サンプル「Some text...」を使用して「google.com」を検索すると、オフセットを指定しない場合、オフセットは長さ (500 文字) - オフセット (0 文字) - 1 として計算されます。次に、strpos を使用します。オフセット文字 499 から始まる 500 文字の長さの文字列。そのように何かを見つけることは決してありません。

干し草の山と針を逆にしているので、オフセットを「逆にする」必要があります。行を次のように変更します。

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

(実際には、前の行を変更して、必要な場所で $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ループのギミックよりも好ましいはずです。

于 2011-09-07T05:40:15.613 に答える