最近的一个项目有关网站图标爬取,以是将一些履历点及办理办法分享出来。
favicon图标先容
favicon.ico一样平常用于网站logo标志,它显示在浏览器的地址栏、浏览器标签上或者在收藏夹上,是展示网站个性的缩略logo标志。

浏览器是怎么得到网站图标的?
浏览器首先会剖析要求的网址源代码的head部分,找到带有rel=\"大众icon\"大众属性的link元素,个中href属性便是图标地址,但是并不是所有网站都会设置这一项,有些网站喜好直接将favicon.ico放在根目录下,便于SEO优化。由于搜索引擎爬虫会在网站根目录考试测验要求favicon.ico,久而久之,潜移默化就变成了行业规范。理解了网站图标的获取源后,抓取思路就有了。
暴力要求
不管你网站根目录有没有favicon.ico,我便是要抓,至于能不能抓到,碰尝尝看再说(毕竟这个运气概率还是非常高的)。以我们官网(https://www.kunquer.com)为例,PHP抓取代码如下:
$url = 'https://www.kunquer.com';$content = file_get_contents($url.'/favicon.ico');
请体谅我不把代码一次性放出来,毕竟要讲得详细才够味(还有凑凑文章字数好交差)。怎么判断抓取回来的内容便是图标呢?大概只是一个404页面?保存内容到本地文件后,通过getimagesize()函数就能判断出来:
$file = tmpfile();$path = stream_get_meta_data($file)['uri'];file_put_contents($path, file_get_contents($Pea->url.'/favicon.ico'));var_dump(getimagesize($path));
顺利的话,将会打印出如下内容:
array(6) { [0]=> int(48) [1]=> int(48) [2]=> int(17) [3]=> string(22) \公众width=\"大众48\"大众 height=\"大众48\"大众\"大众 [\"大众bits\"大众]=> int(32) [\"大众mime\"大众]=> string(24) \公众image/vnd.microsoft.icon\"大众 }
以上例子不可能不顺利,由于我们官网根目录下是有这个文件的哈哈哈嗝。为了后续演出(不对是另一种情形)能演示下去,我们以虾米网为例,访问xiami.com/favicon.ico,得到以下回馈:
很好!
我们可以开始下一步了。
剖析网页源码
当暴力要求无果后,只好通过抓取页面,剖析个中源码来获取图标了,由于图标是放在head部分的link中,通过设置rel=\"大众icon\"大众或者 rel=\"大众shortcut icon\"大众 来让浏览器识别,我们也只须要找出这个部分的href,剖析匹配代码如下:
$base = 'http://xiami.com';preg_match('/<head>(.?)<\/head>/is', file_get_contents($base), $head);if(isset($head[1])) { preg_match_all('/<link[^>]+>/is', $head[1], $links); if(isset($links[0]) && is_array($links[0])) { foreach($links[0] as $link) { // 查找rel中包含icon标识的图片路径 if(preg_match('/rel=(\"大众|\')?(icon\w?|\w+\s+icon)(\"大众|\')?/i', $link)) { var_dump($link); } } } }
(恐格式有误,截图以供参考)
以上,为了探求原形,通过一步步缩小查找范围,我们得到结果:
string(102) \公众<link rel=\公众icon\"大众 type=\"大众image/png\公众 href=\"大众//img.alicdn.com/tfs/TB1qP4zgY5YBuNjSspoXXbeNFXa-550-550.png\"大众>\"大众
没错,个中的href部分便是我们要的图标:
preg_match('/([^\"大众\s><]\.(ico|png|jpg))/i', $link, $url);echo $url[1];
运行结果:
//img.alicdn.com/tfs/TB1qP4zgY5YBuNjSspoXXbeNFXa-550-550.png
末了一步我们只须要再次发起对上面结果地址的要求,就可以保存到本地了,但在这之前,我们须要对结果地址轻微做些补全调度:
if(preg_match('/^http(s):\/\//', $url[1])) { // 完全路径 $url = $url[1];} elseif(preg_match('/^\/{2}\w+/', $url[1])) { // 双//打头 $url = 'http:'.$url[1];} else { // 相对路径 $url = $base.'/'.ltrim($url[1], '/');}
(恐格式有误,截图以供参考)
末了放上完全代码:
<?php$url = 'http://xiami.com';$file = tmpfile(); // 创建一个临时文件,用来保存图标$path = stream_get_meta_data($file)['uri'];$extension = 'ico'; // 图标后缀$context = stream_context_create(['http' => ['timeout' => 15]]);file_put_contents($path, file_get_contents($url.'/favicon.ico', null, $context));if(!getimagesize($path)) { // 根目录下没有favicon.ico preg_match('/<head>(.?)<\/head>/is', file_get_contents($Pea->url, null, $context), $head); if(!isset($head[1])) { // 非标准格式页面 $path = false; } else { $Fulfill = function($base, $url) { if(preg_match('/^http(s):\/\//', $url)) { // 完全路径 return $url; } elseif(preg_match('/^\/{2}\w+/', $url)) { // 双//打头://s1.music.126.net/style/favicon.ico return 'http:'.$url; } else { // 相对路径 return $base.'/'.ltrim($url, '/'); } }; $found = false; // 是否查找到 preg_match_all('/<link[^>]+>/is', $head[1], $links); if(isset($links[0]) && is_array($links[0])) { foreach($links[0] as $link) { // 查找rel中包含icon标识的图片路径 if(preg_match('/rel=(\公众|\')?(icon\w?|\w+\s+icon)(\"大众|\')?/i', $link)) { preg_match('/([^\"大众\s><]\.(ico|png|jpg))/i', $link, $url); if(isset($url[1])) { file_put_contents($path, file_get_contents($Fulfill($url, $url[1]), null, $context)); if(getimagesize($path)) { $found = true; $extension = $url[2]; } } } } } if(!$found) $path = false; }}if($path) { // @todo 将文件转移到做事器存储目录等}
(恐格式有误,截图以供参考)
祝大家节日快乐,以上。
给你代码往期回顾:
给你代码:如何压制MySQL主键值非连续增长
给你代码:自建外贸站之PayPal支付集成
给你代码:网站微信登录接入