php curl采集页面内容并提取所有的链接
本文承接上面两篇,本篇中的示例要调用到前两篇中的函数,做一个简单的URL采集。一般php采集网络数据会用file_get_contents、file和cURL。不过据说cURL会比file_get_contents、file更快更专业,更适合采集。今天就试试用cURL来获取网页上的所有链接。示例如下:
<?php
/*
* 使用curl 采集111cn.net下的所有链接。
*/
include_once('function.php');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.111cn.net/');
// 只需返回HTTP header
curl_setopt($ch, CURLOPT_HEADER, 1);
// 页面内容我们并不需要
// curl_setopt($ch, CURLOPT_NOBODY, 1);
// 返回结果,而不是输出它
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$html = curl_exec($ch);
$info = curl_getinfo($ch);
if ($html === false) {
echo "cURL Error: " . curl_error($ch);
}
curl_close($ch);
$linkarr = _striplinks($html);
// 主机部分,补全用
$host = 'http://www.111cn.net/';
if (is_array($linkarr)) {
foreach ($linkarr as $k => $v) {
$linkresult[$k] = _expandlinks($v, $host);
}
}
printf("<p>此页面的所有链接为:</p><pre>%s</pre>n", var_export($linkresult , true));
?>
function.php内容如下(即为上两篇中两个函数的合集):
<?php
function _striplinks($document) {
preg_match_all("'<s*as.*?hrefs*=s*(["'])?(?(1) (.*?)\1 | ([^s>]+))'isx", $document, $links);
// catenate the non-empty matches from the conditional subpattern
while (list($key, $val) = each($links[2])) {
if (!empty($val))
$match[] = $val;
} while (list($key, $val) = each($links[3])) {
if (!empty($val))
$match[] = $val;
}
// return the links
return $match;
}
/*===================================================================*
Function: _expandlinks
Purpose: expand each link into a fully qualified URL
Input: $links the links to qualify
$URI the full URI to get the base from
Output: $expandedLinks the expanded links
*===================================================================*/
function _expandlinks($links,$URI)
{
$URI_PARTS = parse_url($URI);
$host = $URI_PARTS["host"];
preg_match("/^[^?]+/",$URI,$match);
$match = preg_replace("|/[^/.]+.[^/.]+$|","",$match[0]);
$match = preg_replace("|/$|","",$match);
$match_part = parse_url($match);
$match_root =
$match_part["scheme"]."://".$match_part["host"];
$search = array( "|^http://".preg_quote($host)."|i",
"|^(/)|i",
"|^(?!http://)(?!mailto:)|i",
"|/./|",
"|/[^/]+/../|"
);
$replace = array( "",
$match_root."/",
$match."/",
"/",
"/"
);
$expandedLinks = preg_replace($search,$replace,$links);
return $expandedLinks;
}
?>
具体想要和file_get_contents做一个比较的话,可以利用linux下的time命令查看两者执行各需多长时间。据目前测试看是CURL更快一些。最后链接下上面两个函数相关介绍。
匹配链接函数: function _striplinks()
相对路径转绝对:function _expandlinks()
file_get_contents函数我们通常是拿来对文件操作了,下面一起来看看file_get_contents函数的高级使用方法吧.
首先解决file_get_contents的超时问题,在超时返回错误后就象js中的settimeout那样进行一次尝试,错误超过3次或者5次后就确认为无法连线伺服器而彻底放弃。
这?就简单介绍两种解决方法:
一、增加超时的时间限制
注意:set_time_limit只是设定你的PHP程式的超时时间,而不是file_get_contents函数读取URL的超时时间。
我一开始以为set_time_limit也能影响到file_get_contents,后来经测试是无效的。真正的修改file_get_contents延时可以用resource $context的timeout参数:
PHP程式码
$opts = array(
'http'=>array(
'method'=>"GET",
'timeout'=>60,
)
);
$context = stream_context_create($opts);
$html =file_get_contents('http://www.111cn.net', false, $context);
fpassthru($fp);
二、多次尝试
PHP程式码
$cnt=0;
while($cnt < 3 && ($str=@file_get_contents('http...'))===FALSE){
$cnt++;
}
以上方法对付超时已经OK了。接下来演示一下用file_get_contents实现Post,如下:
PHP程式码
function Post($url, $post = null){
$context = array();
if (is_array($post)) {
ksort($post);
$context['http'] = array (
'timeout'=>60,
'method' => 'POST',
'content' => http_build_query($post, '', '&'),
);
}
return file_get_contents($url, false, stream_context_create($context));
}
$data = array (
'name' => 'test',
'email' => 'test@gmail.com',
'submit' => 'submit',
);
echo Post('http://www.111cn.net', $data);
注意档案头的Set_time_out否则整个档案都得超时了
在做文件上传时有一个非常必须要做的功能就是上传文件会按日期生成目录并把文件保存在目录下了,下面我来为各位介绍一段php自动创建目录并保存文件函数php保存文件,还可以根据文件路径自动连续创建目录,代码如下(注:PHP要版本5以上):
<?php
/**
* 保存文件
*
* @param string $fileName 文件名(含相对路径)
* @param string $text 文件内容
* @return boolean
*/
function saveFile($fileName, $text) {
if (!$fileName || !$text)
return false;
if (makeDir(dirname($fileName))) {
if ($fp = fopen($fileName, "w")) {
if (@fwrite($fp, $text)) {
fclose($fp);
return true;
} else {
fclose($fp);
return false;
}
}
}
return false;
}
/**
* 连续创建目录
*
* @param string $dir 目录字符串
* @param int $mode 权限数字
* @return boolean
*/
function makeDir($dir, $mode=0755) {
/*function makeDir($dir, $mode="0777") { 此外0777不能加单引号和双引号,
加了以后,"0400" = 600权限,处以为会这样,我也想不通*/
if (!dir) return false;
if(!file_exists($dir)) {
return mkdir($dir,$mode,true);
} else {
return true;
}
}
?>
//以下是测试内容,并调用上面的函数
<?php
$content = '这里是测试内容';
if(saveFile('dir/test.txt',$content)){
echo '写入成功';
}else{
echo '写入失败';
}
?>
注意:makeDir就是一个目录创建函数,我们使用的是递归创建了.
下文给各位介绍一个PHP中number_format函数输出数字格式化,增加千分位符号,如果有需要的朋友可一起来看看.在输出数据到屏幕上显示的时候,如果数据较大,位数较多,看上去会比较费劲,有一种比较直观的方法是使用千分位,也就是每三位数字显示一个逗号,这样可以快速的知道数的大小,不用一位位的去慢慢数了。
令人高兴的是,php中有专门的函数可以完成这个任务,可以在输出数据的时候自动加上千分位。
string number_format ( float number [, int decimals [, string dec_point, string thousands_sep]] )
number_format有四个参数,第一个参数是要输出的数字(浮点类型),这个参数是必需的,后面三个参数为可选的,其中后面两个参数要么全没有,要么全提供
number 必需。要格式化的数字。如果未设置其他参数,则数字会被格式化为不带小数点且以逗号 (,) 作为分隔符。
decimals 可选。规定多少个小数。如果设置了该参数,则使用点号 (.) 作为小数点来格式化数字。
decimalpoint 可选。规定用作小数点的字符串。
separator 可选。规定用作千位分隔符的字符串。仅使用该参数的第一个字符。比如 “xyz” 仅输出 “x”。
string number_format(
float number, //要输出的数字
int decimals, //小数位的位数,默认为0
string dec_point, //小数点的表示,默认为.
string thousands_sep //千分位的表示,默认为,
)
下面搞个例子试试
echo number_format('1234.56');
echo number_format('1234.56',1);
echo number_format('1234.56',2);
echo number_format('1234.56',3);
echo number_format('1234.56',2,'-','/');
结果如下
1,235 // 四舍五入
1,234.6 //
1,234.56 //
1,234.560 // 小数位不足,补充0
1/234-56 // 千分位符号变成/,小数点符号变为-
例子
number_format
<?php
$number = 1234.56;
// english notation (default)
$english_format_number = number_format($number);
// 1,235
// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
// 1 234,56
$number = 1234.5678;
// english notation without thousands seperator
$english_format_number = number_format($number, 2, '.', '');
// 1234.57
?>
记得以前的港片《杀手之王》有一个镜头,就是用计算机判断一个照片和杀手留下的背影照片的相似度,现在我们来分享一个PHP简单的图片相似度比较类。由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
代码如下 | 复制代码 |
<?php /** * 图片相似度比较 * * @version $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax $ * @author jax.hu * * <code> * //Sample_1 * $aHash = ImageHash::hashImageFile('wsz.11.jpg'); * $bHash = ImageHash::hashImageFile('wsz.12.jpg'); * var_dump(ImageHash::isHashSimilar($aHash, $bHash)); * * //Sample_2 * var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg')); * </code> */ class ImageHash { /**取样倍率 1~10 * @access public * @staticvar int * */ public static $rate = 2; /**相似度允许值 0~64 * @access public * @staticvar int * */ public static $similarity = 80; /**图片类型对应的开启函数 * @access private * @staticvar string * */ private static $_createFunc = array( IMAGETYPE_GIF =>'imageCreateFromGIF', IMAGETYPE_JPEG =>'imageCreateFromJPEG', IMAGETYPE_PNG =>'imageCreateFromPNG', IMAGETYPE_BMP =>'imageCreateFromBMP', IMAGETYPE_WBMP =>'imageCreateFromWBMP', IMAGETYPE_XBM =>'imageCreateFromXBM', ); /**从文件建立图片 * @param string $filePath 文件地址路径 * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false * */ public static function createImage($filePath){ if(!file_exists($filePath)){ return false; } /*判断文件类型是否可以开启*/ $type = exif_imagetype($filePath); if(!array_key_exists($type,self::$_createFunc)){ return false; } $func = self::$_createFunc[$type]; if(!function_exists($func)){ return false; } return $func($filePath); } /**hash 图片 * @param resource $src 图片 resource ID * @return string 图片 hash 值,失败则是 false * */ public static function hashImage($src){ if(!$src){ return false; } /*缩小图片尺寸*/ $delta = 8 * self::$rate; $img = imageCreateTrueColor($delta,$delta); imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src)); /*计算图片灰阶值*/ $grayArray = array(); for ($y=0; $y<$delta; $y++){ for ($x=0; $x<$delta; $x++){ $rgb = imagecolorat($img,$x,$y); $col = imagecolorsforindex($img, $rgb); $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF; $grayArray[] = $gray; } } imagedestroy($img); /*计算所有像素的灰阶平均值*/ $average = array_sum($grayArray)/count($grayArray); /*计算 hash 值*/ $hashStr = ''; foreach ($grayArray as $gray){ $hashStr .= ($gray>=$average) ? '1' : '0'; } return $hashStr; } /**hash 图片文件 * @param string $filePath 文件地址路径 * @return string 图片 hash 值,失败则是 false * */ public static function hashImageFile($filePath){ $src = self::createImage($filePath); $hashStr = self::hashImage($src); imagedestroy($src); return $hashStr; } /**比较两个 hash 值,是不是相似 * @param string $aHash A图片的 hash 值 * @param string $bHash B图片的 hash 值 * @return bool 当图片相似则传递 true,否则是 false * */ public static function isHashSimilar($aHash, $bHash){ $aL = strlen($aHash); $bL = strlen($bHash); if ($aL !== $bL){ return false; } /*计算容许落差的数量*/ $allowGap = $aL*(100-self::$similarity)/100; /*计算两个 hash 值的汉明距离*/ $distance = 0; for($i=0; $i<$aL; $i++){ if ($aHash{$i} !== $bHash{$i}){ $distance++; } } return ($distance<=$allowGap) ? true : false; } /**比较两个图片文件,是不是相似 * @param string $aHash A图片的路径 * @param string $bHash B图片的路径 * @return bool 当图片相似则传递 true,否则是 false * */ public static function isImageFileSimilar($aPath, $bPath){ $aHash = ImageHash::hashImageFile($aPath); $bHash = ImageHash::hashImageFile($bPath); return ImageHash::isHashSimilar($aHash, $bHash); } } |
相关文章
- 本文实例讲述了jQuery实现鼠标滑过链接控制图片的滑动展开与隐藏效果。分享给大家供大家参考,具体如下:这里演示jQuery实现鼠标移动到链接上,滑动展开/隐藏图片效果,鼠标放在“上一页”“下一页”上,立即浮现出所对应的图...2015-10-30
- 大家用百度搜索的时候,可能会发现,结果链接用的还是百度的链接,点击之后才会跳转到另外一个页面,另外一个页面的真实链接如何获取到呢?? 通过分析发现: 可以看出,返回...2016-05-19
ASP.NET中iframe框架点击左边页面链接 右边显示链接页面内容
这篇文章主要介绍了ASP.NET中iframe框架点击左边页面链接,右边显示链接页面内容的实现代码,感兴趣的小伙伴们可以参考一下...2021-09-22- 这篇文章主要介绍了python docx的超链接网址和链接文本操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-06
- 今天小编就为大家分享一篇opencv3/C++轮廓的提取与筛选方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
python 利用jieba.analyse进行 关键词提取
这篇文章主要介绍了python 利用jieba.analyse进行关键词提取的方法,帮助大家更好的利用python,感兴趣的朋友可以了解下...2020-12-18- 今天小编就为大家分享一篇Python 实现自动获取种子磁力链接方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-27
- 这篇文章主要介绍了Python提取视频中图片的示例,分别按帧和按秒提取,帮助大家利用python处理视频,获取素材,感兴趣的朋友可以了解下...2020-10-23
- 本篇文章为大家介绍了PHP利用ffmpeg提取视频中音频与视频画面的相关资料,很有参考价值,一起来看一看吧。 前言FFmpeg的名称来自MPEG视频编码标准,前面的“FF”代表...2017-07-06
- 下面小编就为大家介绍C++静态链接与动态链接。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-10-11
- 下面小编就为大家带来一篇浅谈CMake配置OpenCV 时静态链接与动态链接的选择。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
- 这篇文章主要介绍了c语言通过opencv实现轮廓处理与切割,具有一定借鉴价值,需要的朋友可以参考下...2020-04-25
C++获取文件哈希值(hash)和获取torrent(bt种子)磁力链接哈希值
这二个代码一个是获取文件哈希值的,另外一个是获取torrent文件磁力链接的哈希值...2020-04-25- 这篇文章主要介绍了dotnet core链接mongodb代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-25
- 在php中要过滤一些特殊字符或非法字符我们可以有很多的办法,像正则表达式str_replace就是一个不错的办法,像回车,空格,换行都可以用它来解决。 近负责的一个系统模块...2016-11-25
- 帮你的页面瘦身 我们浏览网页实际上是将虚拟主机中的网页内容下载到本地硬盘,再用浏览器解释查看的。下载网页的快慢在显示速度上占了很大比重,所以,网页...2016-09-20
- 下面提供二款关于php正则链接方法,他们可以-取得内容所有链接并且保存到一个数组,当然也可以把链接全部替换哦。 方法一 代码如下 ...2016-11-25
WordPress中获取页面链接和标题的相关PHP函数用法解析
这篇文章主要介绍了WordPress中获取页面链接和标题的相关PHP函数用法解析,分别为get_permalink()和wp_title()函数的使用,需要的朋友可以参考下...2015-12-21使用C# CefSharp Python采集某网站简历并且自动发送邀请短信的方法
这篇文章主要给大家介绍了关于如何使用C# CefSharp Python采集某网站简历并且自动发送邀请短信的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧...2020-06-25- 百度优化之黑链过后伪装友情链接开始流行 站长可学习一下。 关注百度优化的站长都知道,这段时间百度一直在发公告宣称惩罚黑链、链接交易;实际情况确实如此,不少买...2016-10-10