php 抓取网页生成图片( 编写类代码我们定义一个和文件名index.php和一个)

优采云 发布时间: 2022-04-20 19:08

  php 抓取网页生成图片(

编写类代码我们定义一个和文件名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>

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线