php 获取网页内的图片地址正则表达式

 更新时间:2016年11月25日 15:46  点击:1671
获取网页中的图片地址并保存下载我们需要采集页面,然后再利用正则表达式获取页面中的图片url,然后我们再通过相关的php函数把图片保存到指定本地硬盘了。


1. 获取地址
这个功能最主要的就是用正则表达式来匹配页面源码里的图片地址了,这里用到得正则表达式是:

 代码如下 复制代码

/<img.*src="(.*)"\s*.*>/iU

首页通过PHP自带的读取文件函数来获得请求页面的html代码,然后用正则表达式来匹配里面的src地址,这里有两个注意点:

■file_get_content

只能获取到静态的页面内容,也就是说如果你在页面里看到的是图片是通过Javascript来展示的,通过这个工具是获取不到图片信息的
■有的网站对file_get_content 这个函数做了些限制,如果不是通过浏览器打开的网页,服务器是拒绝请求的,这个时候我们就需要给php 程序添加一个配置信息,让采集的程序能够模拟一个留言器的UA(user agent),具体的做法可以通过下面的代码来实现://现在模拟的是一个Window 环境下的浏览器
ini_set('user_agent','Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; 4399Box.560; .NET4.0C; .NET4.0E)');
通过以上两点的处理,获取网页源码就没有问题了,唯一要做的就是用正则表达式对图片地址的匹配。

例子1

 代码如下 复制代码

/**
 * 获取替换文章中的图片路径
 * @param string $xstr 内容 采集网页的content
 * @param string $keyword 创建照片的文件名 我写upimg
 * @param string $oriweb 网址 一般写null
 * @return string
 *
 */
function replaceimg($xstr,$keyword, $oriweb){
 $basedir = dirname(__FILE__);
 
    //保存路径
    $d = date('Ym', time());
    $dirslsitss = $basedir.'/../uploads/'.$keyword.'/'.$d;//分类是否存在
    if(!is_dir($dirslsitss)) {
        @mkdir($dirslsitss, 0777);
    }
 
    //匹配图片的src
    preg_match_all('#<img.*?src="([^"]*)"[^>]*>#i', $xstr, $match);
 
    foreach($match[1] as $imgurl){
 
        $imgurl = $imgurl;
 
        if(is_int(strpos($imgurl, 'http'))){
            $arcurl = $imgurl;
        } else {
            $arcurl = $oriweb.$imgurl;       
        }
        $img=file_get_contents($arcurl);
 
 
        if(!empty($img)) {
 
            //保存图片到服务器
            $fileimgname = time()."-".rand(1000,9999).".jpg";
            $filecachs=$dirslsitss."/".$fileimgname;
            $fanhuistr = file_put_contents( $filecachs, $img );
            $saveimgfile = "/uploads/$keyword"."/".$d."/".$fileimgname;
 
 
            $xstr=str_replace($imgurl,$saveimgfile,$xstr);
        }
    }
    return $xstr;
}

可能有些朋友也知道file_get_contents性能不怎么样,我们可使用curl来获取

 代码如下 复制代码


/*
*功能:php完美实现下载远程图片保存到本地
*参数:文件url,保存文件目录,保存文件名称,使用的下载方式
*当保存文件名称为空时则使用远程文件原来的名称
*/
function getImage($url,$save_dir='',$filename='',$type=0){
    if(trim($url)==''){
  return array('file_name'=>'','save_path'=>'','error'=>1);
 }
 if(trim($save_dir)==''){
  $save_dir='./';
 }
    if(trim($filename)==''){//保存文件名
        $ext=strrchr($url,'.');
        if($ext!='.gif'&&$ext!='.jpg'){
   return array('file_name'=>'','save_path'=>'','error'=>3);
  }
        $filename=time().$ext;
    }
 if(0!==strrpos($save_dir,'/')){
  $save_dir.='/';
 }
 //创建保存目录
 if(!file_exists($save_dir)&&!mkdir($save_dir,0777,true)){
  return array('file_name'=>'','save_path'=>'','error'=>5);
 }
    //获取远程文件所采用的方法
    if($type){
  $ch=curl_init();
  $timeout=5;
  curl_setopt($ch,CURLOPT_URL,$url);
  curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
  curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
  $img=curl_exec($ch);
  curl_close($ch);
    }else{
     ob_start();
     readfile($url);
     $img=ob_get_contents();
     ob_end_clean();
    }
    //$size=strlen($img);
    //文件大小
    $fp2=@fopen($save_dir.$filename,'a');
    fwrite($fp2,$img);
    fclose($fp2);
 unset($img,$url);
    return array('file_name'=>$filename,'save_path'=>$save_dir.$filename,'error'=>0);
}

Global是php中一个比较特殊的命令,大家直接叫他超级全局变量了,下面我来介绍我今天在使用Global定义全局学习笔记了。

很不习惯PHP中的变量作用域,PHP中函数变量和全局是完全隔绝的,也就是无法相互访问。
比如下面这样:

copytext

 代码如下 复制代码

$test = 123;

 abc(); //这里什么都不输出,因为访问不到$test变量
function abc(){
    echo($test);
}$test = 123;

abc(); //这里什么都不输出,因为访问不到$test变量
function abc(){
    echo($test);

}如果,你想在函数内部访问外部变量,你需要这样:

copytext

 代码如下 复制代码

$test = 123;

 abc(); //输出123
function abc(){
    global $test;
    echo($test);
}$test = 123;

abc(); //输出123
function abc(){
    global $test;
    echo($test);
}

但如果我们在函数中定义全局变量呢,像下面这样:

copytext

 代码如下 复制代码
function abc(){
    global $test;
    $test = 123;
}
abc();
echo($test); //输出123function abc(){
 global $test;
 $test = 123;
}
abc();
echo($test);

 //输出123通过这种方式,我们可以在外部访问到函数内部定义的变量

在用户自定义函数中,一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内(包括include 和 require 导入的文件内的变量)!
解释:A.php文件的内Test_Global是定义好的第三方函数,该函数用include导入了B.php文件内的$a的global全局变量,所以$a被限制在Test_Global局部函数范围内,所以B.php文件内的$a的作用范围都在Test_Global内,而不是作用了整个A.php内….

解决方案:
1. 冲出局部函数

&nbsp;//A.php 文件

 代码如下 复制代码

<?php
function Test_Global()
{&nbsp;&nbsp;
    Test();&nbsp;&nbsp;
}&nbsp;&nbsp;
include 'B.php';&nbsp;&nbsp; //将include 从局部Test_Global函数中移出
$a = 0 ;
Test_Global();
echo $a;
?>&nbsp;

//B.php 文件

<?php
function Test()
{
    global $a;
    $a =1;
}
?>

2.优秀的访问器

 代码如下 复制代码

//A.php 文件
<?php
include 'B.php';&nbsp;
$a =0;
Set_Global($a);
echo $a;
?>&nbsp;

//B.php 文件

<?php
function Set_Global(&$var)
{
    $var=1;
}
?>

PHPExcel是一个非常方便生成Excel格式文件的类,官方下载包中带有大量如何生成各种样式excel文件的示例,但没有一个读取Excel文件的完整例子.Xiaoqiang根据网上的资料,整理了一份简单读取Excel文件的例子

在网站的管理后台经常会使用到报表的生成和读取,CSV和Excel都是常用的报表格式,CSV相对来说比较简单,如果大家有疑问我会相继发布一些CSV的实例,这里主要介绍用PHP 来生成和读取Excel文件。

要执行下面的函数,首先要引入一个类库:PHPExcel,PHPExcel是一个强大的PHP类库,用来读写不同的文件格式,比如说Excel 2007,PDF格式,HTML格式等等,这个类库是建立在Microsoft's OpenXML和PHP 的基础上的,对Excel提供的强大的支持,比如设置工作薄,字体样式,图片以及边框等等,下面来看看它是如何读写Excel文件的:

首先来看如果生成Excel文件:
下面这代码中函数arrayToExcel的功能是把一个二维数组的数据生成一个excel文件,并且保存在服务器上。

 代码如下 复制代码
require_once 'Classes/PHPExcel/Reader/Excel2007.php';
require_once 'Classes/PHPExcel/Reader/Excel5.php';
include 'Classes/PHPExcel/IOFactory.php';
function arrayToExcel($data){
$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->setTitle('firstsheet');
$objPHPExcel->getDefaultStyle()->getFont()->setName('Arial');
$objPHPExcel->getDefaultStyle()->getFont()->setSize(10);
//add data
$i = 2;
foreach ($data as $line){
$objPHPExcel->getActiveSheet()->setCellValue('A'.$i, $line['From']);
$objPHPExcel->getActiveSheet()->getCell('A'.$i)->setDataType('n');
$objPHPExcel->getActiveSheet()->setCellValue('B'.$i, $line['To']);
$objPHPExcel->getActiveSheet()->getCell('B'.$i)->setDataType('n');
$i++;
}
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$file = 'excel.xls';
$objWriter->save($file);
}

如果你不希望保存在服务器上,希望生成以后直接下载到客户端,可以在输出文件的时候加入下面的代码,而不使用 $objWriter->save($file);

 代码如下 复制代码

header("Pragma: public");
header("Expires: 0");
header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
header("Content-Type:application/force-download");
header("Content-Type:application/vnd.ms-execl");
header("Content-Type:application/octet-stream");
header("Content-Type:application/download");
header('Content-Disposition:attachment;filename="excel.xls"');
header("Content-Transfer-Encoding:binary");
$objWriter->save('php://output');

接下来看一个读取Excel文件内容的实例:
下面这代码中函数excelToArray的功能是把一个excel里的内容重新整理放到一个数组了。

 代码如下 复制代码
require_once 'Classes/PHPExcel.php';
require_once 'Classes/PHPExcel/IOFactory.php';
function excelToArray($file){
$objReader = PHPExcel_IOFactory::createReader('Excel5');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($file);
$objWorksheet = $objPHPExcel->getActiveSheet();
$highestRow = $objWorksheet->getHighestRow();
$highestColumn = $objWorksheet->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
$excelData = array();
for ($row = 2; $row <= $highestRow; ++$row) {
for ($col = 0; $col <= $highestColumnIndex; ++$col) { $excelData[$row][] = $objWorksheet->getCellByColumnAndRow($col, $row)->getValue();
}
}
return $excelData;
}


精简办法

 

 代码如下 复制代码
<?php
/**
 *
 * @copyright 2007-2012 Xiaoqiang.
 * @author Xiaoqiang.Wu <jamblues@gmail.com>
 * @version 1.01
 */
 
error_reporting(E_ALL);
 
date_default_timezone_set('Asia/ShangHai');
 
/** PHPExcel_IOFactory */
require_once '../Classes/PHPExcel/IOFactory.php';
 
 
// Check prerequisites
if (!file_exists("31excel5.xls")) {
    exit("not found 31excel5.xls.n");
}
 
$reader = PHPExcel_IOFactory::createReader('Excel5'); //设置以Excel5格式(Excel97-2003工作簿)
$PHPExcel = $reader->load("31excel5.xls"); // 载入excel文件
$sheet = $PHPExcel->getSheet(0); // 读取第一??工作表
$highestRow = $sheet->getHighestRow(); // 取得总行数
$highestColumm = $sheet->getHighestColumn(); // 取得总列数
 
/** 循环读取每个单元格的数据 */
for ($row = 1; $row <= $highestRow; $row++){//行数是以第1行开始
    for ($column = 'A'; $column <= $highestColumm; $column++) {//列数是以A列开始
        $dataset[] = $sheet->getCell($column.$row)->getValue();
        echo $column.$row.":".$sheet->getCell($column.$row)->getValue()."<br />";
    }
}
 
?>
这里说的异步执行是让php脚本在后台挂起一个执行具体操作的脚本,主脚本退出后,挂起的脚本还能继续执行。比如执行某些耗时操作或可以并行执行的操作,可以采用php异步执行的方式。主脚本和子脚本的通讯可以采用外部文件或memcached的方式。原理就是通过exec或system来执行一个外部命令。注意:本文所述的是针对Linux环境。

在Linux下要让一个脚本挂在后台执行可以在命令的结尾加上一个 "&" 符号,有时候这还不够,需要借助nohup命令,关于nohup,


玩过Linux的人应该都知道,如果想让一个程序在后台运行,只要在执行命令的末尾加上一个&符号就可以了。但是这种方式不是很保险,有些程序当你登出终端后它就会停止。那么如何让一个程序真正永远在后台执行呢。答案就是使用 nohub 命令,格式为:

nohup 执行程序的命令 &

如果程序有输出,它会试着把输出写入执
行上述命令的当前文件夹下的 nohup.out 文件中,当写入失败,就会写当前用户的$HOME目录下的nohup.out 中。

 

CLI环境和Web环境执行的操作还不太一样。先来说CLI环境,这里需要用上nohup和&,同时还要把指定输出,如果不想要输出结果,可以把输出定向到/dev/null中。现在来做一个测试,假设在一个目录中有main.php、sub1.php和sub2.php,其中sub1和sub2内容一样都让sleep函数暂停一段时间。代码如下:

 代码如下 复制代码

//main.php
<?php
    $cmd = 'nohup php ./sub.php >./tmp.log  &';
    exec($cmd);
    $cmd = 'nohup php ./sub1.php >/dev/null  &';
    exec($cmd);
?>

//sub1.php sub2.php
<?php
    sleep(100000);
?>

上述文件中main.php是作为主脚本,在命令行中执行php main.php,可以看到main.php脚本很快就执行完并退出。在使用ps aux | grep sub命令搜索进程,应该可以在后台看到上述的两个子脚本,说明成功挂起了子脚本。

在Web环境下,执行php脚本都是Web服务器开启的cgi进程来处理,只要脚本不退出,就会一直占有该cgi进程,当启动的所有cgi进程都被占用完后就不能在处理新的请求。所以对那些可能会很费时的脚本,可以采用异步的方式。启动子脚本的方式和CLI差不多,必须要使用&和指定输出(只好是定向到/dev/null),但是不能使用nohup。例如:

 代码如下 复制代码
<?php
    $cmd = 'php PATH_TO_SUB1/sub1.php >/dev/null  &';
    exec($cmd);
    $cmd = 'php PATH_TO_SUB1/sub2.php >/dev/null  &';
    exec($cmd);
?>

当在浏览器中访问该脚本文件,可以看到浏览器里面响应完成,同时使用ps命令查看后台可以看到sub1和sub2脚本。

注意上述例子中如果php命令不在PATH中,需要指定命令完整的路径。推荐使用完整路径,特别是在Web下

empty() 判断一个变量是否为\"空\",isset() 判断一个变量是否已经设置。正是这种所谓的\"顾名思义\",令我开始时走了些弯路:当一个变量值等于0时,empty()也会成立(True),因而会发生一些意外

empty是判断变量值是非空或非零的值。对应空定义包括:""(空字符串)、0、"0"、NULL、FALSE、array()和$var(只声明但未赋值)。也就是说当变量值为上述这些,empty返回TRUE,其他的都返回FALSE。

isset是检测变量是否设置,并且不是 NULL。变量设置可以从几个方面来说。1:最简单的就是变量是否先声明和赋值;2:array中是否存在对应的index或key;3:object中是否存在对应的属性。

从上面的两个function定义可以看到,在某些情况下,两者可以公用,但其区别还是很大的。另外它们都只能检测变量,检测任何非变量的东西都将导致解析错误。例如直接检查另一个function的返回值(empty(otherFunction())),你将看到"Fatal error: Can't use function return value in write context in"这样的错误。

另外isset可以一次检查多个变量,例如:isset($var1, $var2, $var3),当这三个值分别的isset都为TRUE结果为TRUE,否则结果为FALSE。


比如检测 $id 变量,当 $id=0 时,用empty() 和 isset() 来检测变量 $id 是否已经配置,两都将返回不同的值—— empty() 认为没有配置,isset() 能够取得 $id 的值:

 

 代码如下 复制代码
 $id=0;
    empty($id)?print "It's empty .":print "It's $id .";
      //结果:It's empty .
    print "<br>";
    !isset($id)?print "It's empty .":print "It's $id .";
      //结果:It's 0 .


   这意味着,我们在使用变量处理函数时,当该变量可能出现0的值,使用 empty() 要小心,这个时候用 isset 取代它更明智一些。

当一个php页面的 URL 尾部参数出现 id=0 时(比如:test.php?id=0),试比较:

 

 代码如下 复制代码
if(empty($id)) $id=1; - 若 id=0 ,id 也会为1
if(!isset($id)) $id=1; - 若 id=0 ,id 不会为1


可分开运行以下代码检测上述推断:

 

 代码如下 复制代码

 if(empty($id)) $id=1;
    print $id; // 得到 1

    if(!isset($id)) $id=1;
 print $id; //得到 0

测试代码:

$sep = "<br />";

echo 'test undeclared var empty : ';
var_dump(empty($var)); // TRUE
echo $sep . 'test undeclared var isset : ';
var_dump(isset($var)); // FALSE

$var;
echo $sep . 'test declared var but no set value empty : ';
var_dump(empty($var)); // TRUE
echo $sep . 'test declared var but no set value isset : ';
var_dump(isset($var)); // FALSE, 变量申明未赋值,默认值为NULL

$var = NULL;
echo $sep . 'test declared var and set value NULL empty : ';
var_dump(empty($var)); // TRUE
echo $sep . 'test declared var and set value NULL isset : ';
var_dump(isset($var)); // FALSE, 变量申明赋值为NULL

$var1 = ''; $var2 = '0'; $var3 = 0; $var4 = FALSE; $var5 = array();

echo $sep . 'test '' empty : ';
var_dump(empty($var1)); // TRUE
echo $sep . 'test '0' empty : ';
var_dump(empty($var2)); // TRUE
echo $sep . 'test 0 empty : ';
var_dump(empty($var3)); // TRUE
echo $sep . 'test FALSE empty : ';
var_dump(empty($var4)); // TRUE
echo $sep . 'test array() empty : ';
var_dump(empty($var5)); // TRUE
echo $sep . 'test '', '0', 0, FALSE, array() isset : ';
var_dump(isset($var1, $var2, $var3, $var4, $var5)); // TRUE,  变量申明并赋值为空字符串输出的结果为:

test undeclared var empty : bool(true)
test undeclared var isset : bool(false)
test declared var but no set value empty : bool(true)
test declared var but no set value isset : bool(false)
test declared var and set value NULL empty : bool(true)
test declared var and set value NULL isset : bool(false)
test '' empty : bool(true)
test '0' empty : bool(true)
test 0 empty : bool(true)
test FALSE empty : bool(true)
test array() empty : bool(true)
test '', '0', 0, FALSE, array() isset : bool(true)

[!--infotagslink--]

相关文章

  • PHP正则表达式取双引号内的内容

    取双引号内的内容我们如果一个字符串中只有一个可以使用explode来获得,但如果有多个需要使用正则表达式来提取了,具体的例子如下。 写程序的时候总结一点经验,如何只...2016-11-25
  • PHP正则表达式之捕获组与非捕获组

    今天遇到一个正则匹配的问题,忽然翻到有捕获组的概念,手册上也是一略而过,百度时无意翻到C#和Java中有对正则捕获组的特殊用法,搜索关键词有PHP时竟然没有相关内容,自己试了一下,发现在PHP中也是可行的,于是总结一下,分享的同...2015-11-08
  • php 验证只能输入汉字、英语、数字的正则表达式

    正则表达式是一门非常有用的并且进行模糊判断的一个功能了,我们下面来看通过正则来验证输入汉字、英语、数字,具体如下。 收藏了正则表达式。可以验证只能输入数...2016-11-25
  • java正则表达式判断前端参数修改表中另一个字段的值

    这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
  • 常用的日期时间正则表达式

    常用的日期时间正则表达式 下面收藏了大量的日期时间正则匹配函数,包括分钟,时间与秒都能达到。 正则表达式 (?n:^(?=d)((?<day>31(?!(.0?[2469]|11))|30(?!.0?2)|29(...2016-11-25
  • PHP正则表达式匹配验证提取网址URL实例总结

    网址规则是可寻的,所以我们可以使用正则表达式来提取字符串中的url地址了,下面一起来看看小编整理的几个PHP正则表达式匹配验证提取网址URL实例. 匹配网址 URL 的...2016-11-25
  • 正则表达式中两个反斜杠的匹配规则详解

    这篇文章主要介绍了正则表达式中两个反斜杠的匹配规则,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-05-07
  • JS中使用正则表达式g模式和非g模式的区别

    这篇文章给大家详细介绍了JS中使用正则表达式g模式和非g模式的区别,非常不错,具有参考借鉴价值,需要的朋友参考下吧...2017-04-03
  • JavaScript利用正则表达式替换字符串中的内容

    本文主要介绍了JavaScript利用正则表达式替换字符串中内容的具体实现方法,并做了简要注释,便于理解。具有一定的参考价值,需要的朋友可以看下...2017-01-09
  • C#正则表达式使用方法示例

    这篇文章主要介绍了C#正则表达式使用方法,大家参考使用...2020-06-25
  • 常用C#正则表达式汇总介绍

    c#正则表达式,用于字符串处理、表单验证等场合,实用高效。现将一些常用的表达式收集于此,以备不时之需。...2020-06-25
  • 一文秒懂python正则表达式常用函数

    这篇文章主要介绍了python正则表达式常用函数及使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-05-07
  • Idea使用正则表达式批量替换字符串的方法

    这篇文章给大家介绍了Idea使用正则表达式批量替换字符串的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧...2021-07-21
  • PHP正则表达式之捕获组与非捕获组

    今天遇到一个正则匹配的问题,忽然翻到有捕获组的概念,手册上也是一略而过,百度时无意翻到C#和Java中有对正则捕获组的特殊用法,搜索关键词有PHP时竟然没有相关内容,自己试了一下,发现在PHP中也是可行的,于是总结一下,分享的同...2015-11-08
  • C# 中使用正则表达式匹配字符的含义

    正则表达式的作用用来描述字符串的特征。本文重点给大家介绍C# 中使用正则表达式匹配字符的含义,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧...2020-06-25
  • Python验证的50个常见正则表达式

    这篇文章主要给大家介绍了关于利用Python验证的50个常见正则表达式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-11
  • C#编程自学之运算符和表达式

    这篇文章主要介绍了C#运算符和表达式,这是自学C#编程的第五篇,希望对大家的学习有所帮助。...2020-06-25
  • PHP正则表达式过滤html标签属性(DEMO)

    这篇文章主要介绍了PHP正则表达式过滤html标签属性的相关内容,实用性非常,感兴趣的朋友参考下吧...2016-05-06
  • js用正则表达式筛选年月日的实例方法

    在本篇文章里小编给大家整理的是一篇关于js用正则表达式筛选年月日的实例方法,对此有兴趣的朋友们可以学习下。...2021-01-04
  • javascript 手机号码正则表达式验证函数 <font color=red>原创</font>

    随着手机号码段的不断增加,以前网上的手机号码验证函数都不能那么完美的支持了,这里脚本之家编辑特为大家准备的一个简单的正则与手机验证的函数分析。...2021-05-07