php 抓取网页生成图片( 编写类代码我们定义一个和文件名index.php和一个)
优采云 发布时间: 2022-04-20 19:08php 抓取网页生成图片(
编写类代码我们定义一个和文件名index.php和一个)
之前在做微信登录开发的时候,发现微信头像图片没有后缀名。传统的图像捕获方法不起作用,需要进行特殊的捕获处理。因此,各种情况被组合起来,封装成一个类,共享。
创建项目
作为演示,我们在 www 根目录下创建项目 grabimg,创建一个类 GrabImage.php 和一个 index.php。
编写类代码
我们定义一个与文件同名的类:GrabImage
class GrabImage{}
属性
接下来,定义一些需要使用的属性。
1、先定义一个需要抓取的图片地址:$img_url
2、再定义一个$file_name来存放文件名,但是不带扩展名,因为可能涉及扩展名替换,所以这里定义
3、后面是扩展名 $extension
4、然后我们定义一个$file_dir。该属性的作用是本地抓取远程图片后存放的目录一般以相对于PHP入口文件的位置为起点。但路径一般不会保存到数据库中。
5、最后我们定义一个$save_dir,顾名思义,这个路径就是用来直接保存的数据库的目录。这里解释一下,我们不直接将文件保存路径存储到数据库中,一般是为以后系统迁移时路径的替换做准备。我们这里的$save_dir一般是日期+文件名。如果需要使用时需要取出,在前面拼出需要的路径即可。
方法
属性写完了,接下来我们正式开始爬取工作。
首先,我们定义一个open方法getInstances来获取一些数据,比如抓取图片地址和本地保存路径。也把它放在属性中。
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/}
图片保存路径拼接在一起。接下来,我们需要注意一个问题,目录是否存在。日期一天一天过去,但目录不会自动创建。所以,在保存图片之前,我们首先需要检查,如果当前目录不存在,我们需要动态创建它。
我们创建设置目录方法setDir。我们设置的属性private、safe
/** * 检查图片需要保持的目录是否存在 * 如果不存在,则立即创建一个目录 * @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;}
下一步是抓取核心代码
第一步是解决一个问题,我们需要抓取的图片可能没有后缀。按照传统的抓取方式,先抓取图片再截取后缀名的方案是行不通的。我们必须通过其他方式获取图片类型。方法是从文件流信息中获取文件头信息,从而判断文件mime信息,进而可以知道文件后缀名。为方便起见,首先定义一个 mime 和文件扩展名映射。
$mimes=array( 'image/bmp'=>'bmp', 'image/gif'=>'gif', 'image/jpeg'=>'jpg', 'image/png'=>'png', 'image/x-icon'=>'ico');
这样,当我得到类型 image/gif 时,我就可以知道它是一个 .gif 图像。
使用php函数get_headers获取文件流头信息。当它的值不为假时,我们将它分配给变量 $headers
取出的Content-Type的值就是mime的值。
if(($headers=get_headers($this->img_url, 1))!==false){ // 获取响应的类型 $type=$headers['Content-Type'];}
使用我们上面定义的映射表,我们可以很容易的得到后缀名。
$this->extension=$mimes[$type];
当然,上面得到的$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;}
先获取完整路径$file_path将图片保存到本地,然后使用file_get_contents抓取数据,再使用file_put_contents保存到刚才的文件路径。
最后我们返回一个可以直接保存到数据库的路径,而不是文件存储路径。
完整版的抓取方法是:
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 文件中尝试一下。
妈的,我抢到了
完整代码
<p>