Trouver et télécharger le favicon d'une page en PHP

Mars 2014

Le favicon, c'est la petite image affichée par le navigateur web, généralement dans les onglets, pour identifier facilement et rapidement un site sans ouvrir l'onglet :

Favicon dans les onglets de Firefox 27.0.1

Techniquement, le favicon est simplement une image, qui porte généralement l'extension .ico, ou plus rarement l'extension .png (car le PNG n'est pas compatible avec certains navigateurs anciens ou de mauvaise qualité comme Internet Explorer).

Chaque site héberge son propre favicon, et le navigateur a 2 façons de trouver ce favicon :

  • Avec l'URL par défaut : http;//www.site.com/favicon.ico
  • Ou alors en utilisant la balise link shortcut icon qui indique l'URL du favicon : <link rel="shortcut icon" href="//cdn.sstatic.net/stackoverflow/img/favicon.ico?v=5bcec08ba0c5">

Du coup, déterminer l'URL du favicon d'un site web n'est pas simple, il y a beaucoup de paramètres à prendre en compte, notamment pour lire et interpréter la valeur de la base link shortcut icon qui peut contenir des URL absolues ou relatives, et dont potentiellement dépendantes du contexte comme le protocole (http/https) ou la base <base href="..." />. Sans compter les éventuelles redirections HTTP qui viennent encore compliquer le travail...

Voilà donc une classe PHP que j'ai écrite et qui permet de trouver et télécharger très facilement le favicon d'un site simplement à partir d'une URL. Voici comment on l'utilise :

La page du jour est aperçu avant impression dans excel, bonne lecture.

<?php
require 'FaviconDownloader.class.php';

$favicon = new FaviconDownloader('http://koreus.fr');

if($favicon->icoExists){
	echo "URL du favicon : ".$favicon->icoUrl."\n";
	file_put_contents('favicon.'.$favicon->icoType, $favicon->icoData);
} else {
	echo "Aucun favicon";
}

echo "Détails :\n";
$favicon->debug();
?>

Voici la classe FaviconDownloader (les commentaires sont en anglais car je ratisse large ^^) :

Classe FaviconDownloader Télécharger la classe PHP FaviconDownloader, avec un fichier d'exemple inclus.
Télécharger
<?php
/**
* FaviconDownloader
* Find favicon URL and download it easy
* Requirements : PHP 5.2+ with curl extension
* © 2014 www.finalclap.com
* @copyright  2014 Vincent Paré
* @author     Vincent Paré
* @link       http://www.finalclap.com/
* @version    1
*/

class FaviconDownloader
{
	public $url			= null; // (string) Page URL
	public $pageUrl		= null; // (string) Page URL, after prospective redirects
	public $siteUrl		= null; // (string) Site root URL (homepage), based on $pageUrl
	public $icoUrl		= null; // (string) full URI to favicon
	public $icoType		= null; // (string) favicon type (file extension, ex: ico|gif|png)
	public $findMethod	= null; // (string) favicon url determination method (default /favicon.ico or found in <head> <link/> tag)
	public $error		= null; // (string) details, in case of failure...
	public $icoExists 	= null; // (bool)   tell if the favicon exists (set after calling downloadFavicon)
	public $icoMd5		= null; // (string) md5 of $icoData
	public $icoData		= null; // (binary) favicon binary data
	public $debugInfo	= null; // (array)  additionnal debug info
	public static $httpProxy = null; // (string) HTTP proxy (ex: localhost:8888)

	/**
	* Create a new FaviconDownloader object, search & download favicon if $auto is true
	*/
	public function __construct($url = null, $auto = true)
	{
		if(!$url) return;
		$this->url = $url;
		if(!$auto) return;
		$this->getFaviconUrl();
		$this->downloadFavicon();
	}
	
	/**
	* Download page and search html to find favicon URL. Returns favicon URL.
	*/
	public function getFaviconUrl()
	{
		// If already executed, don't need to search again
		if(!empty($this->icoUrl)){
			return $this->icoUrl;
		}
		
		// Check URL to search
		if(empty($this->url)){
			trigger_error('$this->url is empty', E_USER_WARNING);
			return false;
		}
		
		// Removing fragment (hash) from URL
		$url = $this->url;
		$urlInfo = parse_url($this->url);
		if(isset($urlInfo['fragment'])){
			$url = str_replace('#'.$urlInfo['fragment'], '', $url);
		}
		
		// Downloading the page
		$html = self::downloadAs($url, $info);
		if($info['curl_errno'] != 0){
			$this->error = $info['curl_error'];
			return false;
		}
		
		// Saving final URL (after prospective redirects) and get root URL
		$this->pageUrl = $info['effective_url'];
		$pageUrlInfo = parse_url($this->pageUrl);
		if(!empty($pageUrlInfo['scheme']) && !empty($pageUrlInfo['host'])){
			$this->siteUrl = $pageUrlInfo['scheme'].'://'.$pageUrlInfo['host'].'/';
		}
		
		// Default favicon URL
		$this->icoUrl = $this->siteUrl.'favicon.ico';
		$this->findMethod = 'default';
		
		// HTML <head> tag extraction
		preg_match('#^(.*)<\s*body#isU', $html, $matches);
		$htmlHead = isset($matches[1]) ? $matches[1] : $html;
		
		// HTML <base> tag href extraction
		$base_href = null;
		if(preg_match('#<base[^>]+href=(["\'])([^>]+)\1#i', $htmlHead, $matches)){
			$base_href = rtrim($matches[2],'/').'/';
			$this->debugInfo['base_href'] = &$base_href;
		}
		
		// HTML <link> icon tag analysis
		if(preg_match('#<\s*link[^>]*(rel=(["\'])[^>\2]*icon[^>\2]*\2)[^>]*>#i', $htmlHead, $matches)){
			$link_tag = $matches[0];
			$this->debugInfo['link_tag'] = &$link_tag;
			
			// HTML <link> icon tag href analysis
			if(preg_match('#href\s*=\s*(["\'])(.*?)\1#i', $link_tag, $matches)){
				$ico_href = trim($matches[2]);
				$this->debugInfo['ico_href'] = &$ico_href;
				$this->findMethod = 'head';
				
				// Building full absolute URL
				$urlType = self::urlType($ico_href);
				$this->findMethod .= ' '.$urlType;
				switch($urlType){
					case 'absolue_full':
						$this->icoUrl = $ico_href;
						break;
					case 'absolute_scheme':
						$this->icoUrl = $pageUrlInfo['scheme'].':'.$ico_href;
						break;
					case 'absolute_path':
						if(isset($base_href)){
							$this->icoUrl = $base_href.$ico_href;
							$this->findMethod .= ' with base href';
						} else {
							$this->icoUrl = rtrim($this->siteUrl, '/').'/'.ltrim($ico_href, '/');
							$this->findMethod .= ' without base href';
						}
						break;
					case 'relative':
						$path = preg_replace('#/[^/]+?$#i', '/', $pageUrlInfo['path']);
						if(isset($base_href)){
							$this->icoUrl = $base_href.$ico_href;
							$this->findMethod .= ' with base href';
						} else {
							$this->icoUrl = $pageUrlInfo['scheme'].'://'.$pageUrlInfo['host'].$path.$ico_href;
							$this->findMethod .= ' without base href';
						}
						break;
				}
			}
		}
		
		$this->icoType = self::getExtension($this->icoUrl);
		return $this->icoUrl;
	}
	
	/**
	* Télécharge le favicon (et vérifie son existance au passage)
	*/
	public function downloadFavicon()
	{
		// Check params
		if(empty($this->icoUrl)){
			return false;
		}
		
		// Prevent useless re-download
		if(!empty($this->icoData)){
			return false;
		}
		
		// Download favicon
		$content = self::downloadAs($this->icoUrl, $info);
		$this->debugInfo['favicon_download_metadata'] = $info;
		
		// Failover : if getting a 404 with favicon URL found in HTML source, trying with the default favicon URL
		if($content === false && $info['http_code'] == 404 && $this->findMethod != 'default' && !isset($this->debugInfo['failover'])){
			$this->icoUrl = $this->siteUrl.'favicon.ico';
			$this->findMethod = 'default';
			$this->icoType = self::getExtension($this->icoUrl);
			$this->debugInfo['failover'] = true;
			return $this->downloadFavicon();
		}
		
		// Download error
		if($content === false){
			$this->error = 'HTTP '.$info['http_code'];
			return false;
		}
		
		// Check favicon content
		if(strlen($content) == 0){
			$this->error = "Empty content";
			return false;
		}
		if(in_array($info['content_type'], array('text/html', 'text/plain')) || preg_match('#(</html>|</b>)#i', $content)){
			$this->error = "Seems to be HTML page";
			return false;
		}
		
		// All right baby !
		$this->icoData   = $content;
		$this->icoMd5    = md5($content);
		$this->icoExists = true;
		return true;
	}
	
	/**
	* Download URL as Firefox with cURL
	* Details available in $info if provided
	*/
	public static function downloadAs($url, &$info = null)
	{
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Don't check SSL certificate to allow autosigned certificate
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // Follow redirects (302, 301)
		curl_setopt($ch, CURLOPT_MAXREDIRS, 20);         // Follow up to 20 redirects
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0');
		if(!empty(self::$httpProxy)){
			curl_setopt($ch, CURLOPT_PROXY, self::$httpProxy); // Set HTTP proxy
		}
		$content = curl_exec($ch);
		$info['curl_errno'] = curl_errno($ch);
		$info['curl_error'] = curl_error($ch);
		$info['http_code'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		$info['effective_url'] = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
		$info['redirect_count'] = curl_getinfo($ch, CURLINFO_REDIRECT_COUNT);
		$info['content_type'] = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
		curl_close($ch);
		
		if($info['curl_errno'] !== 0 || in_array($info['http_code'], array(403, 404, 500, 503))){
			return false;
		}
		return $content;
	}
	
	/**
	* Return file extension from an URL or a file path
	*/
	public static function getExtension($filename)
	{
		if(preg_match('#^(https?|ftp)#i', $filename)){
			$url = parse_url($filename);
			$filename = $url['path'];
		}
		
		$info = pathinfo($filename);
		return $info['extension'];
	}
	
	/**
	* Return URL type, either :
	* - absolute_full   ex: http://www.domain.com/images/fav.ico
	* - absolute_scheme ex: //www.domain.com/images/fav.ico
	* - absolute_path   ex: /images/fav.ico
	* - relative        ex: ../images/fav.ico
	*/
	public static function urlType($url)
	{
		if(empty($url)) return false;
		$urlInfo = parse_url($url);
		if(!empty($urlInfo['scheme'])) return 'absolue_full';
		if(preg_match('#^//#i', $url)) return 'absolute_scheme';
		if(preg_match('#^/[^/]#i', $url)) return 'absolute_path';
		return 'relative';
	}
	
	/**
	* Show object printable properties, or return it if $return is true
	*/
	public function debug($return = false)
	{
		$dump = clone $this;
		unset($dump->icoData);
		if($return) return $dump;
		print_r($dump);
	}
}
?>

Allez donc jeter un oeil sur cette page : nuit magique.

7 commentaires :
commentaire n°4147 par jameser239@gmail.com
jameser239@gmail.com mercredi 26 juin 2019, 06:51
Learn If Your Home Business Enterprise Fits Your Needs

It's both tough and rewarding to start your own business. The first time and effort you place to the business will likely be integral to how successful the business has ended the long run. Over time it would build, but it can be tough at the start. If you want great results, you must strive.

You must be able to discuss your organization to others. The opportunity to sum your company up in certain simple sentences is undoubtedly an impressive skill that clients appreciate. This can be your slogan and assist you to sell your small business.

Keep an eye out for websites where work at home business owners gather. There is reliable information available online, and a quick search will result in many good sites. There are lots of bloggers offering helpful information on the web, too.

Join a couple of discussion groups and forums that discuss the main topic of home based business. Using the search engines on your computer system should restrict some which are applicable for you, and are generally a great resource of data. There are several online articles and blogs you could find to get useful.

Make certain you will not be breaking any laws or ordinances in your neighborhood. You could wind up being put out of business or charged hefty fines, and that can be quite embarrassing, when you don't. Also do not forget that a neighbor-friendly attitude goes right together with making sure you adhere to the letter of the law. To some extent, it means discreet signage and minimum noise and traffic. Try to be as courteous as is possible.

Emergency funds are needed for your personal business in case there are unexpected expenses. You then are prepared for a variety of unexpected turns. Avoid tapping in the fund unless it is actually absolutely necessary, and promptly replace money that you do withdraw.

It is wise to save a few of the money that you make in a year to help you your taxes. Income taxes are due following every quarter. The tax rate is normally 15 to twenty percent which could cause substantial amounts owed.

There are actually lots of people who run their very own home businesses online. Look around the world wide web for forums or discussion boards where folks your small business swap strategies. Finding these conversations can provide some good concepts for improving your house business enterprise.

You should consider joining an web-based web business assembly. Speaking to others looking to do exactly the same thing as you can be helpful. Other online business enterprise owners know what you handle, and you will collaborate together inquire about advice.

Whenever you get yourself a payment, place it from the bank. Instead of setting up a weekly or monthly bank deposit, make deposits daily or weekly. Should you don't deposit a check straight away, it could go missing. Make use of a teller to deposit your hard earned dollars through, instead of an ATM, to make sure the funds explores your money.

There are lots of people trying to sell yourself on scams, as you may have just learned. There are also many common-sense tactics and tips which can be used to be able to expand your home based business, as you've learned throughout this informative article. You are able to easily be successful if you're willing to put in the work.


https://thetrueone1.blogspot.com/2019/06/oody-geffen_2.html


yehuda sadok
commentaire n°7432 par annodcami@svmail.xyz
annodcami@svmail.xyz lundi 30 août 2021, 10:06
https://buystromectolon.com/ - Stromectol
commentaire n°7525 par reornepen@manmail.xyz
reornepen@manmail.xyz dimanche 5 septembre 2021, 08:26
<a href=https://buypropeciaon.com/>;buy canadian finasteride 1 mg</a>
commentaire n°7545 par flarakeva@abdulah.xyz
flarakeva@abdulah.xyz lundi 6 septembre 2021, 01:16
https://buypropeciaon.com/ - propecia side effects
commentaire n°7940 par assulpabe@rqmail.xyz
assulpabe@rqmail.xyz vendredi 17 septembre 2021, 21:21
<a href=https://buyplaquenilcv.com/>;Plaquenil</a>
commentaire n°8021 par Amedeenda@mktmail.xyz
Amedeenda@mktmail.xyz dimanche 19 septembre 2021, 05:39
<a href=https://buyzithromaxinf.com/>;buy zithromax no prescription</a>
commentaire n°8133 par chishar@sqmail.xyz
chishar@sqmail.xyz mardi 21 septembre 2021, 16:30
<a href=https://buypriligyhop.com/>;Priligy</a>
facultatif
Facebook Twitter RSS Email
Forum Excel
Venez découvrir le nouveau forum excel question/réponse à la stackoverflow.com !
Forum Excel
hit parade n'en a rien a foutre du W3C Positionnement et Statistiques Gratuites Vincent Paré