2016-08-04 6 views
1

PHPを使用してリモートページを取得しています。そのページからいくつかのリンクを取得し、各リンクにアクセスして解析しています。
これはあまりにも多くの12秒かかる、私は何とかコードを最適化する必要があります。私は、ループ内のいくつかのより多くのpreg_match電話を持っているリモートページの取得と解析の最適化

$result = get_web_page('THE_WEB_PAGE'); 

preg_match_all('/<a data\-a=".*" href="(.*)">/', $result['content'], $matches); 

foreach ($matches[2] as $lnk) { 
    $result = get_web_page($lnk); 

    preg_match('/<span id="tests">(.*)<\/span>/', $result['content'], $match); 

    $re[$index]['test'] = $match[1]; 

    preg_match('/<span id="tests2">(.*)<\/span>/', $result['content'], $match); 

    $re[$index]['test2'] = $match[1]; 

    preg_match('/<span id="tests3">(.*)<\/span>/', $result['content'], $match); 

    $re[$index]['test3'] = $match[1]; 
    ++$index; 
} 


私のコードは、そのようなものです。
コードを最適化するにはどうすればよいですか?

編集:

私の代わりに正規表現のXPathを使用するために自分のコードを変更しました、そして、それははるかに遅くなりました。

EDIT2:

私の完全なコードです

<?php 
$begin = microtime(TRUE); 
$result = get_web_page('WEB_PAGE'); 

$dom = new DOMDocument(); 
$dom->loadHTML($result['content']); 
$xpath = new DOMXPath($dom); 

// Get the links 
$matches = $xpath->evaluate('//li[@class = "lasts"]/a[@class = "lnk"]/@href | //li[@class=""]/a[ @class = "lnk"]/@href'); 
if ($matches === FALSE) { 
    echo 'error'; 
    exit(); 
} 
foreach ($matches as $match) { 
    $links[] = 'WEB_PAGE'.$match->value; 
} 

$index = 0; 

// For each link 
foreach ($links as $link) { 
    echo (string)($index).' loop '.(string)(microtime(TRUE)-$begin).'<br>'; 
    $result = get_web_page($link); 

    $dom = new DOMDocument(); 
    $dom->loadHTML($result['content']); 
    $xpath = new DOMXPath($dom); 

    $match = $xpath->evaluate('concat(//span[@id = "header"]/span[@id = "sub_header"]/text(), //span[@id = "header"]/span[@id = "sub_header"]/following-sibling::text()[1])'); 
    if ($matches === FALSE) { 
     exit(); 
    } 
    $data[$index]['name'] = $match; 

    $matches = $xpath->evaluate('//li[starts-with(@class, "active")]/a/text()'); 
    if ($matches === FALSE) { 
     exit(); 
    } 
    foreach ($matches as $match) { 
     $data[$index]['types'][] = $match->data; 
    } 

    $matches = $xpath->evaluate('//span[@title = "this is a title" and @class = "info"]/text()'); 
    if ($matches === FALSE) { 
     exit(); 
    } 
    foreach ($matches as $match) { 
     $data[$index]['info'][] = $match->data; 
    } 

    $matches = $xpath->evaluate('//span[@title = "this is another title" and @class = "name"]/text()'); 
    if ($matches === FALSE) { 
     exit(); 
    } 
    foreach ($matches as $match) { 
     $data[$index]['names'][] = $match->data; 
    } 

    ++$index; 
} 

?> 
+1

HTMLをパーズするために正規表現を使用するときのトラブルを尋ねます。 (@Tim van Oschの回答を参照)http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags –

+0

http://stackoverflow.com/questions/ 3537641/how-do-you-parse-and-process-html-xml-in-php – AbraCadaver

+0

最初に貪欲な量指定子を使用しているときに、どのように期待される結果を得ようとしていますか? – revo

答えて

2

は、PHPのDOMフレームワークを使用することを検討してください。これは速くなければなりません。

XPathクエリと

使用PHPののDOMDocument:
http://php.net/manual/en/class.domdocument.php

は、より詳細な説明のために月の回答を参照してください。

次のようにも動作しますが、コメントによればあまり好ましくありません。
http://simplehtmldom.sourceforge.net/

の例では、ページ上のすべてのaのタグを取得する:
たとえば 他の人が述べたように

<?php 
    include_once('simple_html_dom.php'); 

    $url = "http://your_url/"; 
    $html = new simple_html_dom(); 
    $html->load_file($url); 

    foreach($html->find("a") as $link) 
    { 
    // do something with the link 
    } 
?> 
+0

外部ライブラリは不要です。 – revo

+0

simple_html_domはあまり単純ではなく、ソースコードが正規表現を大量に使用していることに注意してください。 –

+0

私は自分の答えを編集し、@ Janの答え –

2

が、代わりにパーサーを使用(すなわちDOMDocument)とxpathクエリとそれを組み合わせます。以下の例を考えてみましょう:

<?php 

# set up some dummy data 
$data = <<<DATA 
<div> 
    <a class='link'>Some link</a> 
    <a class='link' id='otherid'>Some link 2</a> 
</div> 
DATA; 

$dom = new DOMDocument(); 
$dom->loadHTML($data); 

$xpath = new DOMXPath($dom); 

# all links 
$links = $xpath->query("//a[@class = 'link']"); 
print_r($links); 

# special id link 
$special = $xpath->query("//a[@id = 'otherid']") 

# and so on 
$textlinks = $xpath->query("//a[startswith(text(), 'Some')]"); 
?> 
+0

私は、正規表現の代わりにxpathを使用するようにコードを変更しました。これははるかに遅くなりました。 – Lior

+0

@Lior:xpathクエリでは、 '/ a 'ではなく'/div/span/p/a'のように具体的にする必要があります。私はもっ​​とロバストな解決策に向かうだろうが、いくらか遅い(1-2秒)。 – Jan

+0

問題は、それがループのforeachリンク内で実行されることです。そのため、繰り返しが繰り返されると、さらに遅くなります。 0ループ1.66981506348 1ループ2.49688410759 2ループ3.00950098038 3ループ3.5253970623 4ループ4.01076102257 5ループ4.67162799835 6ループ5.2378718853 7ループ5.74008488655 8ループ6.26041197777 9ループ6.78747105598 10ループ7.47332000732 11ループ8.03243994713 12ループ8.50538802147 13ループ9.37472701073 14ループ11.5049209595 15ループ12.2112920284 ... 40ループ30.2815680504 41ループ31.1307020187 – Lior

関連する問題