网上找了一个利用simple_html_dom分析每个网页上所有图片地址,得出最大图片的代码。
我把它结合到MYSQL QUERY里,(从数据库调出一组URL地址,逐个进行每个页面最大图片的解析,然后输出结果,考虑结果写进外部文件json.txt里)但是发现,如果URL地址过多的话,会出现 Fatal error: Out of memory 的错误。虽然可以通过调整PHP.INI的设置,提高内存。但是个人感觉,这个分析过程相当长,如果长时间占用内存,对服务器的性能相当不利。求教高手,是否有办法在在每次FOREACH之后,清除内存?因为每个URL分析完图片大小后,已经FWRITE进外部json.txt文档里,前面分析的数据完全可以清楚掉。求解决问题的代码。谢谢。
<?php
require_once 'simple_html_dom.php';
...//mysql query
while ($row = mysql_fetch_array($result))
{
$url = $row['url']; //'http://news.csdn.net/';
$biggestImage = '';
// process
$maxSize = -1;
$html = file_get_html($url);
// base url
foreach($html->find('img') as $element) {
$pic = $element->src;
if($pic=='')continue;// it happens on your test url
$image=@getimagesize($pic);// get the rest images width and height
if (($image[0] * $image[1]) > $maxSize) {
$maxSize = $image[0] * $image[1]; //compare images' sise
$biggestImage = $pic;
}
}
echo '<img src="'.$biggestImage.'" />'; //echo the biggest one, fwrite in json.txt
}
?>
我把它结合到MYSQL QUERY里,(从数据库调出一组URL地址,逐个进行每个页面最大图片的解析,然后输出结果,考虑结果写进外部文件json.txt里)但是发现,如果URL地址过多的话,会出现 Fatal error: Out of memory 的错误。虽然可以通过调整PHP.INI的设置,提高内存。但是个人感觉,这个分析过程相当长,如果长时间占用内存,对服务器的性能相当不利。求教高手,是否有办法在在每次FOREACH之后,清除内存?因为每个URL分析完图片大小后,已经FWRITE进外部json.txt文档里,前面分析的数据完全可以清楚掉。求解决问题的代码。谢谢。
<?php
require_once 'simple_html_dom.php';
...//mysql query
while ($row = mysql_fetch_array($result))
{
$url = $row['url']; //'http://news.csdn.net/';
$biggestImage = '';
// process
$maxSize = -1;
$html = file_get_html($url);
// base url
foreach($html->find('img') as $element) {
$pic = $element->src;
if($pic=='')continue;// it happens on your test url
$image=@getimagesize($pic);// get the rest images width and height
if (($image[0] * $image[1]) > $maxSize) {
$maxSize = $image[0] * $image[1]; //compare images' sise
$biggestImage = $pic;
}
}
echo '<img src="'.$biggestImage.'" />'; //echo the biggest one, fwrite in json.txt
}
?>
unset($biggestImage,$html,$element,$image,$url);
}
这个代码没什么可以优化的, 也许你的内存真的不够用, 或许问题不是出在这几行代码里。
就知道这段程序是不是真的吃内存如果本身变量就那么大, 程序上而言, 没得优化。
$html->__destruct();嗯,又查了它的手册: 可以用clear
http://simplehtmldom.sourceforge.net/manual_faq.htm#memory_leak这个问题是因为php5对象都用reference,所以循环里不会立即释放占用的内存(需要等到gc运行)
...
$html = file_get_html($url);
// base url
foreach($html->find('img') as $element) {
...先检查 $html 是否占用大量内存
$memo = memory_get_usage();
$html = file_get_html($url);
echo memory_get_usage() - $memo;
如果的确是的话,可以这样做:
$html = file_get_html($url);
// base url
$tmp = $html->find('img');
unset($html);
foreach($tmp as $element) {同样可用这种方法检查其他部位
$html->__destruct();
或 $html->clear();放在你的while循环的结束之前, 就是那个 } 之前. 如果还有问题, 用楼上唠叨的方法慢慢调试,找到有问题的地方.它那个html是很占内存的,因为把整个页面都dom展开了,里面N个嵌套的simple_html_dom对象,
但是只要每次循环释放掉, 就应该没有问题.
foreach($html->find('img') as $element) {===========================================
这样写代码本身就很吃内存,
1. 每次循环都重新初始化一个类
2. 对象放在循环语句中===========================================
客观情况, 应该这样优化代码$html = file_get_html($url);
这行放在while循环上面, 如
$html = init_html();
while () {
.....然后在这个$html对象的类中增加一个get_html的方法实现file_get_html的功能,如
用这行 $html->get_html($url); 代替 file_get_html($url); 这样改了之后, 保证你的内存用少一半以上。
从你写代码的风格, 估计你在这行里重新定义了很多次类。
如果是, 用10楼的解决方法, unset()这个是治标不治本的下策
他的代码显然是套用了 simple_html_dom 的样例程序
如果是自己写的,那些注释显然是不必要的
这个任务留給楼主自己学习吧function file_get_html() { $dom = new simple_html_dom; $args = func_get_args(); $dom->load(call_user_func_array('file_get_contents', $args), true); return $dom;}
$html = file_get_html($url);
$html = init_html();
while($row = mysql_fetch_array($qry)){
$url = $row['url'];
$biggestImage = '';
// process
$maxSize = -1;
// base url
$memo = memory_get_usage();
$html->get_html($url);
foreach($html->find('img') as $element) {
$pic = $element->src;
if($pic=='')continue;// it happens on your test url
$image=@getimagesize($pic);// get the rest images width and height
if (($image[0] * $image[1]) > $maxSize) {
$maxSize = $image[0] * $image[1]; //compare images' sise
$biggestImage = $pic;
}
}
echo strlen($biggestImage);
echo '<img src="'.$biggestImage.'" />'; //echo the biggest one
$html->clear();
unset($html);
echo memory_get_usage() - $memo;
}echo memory_get_usage() - $memo; 每个foreach后得出的值:
2272
-176
-40
86504
2080
2176
456
2104
40
104
...为什么会有正有负?还有,一个没图片的网址,惊人的占了 86504
@coolesting
$html = init_html(); 怎么用,提示 Fatal error: Call to undefined function init_html();
4888
2384
14040776
4131232
3650904
4850408
2446184
2249304
2246296
数值要大很多很多……那个unset,真的可以清除部分内存?
echo memory_get_usage() - $memo;
=================================
1. echo 1111 - 2222; //这是内存负号的原因
2. 另外那个86504 也可能是前面几个变量的叠加数, 不单指你一个url得来的值
3. 我上面说的那二个方法是叫你学习去写的, 本身没有的 (O_o)
#14楼的方法最好吗?我想不占很多内存,而且速度也不要太慢。(我已经嫌我的速度太慢了,嫌getimagesize分析照片大小的效率太低……)
用FOR代码FOREACH的话,看上去占有内存少,但运行时间越长,其实对服务器资源,也是一种消耗。
一个网页不可能只有 img 标记吧?
其他标记他也要分析,而并不管你是否需要