取所有内容中图片的地址我们必须使用正则表达式来匹配了,如果不使用它来匹配我们是无法获取到或才能获取到也是非常的麻烦了,下面我们一起来看看我整理了几段匹配图片地址程序代码吧。
图片网址规范的html代码无非就是
《img title="??" src="/wp-admin/%E5%9B%A73" alt="??" title="??" width="5" height="6" /》
??和??是非必需的,若要通过XHTML认证??、??、??必不可少,??是核心内容,当然就不能少了。
就正则谈正则的话,我写出的最短匹配是
(?<=img.+?src=").*?(?=")
不过,这条在php里不行,会出现:
Warning: preg_match_all() [function.preg-match-all]: Compilation failed: lookbehind assertion is not fixed length at offset *** in ***
纠结了很久,都不行,原因何在呢?试了很多次,终于发现问题在(?<=img.+?src=")这个零宽断言里,在php中,零宽断言里不支持类似“*”、“+”这些无限次的东西,于是报错了,把“.+?”改为定长就好。不过,要“img”和“src=”之间定长基本上是不可能的。通常,图片地址的img和src只会相隔一个很简单的空格,但不排除某些情况在src之前,img后有alt、titlte等东西。
所以
(?<=img.src=").*?(?=")
或
(?<=img\ssrc=").*?(?=")
可能可以,但不保证100%没问题。
你也许会问,单纯
(?<=src=").*?(?=")
不行吗?通常情况,可以,但,搜索过页面的盆友应该知道,除了图片地址用src开头以外,javascript地址也用src开头!而且,太多神通广大的不可预知因素隐含其中,于是这个貌似很简短完美的写法就行不通了。
你又或许会问,聪明简短的不行,我把图片的后缀列出来,总该可以了吧,如
(?<=src=").*?\.(jpg|jpeg|gif|png|bmp|JPG|JPEG|GIF|PNG|BMP)
的确,这个写法实在是很老实,不过,你见过没有后缀的图片?wwe.com 有很多这种例子呢
段一,匹配地址方法
内容:
代码如下 |
复制代码 |
<a href="/item/2864756" target="_blank"><img src="/pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg" height="268" width="200px"/></a>
<a href="/item/2864756" target="_blank"><img src="/pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg" height="268" width="200px"/></a>
<a href="/item/2864756" target="_blank"><img src="/pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg" height="268" width="200px"/></a>
PHP代码:
$p = "/src=\"([^\"]+)/isu";
//$p = "/<[^>]+>/isu";
//$p = "/<a[^>]+>/isu";
preg_match_all($p, $html, $m);
var_dump($m);
结果:
Array
(
[0] => Array
(
[0] => src="/pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg
[1] => src="/pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg
[2] => src="/pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg
[1] => Array
(
[0] => /pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg
[1] => /pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg
[2] => /pic/r/e6/14/28b4766b65373ae6a3b3faccc81f_400_536.jpg
)
)
|
段二,
代码如下 |
复制代码 |
newstext=preg_replace(preg_replace('/(<img[^>]+src\s*=\s*”?([^>"\s]+)”?[^>]*>)/im', ‘<a href=”$2″>$1</a>', $newstext);
|
1.preg_replace和str_replace的区别:
str_replace只是纯字符替换,而preg_replace才是正则替换
2.$0,$1,$2等的说明:
$0指的是被整个模式所匹配的文本;
$1指的是首个 ( ) 引用的串;
$2指的是第二个()引用的串; 以此类推。
防止表单重复提交的解决方案非常的简单,我们下面两个例子都是生成一个随机的token验证用户是不是由我们站内提交并且进行重复验证即可实现了。
在网上搜索了一下有很多站长都这样说的
1、提交按钮置disabled
当用户提交后,立即把按钮置为不可用状态。这种用js来实现。
提交前代码如下:
代码如下 |
复制代码 |
$("#submit").attr('disabled','true');
$("#submit").val("正在提交,请稍等");
|
执行后,把按钮置为原来状态
代码如下:
代码如下 |
复制代码 |
$('#submit ').removeAttr('disabled');
$("#submit ").val("确定提交");
|
这样只是针对一些简单的前台提交了,如果我们自己做个表单站长提交给我们php逻辑层文件就过滤这那个js了。
过期时间法
用户提交按钮后生成一个token(每次业务提交token 为唯一值)存入session,并设置过期时间。当用户再此提交时,检测token是否一致且是否过期,若一致且没有过期,则认为提交了二次
例子
代码如下 |
复制代码 |
<?php
/*
* PHP简单利用token防止表单重复提交
* 此处理方法纯粹是为了给初学者参考
*/
session_start();
function set_token() {
$_SESSION['token'] = md5(microtime(true));
}
function valid_token() {
$return = $_REQUEST['token'] === $_SESSION['token'] ? true : false;
set_token();
return $return;
}
//如果token为空则生成一个token
if(!isset($_SESSION['token']) || $_SESSION['token']=='') {
set_token();
}
if(isset($_POST['test'])){
if(!valid_token()){
echo "token error";
}else{
echo '成功提交,Value:'.$_POST['test'];
}
}
?>
<form method="post" action="">
<input type="hidden" name="token" value="<?php echo $_SESSION['token']?>">
<input type="text" name="test" value="Default">
<input type="submit" value="提交" />
</form>
|
方法二
代码如下 |
复制代码 |
<?php
//开启session
session_start();
//如果有提交标识
if(isset($_GET['action']) && $_GET['action'] === 'save'){
//如果有session且跟传过来的值一样才算提交
if(isset($_SESSION['__open_auth']) && isset($_POST['auth']) && $_SESSION['__open_auth'] == $_POST['auth']){
print_r($_POST);
$_SESSION['__open_auth'] = null;//清空
} else {
//走起
header("location: post.php");
}
exit();
}
//授权
$auth = $_SESSION['__open_auth'] = time();
?>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>post</title>
</head>
<body>
<form action="post.php?action=save" method="post">
<ul>
<li>
<input type="hidden" name="auth" value="<?php echo $auth;?>">
<input type="text" name="userName">
</li>
<li>
<input type="password" name="userpass">
</li>
<li>
<input type="submit" value="走起">
</li>
<li>
<?php echo time(); ?>
</li>
</ul>
</form>
</body>
</html>
|
mysql php数据库重复记录防止
代码如下 |
复制代码 |
<?php
$link=mysql_connect(‘localhost’,’root’,’1234’); //得到MySQL数据库连接
$username=$_GET["name"]; //得到从客户端表单传过来的数据
$q="select * from usertable where user_name='$username'";
mysql_query("SET NAMES gb2312"); //避免出现中文乱码
$rs = mysql_query($q, $link); //查询数据库
$num_rows = mysql_num_rows($rs); //得到查询结果的总行数
if($num_rows==0)
// 烈火? liehuo.net 欢迎复制,拒绝恶意采集 liehuo.net
{
$exec="insert into student (user_name) values ($username)";
mysql_query("SET NAMES gb2312");
mysql_query($exec, $link); //若没有此用户则将数据插入到数据库(注册用户)
echo "用户注册成功!";
}
else
{
echo "该用户名已存在,请重新选择用户名!";
}
?>
|
session过期法有非常重要的一点是一个session设置与提交成功与不成功时的一个session验证了,这个有点像登录一样的如果登录成功了我们要清除session这个原理也差不多。
网页返回状态代码很多站长会去查自己网站状态码是不是200或错误页面是不是404代码了,那么我们使用最多的查看方法就是使用站长工具或ff浏览器来查,但有很多朋友不知道可以自己写一个查看状态代码的功能哦。
方法一,使用 fsockopen
严重鄙视curl_getinfo!
代码如下 |
复制代码 |
function get_http_code($url="localhost", $port=80, $fsock_timeout=10){
set_time_limit(0);
ignore_user_abort(true);
// 记录开始时间
list($usec, $sec) = explode(" ", microtime(true));
$timer['start'] = (float)$usec + (float)$sec;
// 校验URL
if(!preg_match("/^https?:\/\//i", $url)){
$url = "http://".$url;
}
// 支持HTTPS
if(preg_match("/^https:\/\//i", $url)){
$port = 443;
}
// 解析URL
$urlinfo = parse_url($url);
if(empty($urlinfo['path'])){
$urlinfo['path'] = '/';
}
$host = $urlinfo['host'];
$uri = $urlinfo['path'] . (empty($urlinfo['query'])?'':$urlinfo['query']);
// 通过fsock打开连接
if(!$fp = fsockopen($host, $port, $errno, $error, $fsock_timeout)){
list($usec, $sec) = explode(" ", microtime(true));
$timer['end'] = (float)$usec + (float)$sec;
$usetime = (float)$timer['end'] - (float)$timer['start'];
return array('code'=>-1, 'usetime'=>$usetime);
}
// 提交请求
$status = socket_get_status($fp);
$out = "GET {$uri} HTTP/1.1\r\n";
$out .= "Host: {$host}\r\n";
$out .= "Connection: Close\r\n\r\n";
$write = fwrite($fp, $out);
if(!$write){
list($usec, $sec) = explode(" ", microtime(true));
$timer['end'] = (float)$usec + (float)$sec;
$usetime = (float)$timer['end'] - (float)$timer['start'];
return array('code'=>-2, 'usetime'=>$usetime);
}
$ret = fgets($fp, 1024);
preg_match("/http\/\d\.\d\s(\d+)/i", $ret, $m);
$code = $m[1];
fclose($fp);
list($usec, $sec) = explode(" ", microtime(true));
$timer['end'] = (float)$usec + (float)$sec;
$usetime = (float)$timer['end'] - (float)$timer['start'];
return array('code'=>$code, 'usetime'=>$usetime);
}
|
file_get_contents 是 fsockopen 功能的简单打包,效率稍低些,但是抓取成功率很高,所以在 snoopy 出问题的时候我一般那他来。5.0.0 添加了对 context 的支持,有了context,他也可以发送 header 信息,自定义用户 agent, referer, cookies 都不在话下。5.1.0 添加了 offset 和 maxlen 参数,可以只读文件的一部分内容。
方法二,使用snoopy.class.php
Snoopy是一个php类,用来模拟浏览器的功能,可以获取网页内容,发送表单。
代码如下 |
复制代码 |
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.spiegel.de/');
curl_setopt($ch, CURLOPT_RANGE, '0-500');
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
/**
*But as noted before if the server doesn't honor this header but sends the whole file curl will download all of it. E.g. http://www.111cn.net ignores the header. But you can (in addition) set a write function callback and abort the request when more data is received, e.g.
* php 5.3+ only
* use function writefn($ch, $chunk) { ... } for earlier versions
*/
$writefn = function($ch, $chunk) {
static $data='';
static $limit = 500; // 500 bytes, it's only a test
$len = strlen($data) + strlen($chunk);
if ($len >= $limit ) {
$data .= substr($chunk, 0, $limit-strlen($data));
echo strlen($data) , ' ', $data;
return -1;
}
$data .= $chunk;
return strlen($chunk);
};
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.111cn.net/');
curl_setopt($ch, CURLOPT_RANGE, '0-500');
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $writefn);
$result = curl_exec($ch);
curl_close($ch);
|
一些常见的状态码为:
200 - 服务器成功返回网页
404 - 请求的网页不存在
503 - 服务器超时
301 - 页面重定向
为了更好的控制php程序同时操作的一些问题我整理了一个进程锁的类我们可以利用这个进程锁实现程序的控制
程序代码如下
代码如下 |
复制代码 |
<?php
//+----------------------------------------------
//| Usage:
//+----------------------------------------------
//| public function _initialize(){
//| import('@.Util.PHPLock');
//|
//| if(PHPLock::islocked()){
//| echo "[+] Status: Locked\n";
//| echo "[+] Exit\n";
//| exit();
//| }else{
//| echo "[+] Status: Unlocked\n";
//| echo "[-] Locking Now\n";
//| PHPLock::lock();
//| }
//| }
//|
//| function __destruct(){
//| if(true === PHPLock::unlock()){
//| echo "[+] Unlock Success\n";
//| }
//| }
//+----------------------------------------------
class PHPLock
{
const PHPLOCK_TIMEOUT = 1200;
static private $pid = null;
static public function lock(){
$key = self::__getKey();
self::$pid = time();
F($key, self::$pid);
return true;
}
static public function unlock(){
$key = self::__getKey();
if(self::$pid){
F($key, null);
return true;
}
return;
}
static public function islocked(){
$key = self::__getKey();
$time = F($key);
if(!$time){
return false;
}elseif(time() - $time >= self::getTimeout()){
self::unlock();
return false;
}else{
return true;
}
}
static public function getTimeout(){
$key = str_replace(self::__getKey(), '_Lock', '_TIMEOUT');
$expire = C($key) ? C($key) : self::PHPLOCK_TIMEOUT;
return $expire;
}
static private function __getKey(){
return (defined('GROUP_NAME') ? GROUP_NAME.'_' : '') . MODULE_NAME . '_' . ACTION_NAME . '_Lock';
}
}
?>
|
$_FILES与move_uploaded_file就可以在php代码中实现文件或图片上传了,这个比起很多编程语言来讲php上传功能是最简单最好用的了,下面来看个上传图片工作代码。
代码如下 |
复制代码 |
<?php
session_start();
?>
<html xmlns="http://www.111cn.net/ 1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PHP上传文件</title>
<style>
* {margin:0; padding:0; list-style:none;}
.content {width:400px; height:200px; margin:0 auto; margin-top:60px;
background:#ffd3b6; border:dashed 1px #f90}
.content h1 { width:400px; height: 30px; line-height:30px; text-align:
center; font-family:"微软雅黑"; font-size:14px; color:#000}
.content .error {width:300px; height:30px; line-height:30px;
text-align:center; margin:0 auto; color:#f00}
.content .con {width:340px; height:auto; margin:0 auto; font-size:12px;}
.content #file { width:280px; height:20px; border:solid 1px #ccc;
background:#fff; margin:10px 0px 6px 0; font-size:12px;}
.content #send { width:60px; height:22px; border:solid 1px #ccc;
background:#fff; font-size:12px; margin-top:10px;}
</style>
</head>
<body>
<div>
<h1>文件上传</h1>
<div>
<div>
<?php
if ($_GET['up']==up) {
if ($_SESSION['file']==$_GET['irand']) {
$_size=20000; //设置限制文件大小
$_dir='phone/'; //文件保存目录
function size($_size) {
//判断文件大小是否大于1024bit 如果大于,则将大小取值为KB
if ($_size>1024*1024) {
return round($_size/1024/1024,2).' MB';
}else if ($_size>1024) {
$_size=$_size/1024;
return ceil($_size).'KB';
}else {
return $_size.' bit';
}
}
//设置上传图片的类型,设置图片上传大小
$_upfiles = array('image/jpeg','image/pjpeg','image/png','image/x-png','image/gif');
if (is_array($_upfiles)) {
if (!in_array($_FILES['userfile']['type'],$_upfiles)) {
exit('请上传格式为:jpg,png,gif的文件<br /><a href="upload.php">返回</a>');
}
}
if ($_FILES['userfile']['size']>$_size) {
exit('上传文件不能超过:'.size($_size));
}
if ($_FILES['userfile']['error']>0) {
switch ($_FILES['userfile']['error']) {
case 1: echo '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值';
break;
case 2: echo '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值';
break;
case 3: echo '文件只有部分被上传';
break;
case 4: echo '没有文件被上传';
break;
case 6: echo '找不到临时文件夹';
break;
case 7: echo '文件写入失败';
break;
}
exit;
}
//获取文件扩展名
if (!is_dir($_dir)) {
mkdir($_dir,0700);
}
$_rand=mt_rand(0,100000);
$_n=explode('.',$_FILES['userfile']['name']); //将文件名分割
$_file_len=count($_n); //返回数组长度
$_name=$_dir.time().'_'.$_rand.'.'.$_n[$_file_len-1];
if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
if (!@move_uploaded_file($_FILES['userfile']['tmp_name'],$_name)) {
exit('文件移动失败');
}else {
echo '文件上传成功<br />';
echo '文件路径:'.$_name.'<br />';
echo '文件大小:'.size(filesize($_name));
echo '<br /><a href="upload.php">返回继续上传</a>';
}
}else {
exit('上传的临时文件不存在,无法将文件移动到指定文件夹');
}
//销毁session变量,有几种方法
//第一种,销毁所有session变量:session_destroy();
//第二种:销毁单个如:$_SESSION['file']=''
session_destroy();
exit;
}else {
exit('您已经提交过了,不能重复提交<br /><a href="upload.php">返回</a>');
}
}
?>
</div>
<?php $_irand=mt_rand(0,1000000); $_SESSION['file']=$_irand; ?>
<form action="?up=up&irand=<?php echo $_irand; ?>" method="post" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
<input type="file" name="userfile" id="file"/><br />
<input type="submit" name="send" value=" 点击上传 " id="send"/>
</form>
</div>
</div>
</body>
</html>
|