【发布时间】:2015-08-12 17:35:54
【问题描述】:
我正在使用以下脚本从网站获取所有链接。当我设置 $depth = 8 或更少时,此脚本运行良好,但是当我想使用 $depth = 9999 抓取大网站时,它会显示以下错误。
内部服务器错误 服务器遇到内部错误或配置错误,无法完成您的请求。 请通过 webmaster@home.example.com 联系服务器管理员,告知他们此错误发生的时间,以及您在此错误之前执行的操作。 服务器错误日志中可能提供有关此错误的更多信息。 此外,在尝试使用 ErrorDocument 处理请求时遇到 404 Not Found 错误。
我试过 ini_set('max_execution_time', 0);但是还是不行,求大神告诉我怎么一次爬10000多页。
脚本如下
<?php
class crawler
{
protected $_url;
protected $_depth;
protected $_host;
protected $_useHttpAuth = false;
protected $_user;
protected $_pass;
protected $_seen = array();
protected $_filter = array();
public function __construct($url, $depth = 3)
{
$this->_url = $url;
$this->_depth = $depth;
$parse = parse_url($url);
$this->_host = $parse['host'];
}
protected function _processAnchors($content, $url, $depth)
{
$dom = new DOMDocument('1.0');
@$dom->loadHTML($content);
$anchors = $dom->getElementsByTagName('a');
foreach ($anchors as $element) {
$href = $element->getAttribute('href');
if (0 !== strpos($href, 'http')) {
$path = '/' . ltrim($href, '/');
if (extension_loaded('http')) {
$href = http_build_url($url, array('path' => $path));
} else {
$parts = parse_url($url);
$href = $parts['scheme'] . '://';
if (isset($parts['user']) && isset($parts['pass'])) {
$href .= $parts['user'] . ':' . $parts['pass'] . '@';
}
$href .= $parts['host'];
if (isset($parts['port'])) {
$href .= ':' . $parts['port'];
}
$href .= $path;
}
}
// Crawl only link that belongs to the start domain
$this->crawl_page($href, $depth - 1);
}
}
protected function _getContent($url)
{
$handle = curl_init($url);
if ($this->_useHttpAuth) {
curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($handle, CURLOPT_USERPWD, $this->_user . ":" . $this->_pass);
}
// follows 302 redirect, creates problem wiht authentication
// curl_setopt($handle, CURLOPT_FOLLOWLOCATION, TRUE);
// return the content
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
// response total time
$time = curl_getinfo($handle, CURLINFO_TOTAL_TIME);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
return array($response, $httpCode, $time);
}
protected function _printResult($url, $depth, $httpcode, $time)
{
ob_end_flush();
$currentDepth = $this->_depth - $depth;
$count = count($this->_seen);
echo "N::$count,CODE::$httpcode,TIME::$time,DEPTH::$currentDepth URL::$url <br>";
ob_start();
flush();
}
protected function isValid($url, $depth)
{
if (strpos($url, $this->_host) === false
|| $depth === 0
|| isset($this->_seen[$url])
) {
return false;
}
foreach ($this->_filter as $excludePath) {
if (strpos($url, $excludePath) !== false) {
return false;
}
}
return true;
}
public function crawl_page($url, $depth)
{
if (!$this->isValid($url, $depth)) {
return;
}
// add to the seen URL
$this->_seen[$url] = true;
// get Content and Return Code
list($content, $httpcode, $time) = $this->_getContent($url);
// print Result for current Page
$this->_printResult($url, $depth, $httpcode, $time);
// process subPages
$this->_processAnchors($content, $url, $depth);
}
public function setHttpAuth($user, $pass)
{
$this->_useHttpAuth = true;
$this->_user = $user;
$this->_pass = $pass;
}
public function addFilterPath($path)
{
$this->_filter[] = $path;
}
public function run()
{
$this->crawl_page($this->_url, $this->_depth);
}
}
$startURL = 'http://www.example.com/';
$depth = 3;
$username = 'YOURUSER';
$password = 'YOURPASS';
$crawler = new crawler($startURL, $depth);
$crawler->setHttpAuth($username, $password);
// Exclude path with the following structure to be processed
$crawler->addFilterPath('customer/account/login/referer');
$crawler->run();
?>
【问题讨论】:
-
日志说什么? (php 日志或 apache error.log)
-
告诉我你不是想从浏览器运行这个?
-
@tzunghaor 在 error_log.txt 文件中显示以下错误 [12-Aug-2015 19:14:15 UTC] PHP 注意:ob_end_flush():删除和刷新缓冲区失败。在第 85 行 [12-Aug-2015 19:15:26 UTC] PHP 注意:ob_end_flush():删除失败和刷新缓冲区。在第 85 行的 /home/****name/public_html/domain****/index.php 中没有要删除或刷新的缓冲区
-
@rjdown 编码后,我正在浏览器上测试。
-
那些通知告诉你,你在 ob_start() 之前调用 ob_end_flush()。我根本看不出有任何理由使用它们:flush() 就足够了。但是,即使是 flush() 的结果也可能不会立即出现:它也取决于您的服务器和浏览器的缓冲。
标签: php html hyperlink web-crawler