简单的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 新增)。 |
- call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数
- call_user_func — 把第一个参数作为回调函数调用
- create_function — Create an anonymous (lambda-style) function
- forward_static_call_array — Call a static method and pass the arguments as array
- forward_static_call — Call a static method
- func_get_arg — 返回参数列表的某一项
- func_get_args — 返回一个包含函数参数列表的数组
- func_num_args — Returns the number of arguments passed to the function
- function_exists — 如果给定的函数已经被定义就返回 true
- get_defined_functions — 返回所有已定义函数的数组
- register_shutdown_function — 注册一个会在php中止时执行的函数
- register_tick_function — 注册一个函数以便在每个 tick 上执行
- unregister_tick_function — De-register a function for execution on each tick
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);