分类 PHP技巧 下的文章

必应每日一图(cn.bing.com),指的是 cn.bing.com 网站的背景图片每天00:00就会更新一张。

很多人都喜欢把这些图片当作壁纸(包括我,当然,我并不是手动更换的,而是通过一款软件《必应自动桌面》来实现每天自动更换壁纸,当然,我们的主题是 如何用PHP抓取必应的每日背景图 )。

Bing的每日背景图片官方都有一个接口,一个是 json 方式,一个是 XML 的方式,所以就有了下面的这两个地址。

1.  http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1
2.  http://cn.bing.com/HPImageArchive.aspx?idx=0&n=1

根据上面接口的参数,我大致得出了以下3个参数的解析:


1. format,非必要。我理解为输出格式,不存在或者不等于js,即为xml格式,等于js时,输出json格式;

2. idx,非必要。不存在或者等于0时,输出当天的图片,-1为已经预备用于明天显示的信息,1则为昨天的图片,idx最多获取到前16天的图片信息;*
3. n,必要。这是输出信息的数量,比如n=1,即为1条,以此类推,至多输出8条。


有兴趣的同学可以去研究上面的接口吧,接下来我来贴代码了,我是调用的第二个接口(返回格式是 XML):

<?php
/**
 *Description:获取Bing每日背景图
 *Version:1.0
 *Author:初文
 */
ini_set('date.timezone','Asia/Shanghai');//设置时区,亚洲、上海;老外好像更喜欢上海,所以不能改成 Asia/Beijing
/**
*我对此做了缓存,减轻服务器负载,如果不需要,你可以自己改一下
*/
$tomorrow=strtotime(date('Y-m-d 00:00:00',strtotime('+1 day')));//明天的时间戳
$cache_time=$tomorrow-time();//明天的时间戳-现在的时间戳=缓存的时间,因为必应每日一图,一天换一次...
$modified_time=@$_SERVER['HTTP_IF_MODIFIED_SINCE'];
if(strtotime($modified_time)+$cache_time>time()){//如果缓存的时间戳大于现在的时间戳
	header("HTTP/1.1 304");//发送HTTP状态码304,使浏览器返回缓存的结果
}else{//否则抓取重新抓取图片,返回给用户
	$str=curl_get('http://cn.bing.com/HPImageArchive.aspx?idx=0&n=1');
	if(preg_match("/<url>(.+?)<\/url>/ies",$str,$matches)){
		$imgurl='http://cn.bing.com'.$matches[1];
	}
	if($imgurl){
		header('Content-Type: image/JPEG');
		header ("Last-Modified: ".gmdate("D, d M Y H:i:s", time() )." GMT");//发送Last-Modified头标,设置文档的最后的更新日期。
		header ("Expires: ".gmdate("D, d M Y H:i:s", time()+$cache_time )." GMT");//发送Expires头标,设置当前缓存的文档过期时间,GMT格式。
		header ("Cache-Control: max-age=$cache_time");//发送Cache_Control头标,设置xx秒以后文档过时,可以代替Expires,如果同时出现,max-age优先。
		@ob_end_clean();
		@readfile($imgurl);
		@flush();
		@ob_flush();
		die;
	}else{
		die('error, please try again !');//获取失败,提醒用户刷新页面重试
	}
}
function curl_get($url,$time_out=10){
	$ch=curl_init($url);
	curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);
	curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch,CURLOPT_USERAGENT, 'Mozilla/5.0 (Linux; U; Android 4.4.1; zh-cn; R815T Build/JOP40D) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 Chrome/4.5 Mobile Safari/533.1');
	curl_setopt($ch,CURLOPT_TIMEOUT, $time_out);
	$content=curl_exec($ch);
	curl_close($ch);
	return($content);
}
?>


Demo: https://www.ogdn.net/assets/img/bingimg.php  //仅供演示用,不能用此链接作网站背景链接,因为有防盗链,你弄到网站当背景图也不会显示,要是真有需要,请在下方留言,我抽空做一个外链

我们常常会因为不小心改错了表中的某些数据而使网站无法正常运行 或 手误删了数据库,这时你就会想到定时备份数据库是有多么的重要~

MySQL_从入门到删库跑路

网上搜了一些关于 用PHP备份MySQL 数据库的,发现几乎都没什么用,所以我就自己写了个。

1.这段代码我们将它命名为:mysql.class.php  的文件里<MySQL数据库操作类>

<?php
/*
*MySQL数据库操作类
*/
if(extension_loaded('mysqli')){
	class DB{
		var $link=null;
		function __construct($db_host,$db_user,$db_pass,$db_name,$db_port){
			$this->link=mysqli_connect($db_host,$db_user,$db_pass,$db_name,$db_port);
			if(!$this->link)die('Connect Error ('.mysqli_connect_errno().') '.mysqli_connect_error());
			mysqli_query($this->link,"set sql_mode = ''");//字符转换,读库
			mysqli_query($this->link,"set character set 'utf8'");//写库
			mysqli_query($this->link,"set names 'utf8'");
			return true;
		}
		function fetch($q){
			return mysqli_fetch_assoc($q);
		}
		function get_row($q){
			$result=mysqli_query($this->link,$q);
			return mysqli_fetch_assoc($result);
		}
		function count($q){
			$result=mysqli_query($this->link,$q);
			$count=mysqli_fetch_array($result);
			return $count['0'];
		}
		function query($q){
			return mysqli_query($this->link,$q);
		}
		function escape($str){
			return mysqli_real_escape_string($this->link,$str);
		}
		function insert($q){
			if(mysqli_query($this->link,$q))
				return mysqli_insert_id($this->link);
			return false;
		}
		function affected(){
			return mysqli_affected_rows($this->link);
		}
		function insert_array($table=null,$array=null){//插入数据
			if(isset($table) && isset($array)){
				$q="INSERT INTO `$table`";
				$q.=" (`".implode("`,`",array_keys($array))."`) ";
				$q.="VALUES ('".implode("','",array_values($array))."') ";
				if(mysqli_query($this->link,$q)){
					return mysqli_insert_id($this->link);
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function update_array($table=null,$array=null,$where=null){//更新数据
			/*
      Author: NowTime(初文)
      Email: chenwenzho@aliyun.common
      WriteTime: 2017-01-17 16:03:52
      */
			if($table && $array && $where){
				$qs="UPDATE `$table` SET ";
				$key=array_keys($array);
				$values=array_values($array);
				$q='';
				for($i=0;$i<count($key);$i++){
					$q.="`$key[$i]`='$values[$i]',";
				}
				$qa=$qs.substr($q,0,-1);
				$key=array_keys($where);
				$values=array_values($where);
				$qa.=" WHERE `$key[0]`='$values[0]'";
				if(mysqli_query($this->link,$qa)){
					//return mysqli_insert_id($this->link);
					return $qa;
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function error(){
			$error=mysqli_error($this->link);
			$errno=mysqli_errno($this->link);
			return '['.$errno.'] '.$error;
		}
		function close(){
			$q=mysqli_close($this->link);
			return $q;
		}
	}
}else{//we use the old mysql
	class DB{
		var $link=null;
		function __construct($db_host,$db_user,$db_pass,$db_name,$db_port){
			$this->link=@mysql_connect($db_host.':'.$db_port,$db_user,$db_pass);

			if (!$this->link)die('Connect Error (' . mysql_errno() . ') '.mysql_error());
			mysql_select_db($db_name, $this->link) or die(mysql_error($this->link));
			mysql_query("set sql_mode = ''");//字符转换,读库
			mysql_query("set character set 'utf8'");//写库
			mysql_query("set names 'utf8'");
			return true;
		}
		function fetch($q){
			return mysql_fetch_assoc($q);
		}
		function get_row($q){
			$result=mysql_query($q,$this->link);
			return mysql_fetch_assoc($result);
		}
		function count($q){
			$result=mysql_query($q,$this->link);
			$count=mysql_fetch_array($result);
			return $count['0'];
		}
		function query($q){
			return mysql_query($q,$this->link);
		}
		function escape($str){
			return mysql_real_escape_string($str,$this->link);
		}
		function affected(){
			return mysql_affected_rows($this->link);
		}
		function insert($q){
			if(mysql_query($q,$this->link))
				return mysql_insert_id($this->link);
			return false;
		}
		function insert_array($table=null,$array=null){
			if(isset($table) && isset($array)){
				$q="INSERT INTO `$table`";
				$q.=" (`".implode("`,`",array_keys($array))."`) ";
				$q.=" VALUES ('".implode("','",array_values($array))."') ";
				if(mysql_query($q,$this->link)){
					return mysql_insert_id($this->link);
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function update_array($table=null,$array=null,$where=null){//更新数据
			/*
      Author: NowTime(初文)
      Email: chenwenzho@aliyun.common
      WriteTime: 2017-01-17 16:03:52
      */
			if($table && $array && $where){
				$qs="UPDATE `$table` SET ";
				$key=array_keys($array);
				$values=array_values($array);
				$q='';
				for($i=0;$i<count($key);$i++){
					$q.="`$key[$i]`='$values[$i]',";
				}
				$qa=$qs.substr($q,0,-1);
				$key=array_keys($where);
				$values=array_values($where);
				$qa.=" WHERE `$key[0]`='$values[0]'";
				if(mysql_query($this->link,$qa)){
					//return mysql_insert_id($this->link);
					return $qa;
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function error(){
			$error=mysql_error($this->link);
			$errno=mysql_errno($this->link);
			return '['.$errno.'] '.$error;
		}
		function close(){
			$q=mysql_close($this->link);
			return $q;
		}
	}

}
?>

2.这段代码放到命名为:hunction.php 的文件里<自定义函数>

<?php
function backs_tables($array,$back_path=ROOT){
	@mkdir($back_path);
	global $DB,$db_name,$start_time;
	$now=date('Y年m月d日 H时i分s秒');
	$head="--\n-- 数据库: `$db_name`\n--\n-- 导出日期: `$now`\n--\n\n--\n-- Author: 初文\n--\n-- QQ: 1361289290\n--\n-- blog: https://blog.ogdn.net\n--\n\n";

	$sqls='';
	if($array['0']=='*'){
		$result=$DB->query("SHOW TABLES");
		$count=0;
		while($row=$DB->fetch($result)){
			$count++;
			$sqls.=dataBak($row['Tables_in_test']);
		}
	}else{
		$count=count($array);
		for($i=0;$i<$count;$i++){
			$sqls.=dataBak($array[$i]);
		}
	}
	$foot="\n--\n-- 备份完成,耗时: ".(time()-$start_time)." s, 共计备份 $count 个表, 备份完成时间".date('Y年m月d日 H时i分s秒')."\n--";
	$sql=$head.$sqls.$foot;
	$filename=$db_name."_".date('YmdHis')."_".time()."_".rand(0,9).".sql";//文件名
	$fp=fopen($back_path.$filename,'w');
	fputs($fp,$sql);
	fclose($fp);
	return $foot."\n-- 备份文件大小: ".((strlen($sql)/1024)/1024)." M\n-- 文件绝对路径: ".$back_path."\n--";
}

/**
 * @name 输出数据库结构和所有数据
 * @author 初文, E-mail: chenwenzho@aliyun.com
 * @global $DB
 * @param string $table 数据库表名
 * @return string
 * @version 1.0
 */
function dataBak($table){
	global $DB;

	$sql="DROP TABLE IF EXISTS `$table`;\n";
	$createtable=$DB->query("SHOW CREATE TABLE $table");
	$create=$DB->fetch($createtable);
	$sql.=$create['Create Table'].";\n\n";

	$rows=$DB->query("SELECT * FROM $table");

	while($row=$DB->fetch($rows)){
		$comma='';
		$sql.="INSERT INTO `$table` VALUES(";
		foreach($row as $value){
			$sql.=$comma."'".$value."'";
			$comma=',';
		}
		$sql.=");\n";
	}
	return $sql;
}
?>

3.接下来,这段就是执行备份的代码了(你需要更改这些数据库的信息、访问密钥 和 存放备份文件的 路径),把这段代码把他放到 take_backdata.php 文件里(你也可以把它放到其他命名的文件里)

<?php
$start_time=time();
ini_set('memory_limit','1024M');//加上这两行,可以备份大数据,昨晚测了一下公司的一个600M的表,很快就可以备份成功
ini_set('max_execution_time','0');
define('ROOT',dirname(__FILE__)."/");//定义一个绝对路径,如果用Linux或者windows的计划任务定时执行PHP来执行备份,必须要用绝对路径,相对路径会报错,备份存放放的路径也要使 “绝对路径”!否则会报错
require_once(ROOT."mysql.class.php");//引入MySQL数据库操作类
require_once(ROOT."function.php");//引入自定义函数

$key='1361289290';//访问密钥, 关系到数据的安全, 尽量设置强一点!
$back_path=ROOT."Cache/";//要存放备份数据的位置(即目录地址), 最后面一定要有 / ,现在是保存在本文件(take_backdata.php)所处的路径下的 Cache 文件夹里, 关系到数据的安全, 存放路径最好弄的复杂点
$db_host='127.0.0.1';//数据库连接地址
$db_port=3306;//数据库端口
$db_user='root';//数据库用户名
$db_pass='root';//数据库密码
$db_name='test';//数据库库名

$need_back_tables=Array('*');//需要备份的表,*为全部备份
/**
 * 以Emlog博客程序的数据库表做示例:
 * $need_back_table=Array('*');//需要导出的表,*为全部表都备份
 * $need_back_table=Array('emlog_attachment');//备份 emlog_attachment 这1个表
 * $need_back_table=Array('emlog_attachment','emlog_comment');//备份 emlog_attachment 和 comment 这2个表
 * $need_back_table=Array('emlog_attachment','emlog_comment','emlog_options');//备份 emlog_attachment 、 comment 和 options 这3个表
 * ...以此类推
 */

if(php_sapi_name()==='cgi' || php_sapi_name()==='cli'){//如果是以CGI或CLI运行的PHP, 则可以免输入密码
	$DB=new DB($db_host,$db_user,$db_pass,$db_name,$db_port);//连接数据库
	echo "\nYou are using ".strtoupper(php_sapi_name())." run PHP.\n";
	echo "--\n-- 备份开始: ".date('Y年m月d日 H时i分s秒',$start_time)."\n--\n\n";
	echo backs_tables($need_back_tables,$back_path);//输出备份的结果
}elseif(@$_GET['key']===$key){
	$DB=new DB($db_host,$db_user,$db_pass,$db_name,$db_port);//连接数据库
	header("Content-Type: text/json;Charset=UTF-8");
	echo "--\n-- 备份开始: ".date('Y年m月d日 H时i分s秒',$start_time)."\n--\n\n";
	echo backs_tables($need_back_tables);//输出备份的结果
}else{
	die('你没有访问权限!');
}
?>

配置好后,你就可以访问了,亲测55M左右数据库备份完成耗时 11 秒,以下是本地执行的截图:

本地执行备份截图

以下是命令行执行的结果截图(命令行执行的速度比较快,因为她不用经过Apache/Nginx等解析就可以执行):

命令行执行结果


好了,这下可以添加监控定时执行(http://.../take_backdata.php?key=你设置的访问密钥);或者你用的Linux/Windows服务器可以添加计划任务执行,你可以自己在网上搜相关教程。

本站所用到的文件下载地址:PHP备份MySQL数据库.zip