如何加快这个卷曲脚本的报废?

时间:2017-03-28 13:36:05

标签: php csv curl web-scraping simple-html-dom

我正在使用curl使用“PHP Simple HTML DOM Parser”来删除页面内容。我必须废弃数千页,因此我的代码需要花费大量时间执行。如果有人能指出如何加快这一点,那就太好了。

这是我到目前为止所做的。

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

function do_it_with_curl($url)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);    
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $server_output = curl_exec ($ch);
    $error = curl_error($ch);
    $errno = curl_errno($ch);
    curl_close ($ch);
    return str_get_html($server_output);
}

function check_response_object( $str_obj, $type )
{
    if(is_object( $str_obj ))
    {
        if( $type == 'url' )
        {
            return $str_obj->href;
        } else if ( $type == 'text')
        {
            return $str_obj->plaintext;
        }
    } else 
    {
        return false;
    }
}
$scrap_url = '';
$scrap_err = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") 
{
    if (empty($_POST["scrap_url"])) 
    {
        $scrap_err = "URL is required";
    } else 
    {
        $scrap_url = $_POST["scrap_url"];
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename=yellow-pages.csv');
        $output = fopen('php://output', 'w');
        fputcsv( $output, array( 'Name', 'Website', 'Email', 'Phone', 'Address', 'Reference URL' ) );
        $url = $scrap_url;
        do 
        {
            $html = do_it_with_curl($url);
            $next_page = check_response_object( $html->find('[rel="next"]', 0), 'url' );
            $results = $html->find('div.organic div.result');
            foreach( $results as $single_result )
            {
                $item = array();
                $next_url = check_response_object( $single_result->find('a.business-name', 0), 'url' );
                $next_html = do_it_with_curl( $next_url );
                if( $next_html )
                {
                    $item['name'] = check_response_object( $next_html->find('h1[itemprop="name"]', 0 ), 'text' );
                    $item['website'] = check_response_object( $next_html->find('a.website-link', 0 ), 'url' );
                    $item['email'] = substr( check_response_object( $next_html->find('a.email-business', 0 ), 'url' ) , 7 ) ;
                    $item['phone'] = check_response_object( $next_html->find('p.phone', 0 ), 'text' );
                    $item['address'] = check_response_object( $next_html->find('h2[itemprop="address"]', 0 ), 'text' );
                    $item['ypref'] = strtok( $next_url, '?' );
                }
                fputcsv( $output , $item );
            }
            $url = $next_page;
        } while ($next_page);
        exit();
    }
}
?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">  
    URL: 
    <input type="text" name="scrap_url" value="<?php echo $scrap_url;?>" style="width:80%;">
    <span class="error">* <?php echo $scrap_err;?></span>
    <br><br>
    <input type="submit" name="submit" value="Submit">  
</form>

1 个答案:

答案 0 :(得分:0)

瓶颈不是cURL。这是您的抓取操作顺序。如果要抓取数千个网页,则会从获取网页的HTTP请求,读取HTML的解析操作以及将结果保存为CSV的文件操作中获得一些延迟。

通过从cURL切换到其他机制,您不会获得太多性能提升。更好的方法是使您的算法多线程,以便在并行中进行抓取操作。

您可以使用pthreads

在PHP中执行多线程处理
  

pthreads是面向对象的API,允许在PHP中进行用户域多线程。它包括创建针对Web或控制台的多线程应用程序所需的所有工具。 PHP应用程序可以创建,读取,写入,执行和与Threads,Workers和Stackables同步。

你可以创建一个ThreadPool,例如20个线程,并有一个单独的线程来处理你的循环中的每个结果

foreach( $results as $single_result ) {...}

您可以在PHP documentation中找到一个简单的多线程和线程池示例。您可以通过Google搜索找到更多示例。