王新阳

wangxinyang

简单的PHP采集示例

<?php
header('Content-type: text/html; charset=utf-8');
set_time_limit(900);
$a=<<<EOD
复制html内容到这里
EOD;
//获取需要的链接
preg_match_all('/\\/chapter\\/110701\\/\\d+\\.html/i', $a, $arr);
//得到完整链接地址
$arr = explode(',', 'http://vip.book.sina.com.cn' . implode(',http://vip.book.sina.com.cn', $arr[0]));
$b = '文章正文内容开始前面的html';
$c = '/正则匹配章节标题和章节内容之间的html,如果此部门内容没有时间等不同的字符,可以直接用str_replace而不是preg_replace';
$e = '文章正文内容结束后面的html';
$result = '';
//要获取的文章内容
$txt = fopen('e:/web/abc.txt', 'wb');
ob_start();
for ($i = 0; $i < count($arr); $i++) {
	$result = '';
	$str = file_get_contents($arr[$i]);
	//也可以用curl
	$str = explode($b, $str);
	$str = explode($e, count($str) > 1 ? $str[1] : $str[0]);
	$str = explode('</h1>', $str[0], 2);
	$result = $str[0] . "\r\n";
	$str = preg_replace($c, '', $str[1]);
	$str = str_replace('<p>', '', $str);
	$str = str_replace('</p>', "\r\n", $str);
	$result .= $str;
	fwrite($txt, $result);
	echo str_replace("\r\n", '<br />', $result);
	flush();
}
fclose($txt);


file_get_contents()抓取 https 地址时出错:
SSL operation failed with code 1. OpenSSL Error message

原因是证书校验不通过,可以设置忽略证书校验:

$option=array(
	'ssl'=>array('verify_peer' => false, 'verify_peer_name' => false)
);
$stream=stream_context_create($option);
file_get_contents($url, false, $stream);

PHP curl示例

cur进行https请求时,如果出现 curl: (35) SSL connect error
一般是发起请求的服务器ssl_version为 NSS 需要改为 openSSL

/**
 * 通过curl请求远程数据
 * @param string $url
 * @param string $request_method 默认GET
 * @param array $post_data 默认null
 * @param string $do_what http_build_query/json_encode
 * @param array $opt_array 批量设置特殊选项
 * @return FALSE | string
 */
function my_curl($url, $request_method='GET', $post_data=NULL, $do_what='', $opt_array=NULL){
	$arr_header = array();
	if($post_data){
		switch($do_what){
			case 'json_encode': //需要发送json数据时,对数组或对象进行json编码(微信开发此处不能包含中文,否则会有:不合法的请求字符,不能包含\uxxxx格式的字符)
				$post_data = json_encode($post_data);
				$arr_header[] = 'Content-length: '.strlen($post_data);
				break;
			case 'http_build_query':
				$post_data = http_build_query($post_data); //对数组或对象使用http_build_query()以提高兼容性
				$arr_header[] = 'Content-length: '.strlen($post_data);
				break;
			default:
		}
	}
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //curl_exec执行成功则返回结果(默认返回true),失败返回false
	curl_setopt($ch, CURLOPT_HEADER, false); //启用时会将头文件的信息作为数据流输出
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); //连接超时时间
	if(count($arr_header))curl_setopt($ch, CURLOPT_HTTPHEADER, $arr_header);
	if(strtolower($request_method)=='post')curl_setopt($ch, CURLOPT_POST, true); //POST方式时添加
	if(strpos(strtolower($url), 'https://')===0){
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //https请求时跳过cURL验证对等证书
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //https请求时跳过cURL验证域名
	}
	if($post_data)curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
	if(is_array($opt_array) && count($opt_array))curl_setopt_array($ch, $opt_array);
	$output = curl_exec($ch);
//	$outinfo = curl_getinfo($ch);
	$err_no = curl_errno($ch);
	$curl_error = $err_no ?  'curl: '.curl_error($ch)." $err_no" : ''; //失败时返回当前会话最后一次错误的字符串
	curl_close($ch);
	if($err_no){
		log_message('error', $curl_error);
		return FALSE;
	}else{
		return $output;
	}
}

PHP基础知识

● array get_defined_constants ([ bool $categorize = false ] )
返回当前所有已定义的常量名和值,$categorize=true 时返回常量分类后的多维数组

json_encode($value, $flag)
对变量主要是数组进行 JSON 编码

json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

JSON_ERROR_NONE (int)
没有错误发生。
JSON_ERROR_DEPTH (int)
到达了最大堆栈深度。
JSON_ERROR_STATE_MISMATCH (int)
出现了下溢(underflow)或者模式不匹配。
JSON_ERROR_CTRL_CHAR (int)
控制字符错误,可能是编码不对。
JSON_ERROR_SYNTAX (int)
语法错误。
JSON_ERROR_UTF8 (int)
异常的 UTF-8 字符,也许是因为不正确的编码。
JSON_ERROR_RECURSION (int)
传递给 json_encode() 函数的对象或数组包含了递归引用,导致无法被编码。如果打开了 JSON_PARTIAL_OUTPUT_ON_ERROR 选项,则牵涉到递归引用的数据会转换成 null 后返回。
JSON_ERROR_INF_OR_NAN (int)
传递给 json_encode() 函数的参数中包含了 NAN 或 INF,导致编码出错。如果打开了 JSON_PARTIAL_OUTPUT_ON_ERROR 选项,则牵涉到对应不可编码的数字,会转换成数字 0 后返回。
JSON_ERROR_UNSUPPORTED_TYPE (int)
传递了不支持的数据类型给 json_encode() 函数,比如 resource。如果打开了 JSON_PARTIAL_OUTPUT_ON_ERROR 选项,则对于不支持的数据类型,会转换成 null 后返回。
JSON_ERROR_INVALID_PROPERTY_NAME (int)
A key starting with \u0000 character was in the string passed to json_decode() when decoding a JSON object into a PHP object.
JSON_ERROR_UTF16 (int)
Single unpaired UTF-16 surrogate in unicode escape contained in the JSON string passed to json_encode().
下面的常量可以和 json_decode() 的 form 选项结合使用。

JSON_BIGINT_AS_STRING (int)
将大数字编码成原始字符原来的值。
JSON_OBJECT_AS_ARRAY (int)
将 JSON 对象作为数组解码。当调用 json_decode() 且第二个参数为 true 时此选项会自动添加。
下面的常量可以和 json_encode() 的 form 选项结合使用。

JSON_HEX_TAG (int)
所有的 < 和 > 转换成 \u003C 和 \u003E。
JSON_HEX_AMP (int)
所有的 & 转换成 \u0026。
JSON_HEX_APOS (int)
所有的 ' 转换成 \u0027。
JSON_HEX_QUOT (int)
所有的 " 转换成 \u0022。
JSON_FORCE_OBJECT (int)
使一个非关联数组输出一个类(Object)而非数组。 在数组为空而接受者需要一个类(Object)的时候尤其有用。
JSON_NUMERIC_CHECK (int)
将所有数字字符串编码成数字(numbers)。
JSON_PRETTY_PRINT (int)
用空白字符格式化返回的数据。
JSON_UNESCAPED_SLASHES (int)
不要编码 /。
JSON_UNESCAPED_UNICODE (int)
以字面编码多字节 Unicode 字符(默认是编码成 \uXXXX)。
JSON_PARTIAL_OUTPUT_ON_ERROR (int)
用不可编码的值来代替失败。
JSON_PRESERVE_ZERO_FRACTION (int)
确保 float 值始终编码为为 float 值。
JSON_UNESCAPED_LINE_TERMINATORS (int)
The line terminators are kept unescaped when JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was before PHP 7.1 without this constant. Available since PHP 7.1.0.
下面的常量可以和 json_decode() 及 json_encode() 的 form 选项结合使用。

JSON_INVALID_UTF8_IGNORE (int)
忽略无效的 UTF-8 字符。自 PHP 7.2.0 起生效。
JSON_INVALID_UTF8_SUBSTITUTE (int)
将无效 UTF-8 字符转换为 \0xfffd(Unicode 字符"虚缺号")。自 PHP 7.2.0 起生效。
JSON_THROW_ON_ERROR (int)
如果发生错误则会抛出 JsonException,而不是通过 json_last_error() 和 json_last_error_msg() 检索设置到全局的错误状态。JSON_PARTIAL_OUTPUT_ON_ERROR 优先于 JSON_THROW_ON_ERROR。自 PHP 7.3.0 起生效。

json_decode(string $json [, bool $assoc)
对 JSON 格式的字符串进行编码
当参数$assoc为 TRUE 时,将返回 array 而非 object 。

serialize(mixed $value)
产生一个可存储的值的表示,主要是把数组转换成字符串,便于传递
结果默认已经转义,无须再用 addslashes()

unserialize(string $str)
从已存储的表示中创建 PHP 的值,主要是把字符串还原成数组

● array get_defined_vars   — 获取由所有已定义变量所组成的数组

● array get_defined_functions — 获取所有已经定义的函数

● array get_loaded_extensions — 获取所有可用的模块

● array get_extension_funcs — 获取指定模块的可用函数,传入的参数(模块名称)必须是小写
  print_r(get_extension_funcs("gd"));
  print_r(get_extension_funcs("xml")); 

● array get_defined_constants — 获取关联数组的名字所有的常量和他们的价值

● array get_declared_classes — 获取由已定义类的名字所组成的数组

● get_included_files() 和 get_required_files()  — 返回被 include 和 require 文件名的 array

● 用 PHP_EOL 代替写入文本文件的回车换行(windows系统为 \r\n ,unix系统为 \n ,MAC 为 \r ,MAC OS X 为 \n

file_put_contents($file, $data, FILE_APPEND | LOCK_EX) 
  FILE_APPEND | LOCK_EX 追加方式写入,且写入时锁定

int memory_get_usage ([ bool $real_usage = false ] )
返回当前分配给你的 PHP 脚本的内存量,单位是字节(byte)。
int memory_get_peak_usage ([ bool $real_usage = false ] )
返回分配给你的 PHP 脚本的内存峰值字节数。
如果设置为 TRUE 可以获取从系统分配到的真实内存尺寸。 如果未设置,或者设置为 FALSE,仅会报告 emalloc() 使用的内存。

几个 PHP 的"魔术常量"

名称说明
__LINE__文件中的当前行号。
__FILE__文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。自 PHP 4.0.2 起,__FILE__ 总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路径),而在此之前的版本有时会包含一个相对路径。
__DIR__文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于 dirname(__FILE__)。除非是根目录,否则目录中名不包括末尾的斜杠。(PHP 5.3.0中新增) =
__FUNCTION__函数名称(PHP 4.3.0 新加)。自 PHP 5 起本常量返回该函数被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。
__CLASS__类的名称(PHP 4.3.0 新加)。自 PHP 5 起本常量返回该类被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。类名包括其被声明的作用区域(例如 Foo\Bar)。注意自 PHP 5.4 起 __CLASS__ 对 trait 也起作用。当用在 trait 方法中时,__CLASS__ 是调用 trait 方法的类的名字。
__TRAIT__Trait 的名字(PHP 5.4.0 新加)。自 PHP 5.4 起此常量返回 trait 被定义时的名字(区分大小写)。Trait 名包括其被声明的作用区域(例如 Foo\Bar)。
__METHOD__类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)。
__NAMESPACE__当前命名空间的名称(区分大小写)。此常量是在编译时定义的(PHP 5.3.0 新增)。

PHP函数处理函数


CodeIgniter命名规则

1、类文件的命名必须以大写字母开头,其他文件(配置文件,视图,一般的脚本文件等)的命名是全小写。类文件的名称必须和类的名称保持一致,例如,如果你有一个类名为 Myclass , 那么文件名应该是 Myclass.php 。

2、类名(core、libraries、helpers)必须以大写字母开头,多个单词之间使用下划线分割,不要使用驼峰命名法。

3、扩展类需要加前缀MY_(可以在application/config/config.php中自定义$config['subclass_prefix']),类名首字母大写,如扩展核心类CI_Controller:
class MY_Controller extends CI_Controller{}

4、类的方法应该使用全小写,并且应该明确指出该方法的功能,最好包含一个动词。 避免使用冗长的名称,多个单词之间使用下划线分割。

5、辅助函数的文件名全小写,但扩展CI自带的辅助函数需要加config中自定义的前缀MY_。如扩展array_helper.php的文件名应该为 MY_array_helper.php

6、变量的命名规则和类方法的命名规则非常接近,使用全小写,使用下划线分割, 并且应该明确指出该变量的用途。非常短的无意义的变量只应该在 for 循环中作为迭代器使用。

7、控制器放在子目录中,如 application/controllers/Product/Tv.php 中方法 detail() ,访问地址为: index.php/Product/tv/detail 子目录名大小写必须与实际一致(windows系统可不区分)

http://codeigniter.org.cn/user_guide/general/styleguide.html

PHP函数用法

1、string number_format ( float $number , int $decimals = 0 , string $dec_point = "." , string $thousands_sep = "," )
  本函数可以接受1个、2个或者4个参数(注意:不能是3个):


2、int strtotime(string $time [, int $now = time() ])
  时间运算

<?php
echo strtotime("now"), "\n";
echo strtotime("10 September 2000"), "\n";
echo strtotime("+1 day 2010-01-01 12:20:25"), "\n";
echo strtotime("+1 day"), "\n";
echo strtotime("+1 week"), "\n";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
echo strtotime("next Thursday"), "\n";
echo strtotime("last Monday"), "\n";
?>

3、
file_get_contents ( string $filename [, bool $use_include_path = false [, resource $context [, int $offset = -1 [, int$maxlen ]]]] ) : string
把文件读入一个字符串。将在参数 offset 所指定的位置开始读取长度为 maxlen 的内容。如果失败,file_get_contents() 将返回 FALSE。
file_get_contents() 函数是用来将文件的内容读入到一个字符串中的首选方法。
如果操作系统支持还会使用内存映射技术来增强性能。如果要打开有特殊字符的 URL (比如说有空格),就需要使用 urlencode() 进行 URL 编码。

设置 file_get_contents() 的超时时间:

//设置超时参数
$opts=array(
        "http"=>array(
                "method"=>"GET",
                "timeout"=>3
                ),
        );
////创建数据流上下文
$context = stream_context_create($opts);
//$url请求的地址,例如:
$result =file_get_contents($url, false, $context);
//伪造header,可用于fopen/file_get_contents
//个别网站伪造referer反而打不开图片,如 https://mmbiz.qlogo.cn/mmbiz_jpg/lpbWiblialBFNfHKQM7hLhCW2f4QwVYHGhxxHa6ZHjS6IcAd0yBG9FpX4qINm2bJ7AhQdyQbibQIQ6juCUcfLiaZMA/0?wx_fmt=jpeg
$opts = array(
	'http' => array(
		'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36\r\n".
			Referer: ".($source_parse_url['scheme'].'://'.$source_parse_url['host'].$source_parse_url['path'])."\r\n",
	),
);
$context = stream_context_create($opts);
$result =file_get_contents($url, false, $context);

更多参考: https://www.cnblogs.com/Renyi-Fan/p/9642301.html

4、iconv ( string $in_charset , string $out_charset , string $str ) 把字符串按要求的字符编码来转换
如果你在 out_charset 后添加了字符串 //TRANSLIT,将启用转写(transliteration)功能。这个意思是,当一个字符不能被目标字符集所表示时,它可以通过一个或多个形似的字符来近似表达。 如果你添加了字符串 //IGNORE,不能以目标字符集表达的字符将被默默丢弃。 否则,会导致一个 E_NOTICE并返回 FALSE。

iconv("utf-8","gbk//TRANSLIT",$str); //utf-8转gbk
iconv("utf-8","gbk//IGNORE",$str);
iconv("utf-8","gbk",$str);
iconv("gbk","utf-8",$str); //gbk转utf-8


CI知识汇总

1、程序执行时间
  在视图中用 echo $this->benchmark->elapsed_time(); 或 {elapsed_time}

2、显示内存消耗
  在视图中用 echo $this->benchmark->memory_usage(); 或 {memory_usage}

3、

CI初始化设置

1、application/config/config.php
a、添加时区设置 date_default_timezone_set('Etc/GMT-8');
b、$config['base_url'] 
c、$config['subclass_prefix'] 扩展类、扩展辅助函数等的前缀

2、application/config/database.php 设置数据库信息
a、配置交换表前缀
$db['default']['dbprefix'] = 'blog_'; 数据库表前缀
$db['default']['swap_pre'] = 'my_'; 交换前缀
这样我们在写sql语句时就用my_这个表前缀,ci会自动把my_换位blog_,这两项可以相同或不设置。

Codeigniter多目录配置网站前台后台的方法

形如以下:
网站前台URL:http://www.aaa.com
网站后台管理URL::http://www.aaa.com/admin

CI源码下载解压后文件结构如下图:

为了达成多目录共享一个CodeIgniter的目标,我们要完成以下步骤:
1、 在application目录下新建子目录admin,至少将上图中红框标注的5个文件夹复制到admin下(其他按需)。这五个文件夹的的作用简单描述一下,详细说明可参考CI官网:
2、设置入口文件。因为根目录下的index.php默认是去找applcation下的controllers下的控制器,为了读取 applcation/admin/controllers下的控制器,我们需要在网站根目录下新建admin文件,并将根目录下的index.php复 制至此,接下来编辑此index.php,找到:
$system_path = "system";   //改为 $system_path = "../system";
$application_folder="application";  //改为 $application_folder = "../application/admin";
另外此目录可能用到的css/js/images 文件夹 也可以放在新建的admin之下。

此时的程序目录结构如下:

这样就可以实现网站前后台的独立访问:
前台地址:http://www.aaa.com/
后台地址:http://www.aaa.com/admin/

CI官方指导方法:http://codeigniter.org.cn/user_guide/general/managing_apps.html

PHP获取客户端真实IP

//获取用户真实IP
function getIp() {
    if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"),
 "unknown"))
        $ip = getenv("HTTP_CLIENT_IP");
    else
        if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        else
            if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
                $ip = getenv("REMOTE_ADDR");
            else
                if (isset ($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && 
strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
                    $ip = $_SERVER['REMOTE_ADDR'];
                else
                    $ip = "unknown";
    return ($ip);
}

但是:除了 $_SERVER['REMOTE_ADDR'] 不能伪造外,其他均可伪造,所以可以简单点,直接使用 REMOTE_ADDR 即可。

另外,IPv4转数值型:sprintf('%u', ip2long($ip)) 这样可以避免负值的出现

PHP截取字符串长度

/* 
 Utf-8、gb2312都支持的汉字截取函数 
 cut_str(字符串, 截取长度, 开始长度, 编码); 
 编码默认为 utf-8 
 开始长度默认为 0 
*/ 
function cutStr($string, $sublen, $start = 0, $code = 'UTF-8'){ 
    if($code == 'UTF-8'){ 
        $pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/"; 
        preg_match_all($pa, $string, $t_string); 
 
        if(count($t_string[0]) - $start > $sublen) return join('', array_slice
($t_string[0], $start, $sublen))."..."; 
        return join('', array_slice($t_string[0], $start, $sublen)); 
    }else{ 
        $start = $start*2; 
        $sublen = $sublen*2; 
        $strlen = strlen($string); 
        $tmpstr = ''; 
 
        for($i=0; $i<$strlen; $i++){ 
            if($i>=$start && $i<($start+$sublen)){ 
                if(ord(substr($string, $i, 1))>129){ 
                    $tmpstr.= substr($string, $i, 2); 
                }else{ 
                    $tmpstr.= substr($string, $i, 1); 
                } 
            } 
            if(ord(substr($string, $i, 1))>129) $i++; 
        } 
        if(strlen($tmpstr)<$strlen ) $tmpstr.= "..."; 
        return $tmpstr; 
    } 

$str = "jQuery插件实现的加载图片和页面效果"; 
echo cutStr($str,16);

2024-11-23 星期六 农历十月二十三