Als ich zuvor WeChat-Login-Entwicklungen durchführte, stellte ich fest, dass WeChat-Avatarbilder keinen Suffixnamen hatten. Die herkömmliche Bilderfassungsmethode funktionierte nicht und erforderte eine spezielle Erfassungsverarbeitung. Daher wurden später verschiedene Situationen zusammengefasst, in einer Klasse zusammengefasst und geteilt.
Projekt erstellen
Zur Demonstration erstellen wir das Projekt grabimg im WWW-Stammverzeichnis, erstellen eine Klasse GrabImage.php und eine index.php.
Klassencode schreiben
Wir definieren eine Klasse mit demselben Namen wie die Datei: GrabImage
class GrabImage{}
Attribute
Als nächstes definieren Sie einige, die benötigt werden zu nutzendes Eigentum.
1. Definieren Sie zunächst eine Bildadresse, die erfasst werden muss: $img_url
2. Definieren Sie dann einen $file_name, um den Namen der Datei zu speichern, tragen Sie jedoch nicht den Erweiterungsnamen. weil es beinhalten kann Der Erweiterungsname wird geändert, also entpacken wir hier die Definition
3, gefolgt vom Erweiterungsnamen $extension
4 Dann definieren wir ein $file_dir Die Funktion davon Das Attribut dient dazu, das Remote-Image zu erfassen. Das lokal gespeicherte Verzeichnis ist im Allgemeinen relativ zum Speicherort der PHP-Eintragsdatei als Ausgangspunkt. Dieser Pfad wird jedoch im Allgemeinen nicht in der Datenbank gespeichert.
5. Abschließend definieren wir ein $save_dir. Wie der Name schon sagt, ist dieser Pfad das Verzeichnis zum direkten Speichern der Datenbank. Zur Erläuterung: Wir speichern den Dateispeicherpfad nicht direkt in der Datenbank. Dies dient normalerweise dazu, den Pfad bei einer späteren Migration bequem zu ändern. Unser $save_dir ist hier im Allgemeinen der Name der Datumsdatei. Wenn Sie ihn verwenden müssen, nehmen Sie ihn heraus und schreiben Sie den erforderlichen Pfad voran.
Methode
Attribute sind fertig und dann beginnen wir offiziell mit der Crawling-Arbeit.
Zuerst definieren wir eine offene Methode getInstances, um einige Daten zu erhalten, wie zum Beispiel die Adresse des erfassten Bildes und den lokalen Speicherpfad. Fügen Sie es auch in Eigenschaften ein.
public function getInstances($img_url , $base_dir) { $this->img_url = $img_url; $this->save_dir = date("Ym").'/'.date("d").'/'; // 比如:201610/19/ $this->file_dir = $base_dir.'/'.$this->save_dir.'/'; // 比如:./uploads/image/2016/10/19/ }
Der Bildspeicherpfad wurde gespleißt. Jetzt müssen wir auf eine Frage achten, ob das Verzeichnis existiert. Das Datum ändert sich von Tag zu Tag, das Verzeichnis wird jedoch nicht automatisch erstellt. Daher müssen Sie das Bild vor dem Speichern zunächst überprüfen. Wenn das aktuelle Verzeichnis nicht vorhanden ist, müssen wir es sofort erstellen.
Wir erstellen die Set-Directory-Methode setDir. Wir haben die Attribute auf privat und sicher gesetzt
/** * 检查图片需要保持的目录是否存在 * 如果不存在,则立即创建一个目录 * @return bool */ private function setDir() { if(!file_exists($this->file_dir)) { mkdir($this->file_dir,0777,TRUE); } $this->file_name = uniqid().rand(10000,99999);// 文件名,这里只是演示,实际项目中请使用自己的唯一文件名生成方法 return true; }
Der nächste Schritt besteht darin, den Kerncode zu erfassen
Der erste Schritt besteht darin, ein Problem zu lösen. Die Bilder, die wir erfassen müssen, sind möglicherweise nicht vorhanden haben Suffixnamen. Gemäß der herkömmlichen Crawling-Methode ist es nicht möglich, zuerst das Bild zu crawlen und dann den Suffixnamen abzufangen.
Wir müssen den Bildtyp durch andere Methoden ermitteln. Die Methode besteht darin, die Datei-Header-Informationen aus den Datei-Stream-Informationen abzurufen, wodurch die Datei-MIME-Informationen beurteilt werden und dann der Dateisuffixname ermittelt werden kann.
Der Einfachheit halber definieren Sie zunächst eine MIME- und Dateierweiterungszuordnung.
$mimes=array( 'image/bmp'=>'bmp', 'image/gif'=>'gif', 'image/jpeg'=>'jpg', 'image/png'=>'png', 'image/x-icon'=>'ico' );
Auf diese Weise kann ich, wenn ich den Bild-/GIF-Typ erhalte, erkennen, dass es sich um ein GIF-Bild handelt.
Verwenden Sie die PHP-Funktion get_headers, um Dateistream-Header-Informationen abzurufen. Wenn sein Wert nicht falsch ist, weisen wir ihn der Variablen $headers
zu und entnehmen den Wert von Content-Type, der dem Wert von mime entspricht.
if(($headers=get_headers($this->img_url, 1))!==false){ // 获取响应的类型 $type=$headers['Content-Type']; }
Mithilfe der oben definierten Zuordnungstabelle können wir den Suffixnamen leicht ermitteln.
$this->extension=$mimes[$type];
Natürlich ist der oben erhaltene $type möglicherweise nicht in unserer Zuordnungstabelle vorhanden, was bedeutet, dass dieser Dateityp nicht das ist, was wir wollen. Verwerfen Sie ihn einfach und ignorieren Sie ihn.
Die folgenden Schritte sind die gleichen wie beim herkömmlichen Datei-Grabbing.
$file_path = $this->file_dir.$this->file_name.".".$this->extension; // 获取数据并保存 $contents=file_get_contents($this->img_url); if(file_put_contents($file_path , $contents)) { // 这里返回出去的值是直接保存到数据库的路径 + 文件名,形如:201610/19/57feefd7e2a7aY5p7LsPqaI-lY1BF.jpg return $this->save_dir.$this->file_name.".".$this->extension; }
Ermitteln Sie zuerst den vollständigen Pfad des lokal gespeicherten Bildes $file_path, verwenden Sie dann file_get_contents, um die Daten abzurufen, und verwenden Sie dann file_put_contents, um gerade im Dateipfad zu speichern.
Schließlich geben wir einen Pfad zurück, der anstelle eines Dateispeicherpfads direkt in der Datenbank gespeichert werden kann.
Die vollständige Version dieser Crawling-Methode ist:
private function getRemoteImg() { // mime 和 扩展名 的映射 $mimes=array( 'image/bmp'=>'bmp', 'image/gif'=>'gif', 'image/jpeg'=>'jpg', 'image/png'=>'png', 'image/x-icon'=>'ico' ); // 获取响应头 if(($headers=get_headers($this->img_url, 1))!==false) { // 获取响应的类型 $type=$headers['Content-Type']; // 如果符合我们要的类型 if(isset($mimes[$type])) { $this->extension=$mimes[$type]; $file_path = $this->file_dir.$this->file_name.".".$this->extension; // 获取数据并保存 $contents=file_get_contents($this->img_url); if(file_put_contents($file_path , $contents)) { // 这里返回出去的值是直接保存到数据库的路径 + 文件名,形如:201610/19/57feefd7e2a7aY5p7LsPqaI-lY1BF.jpg return $this->save_dir.$this->file_name.".".$this->extension; } } } return false; }
最后,为了简单,我们想在其他地方只要调用其中一个方法就可以完成抓取。所以,我们将抓取动作直接放入到getInstances中,在配置完路径后,直接抓取,所以,在初始化配置方法getInstances里新增代码。
if($this->setDir()) { return $this->getRemoteImg(); } else { return false; }
测试
我们去刚刚创建的index.php文件内试试。
<?php require_once 'GrabImage.php'; $object = new GrabImage(); $img_url = "http://www.bidianer.com/img/icon_mugs.jpg"; // 需要抓取的远程图片 $base_dir = "./uploads/image"; // 本地保存的路径 echo $object->getInstances($img_url , $base_dir); ?>
惹,的确抓取过来了
完整代码
* @link bidianer.com */ class GrabImage{ /** * @var string 需要抓取的远程图片的地址 * 例如:http://www.bidianer.com/img/icon_mugs.jpg * 有一些远程文件路径可能不带拓展名 * 形如:http://www.xxx.com/img/icon_mugs/q/0 */ private $img_url; /** * @var string 需要保存的文件名称 * 抓取到本地的文件名会重新生成名称 * 但是,不带拓展名 * 例如:57feefd7e2a7aY5p7LsPqaI-lY1BF */ private $file_name; /** * @var string 文件的拓展名 * 这里直接使用远程图片拓展名 * 对于没有拓展名的远程图片,会从文件流中获取 * 例如:.jpg */ private $extension; /** * @var string 文件保存在本地的目录 * 这里的路径是PHP保存文件的路径 * 一般相对于入口文件保存的路径 * 比如:./uploads/image/201610/19/ * 但是该路径一般不直接存储到数据库 */ private $file_dir; /** * @var string 数据库保存的文件目录 * 这个路径是直接保存到数据库的图片路径 * 一般直接保存日期 + 文件名,需要使用的时候拼上前面路径 * 这样做的目的是为了迁移系统时候方便更换路径 * 例如:201610/19/ */ private $save_dir; /** * @param string $img_url 需要抓取的图片地址 * @param string $base_dir 本地保存的路径,比如:./uploads/image,最后不带斜杠"/" * @return bool|int */ public function getInstances($img_url , $base_dir) { $this->img_url = $img_url; $this->save_dir = date("Ym").'/'.date("d").'/'; // 比如:201610/19/ $this->file_dir = $base_dir.'/'.$this->save_dir.'/'; // 比如:./uploads/image/2016/10/19/ return $this->start(); } /** * 开始抓取图片 */ private function start() { if($this->setDir()) { return $this->getRemoteImg(); } else { return false; } } /** * 检查图片需要保持的目录是否存在 * 如果不存在,则立即创建一个目录 * @return bool */ private function setDir() { if(!file_exists($this->file_dir)) { mkdir($this->file_dir,0777,TRUE); } $this->file_name = uniqid().rand(10000,99999);// 文件名,这里只是演示,实际项目中请使用自己的唯一文件名生成方法 return true; } /** * 抓取远程图片核心方法,可以同时抓取有后缀名的图片和没有后缀名的图片 * * @return bool|int */ private function getRemoteImg() { // mime 和 扩展名 的映射 $mimes=array( 'image/bmp'=>'bmp', 'image/gif'=>'gif', 'image/jpeg'=>'jpg', 'image/png'=>'png', 'image/x-icon'=>'ico' ); // 获取响应头 if(($headers=get_headers($this->img_url, 1))!==false) { // 获取响应的类型 $type=$headers['Content-Type']; // 如果符合我们要的类型 if(isset($mimes[$type])) { $this->extension=$mimes[$type]; $file_path = $this->file_dir.$this->file_name.".".$this->extension; // 获取数据并保存 $contents=file_get_contents($this->img_url); if(file_put_contents($file_path , $contents)) { // 这里返回出去的值是直接保存到数据库的路径 + 文件名,形如:201610/19/57feefd7e2a7aY5p7LsPqaI-lY1BF.jpg return $this->save_dir.$this->file_name.".".$this->extension; } } } return false; } }