最近手头上有个项目是要基于phpcms开发的,文章数据已经通过抓取的方式获取到了,需要导入到phpcms的数据库里面去,一开始按正常方式在phpcms后台发表了一篇文章分析了下,发现每发表一篇文章所影响的数据库表及字段还挺多,而且粗略了看了下其源代码,针对文章发布的逻辑处理也不少,如果按照它那个逻辑重新写一份导入代码我估计是相当麻烦,而我恰恰是个最怕麻烦的人了,所以此方式果断放弃。
那么要想利用phpcms现有的代码去完成这个导入任务的话就只有两种方式了,一是专门写一份导入程序,类似于当作phpcms的扩展来用,文章入库时调用phpcms本身封装好的类及对应方法就行了。二是直接利用phpcms后台的文章发布方式,通过模拟post数据将文章提交给文章发布入口文件。第一种方法要求对phpcms比较熟悉,而我是刚接触这东西,所以我还是选择了第二种,虽然这第二种看起来还有些笨^_^
我把将文章数据利用模拟post方式提交给发布入口(/index.php?m=content&c=content&a=add)的过程写成了一个函数,当然这里也还用到了phpcms函数库里面本身的几个函数,如下:
* 字符串加密、解密函数 * * * @param string $txt 字符串 * @param string $operation ENCODE为加密,DECODE为解密,可选参数,默认为ENCODE, * @param string $key 密钥:数字、字母、下划线 * @param string $expiry 过期时间 * @return string */ function sys_auth($string, $operation = 'ENCODE', $key = '', $expiry = 0) { $key_length = 4; $key = md5($key != '' ? $key : 'x4lFCp2uWCwmsa0GvgXW'); $fixedkey = md5($key); $egiskeys = md5(substr($fixedkey, 16, 16)); $runtokey = $key_length ? ($operation == 'ENCODE' ? substr(md5(microtime(true)), -$key_length) : substr($string, 0, $key_length)) : ''; $keys = md5(substr($runtokey, 0, 16) . substr($fixedkey, 0, 16) . substr($runtokey, 16) . substr($fixedkey, 16)); $string = $operation == 'ENCODE' ? sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$egiskeys), 0, 16) . $string : base64_decode(substr($string, $key_length)); $i = 0; $result = ''; $string_length = strlen($string); for ($i = 0; $i < $string_length; $i++){ $result .= chr(ord($string{$i}) ^ ord($keys{$i % 32})); } if($operation == 'ENCODE') { return $runtokey . str_replace('=', '', base64_encode($result)); } else { if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$egiskeys), 0, 16)) { return substr($result, 26); } else { return ''; } } } /* 参数说明: $host:目标主机名; $port:目标主机端口号; $path:目标文件路径; $data:需要发送的数据,结构为数组形式,数组键值代表参数名,数组值代表参数值; $siteid:站点id; By Ken http://ken.01h.net/1178.html */ function PostData($host, $port, $path, $data=array('id'=>1), $siteid=1){ $content = ''; if(is_array($data) && count($data)>0){ $auto = 0; foreach($data as $key=>$value){ //注意:数据必须使用rawurlencode进行编码 if($auto) $content .= '&'.rawurlencode($key).'='.rawurlencode($value); else $content .= rawurlencode($key).'='.rawurlencode($value); $auto++; } }else{ return 'param error!'; } //return $content; $data = "POST ".$path." HTTP/1.1\r\n"; $data .= "Host: ".$host."\r\n"; $data .= "Cookie: PHPSESSID=f070d8e98fc5a7a74d969f3f4bf9d1a7; XRHpq_admin_username=e403AQJWUwADCAlTAl0OAAZSXAlRV1VUAQsCW1IRDRVUVEQ; XRHpq_userid=e403AQJWUwADCAlTAgBTUlcBDQQDBVIGDVEBWQBQ; XRHpq_siteid=".sys_auth($siteid, 'ENCODE')."; path=/;\r\n"; $data .= "Content-Type: application/x-www-form-urlencoded\r\n"; $data .= "Connection: Close\r\n"; $data .= "Content-Length: ".strlen($content)."\r\n\r\n"; //必须指定数据长度 www.it165.net $data .= $content."\r\n"; //数据前面必须是 www.it165.net \r\n\r\n $sock = fsockopen($host, $port, $errno, $errstr, 30); if(!$sock){ return "$errstr ($errno)<br />\r\n"; } fwrite($sock, $data); while(!feof($sock)){ $result .= fgets($sock, 1024); } fclose($sock); return $result; } /* 正式写入phpcms库并返回处理结果 By Ken http://ken.01h.net/1178.html */ function articleInPc($siteid, $catid, $title, $keywords, $content){ $arr = array('info[thumb]'=>'', 'info[relation]'=>'', 'info[inputtime]'=>date("Y-m-d H:i:s"), 'info[template]'=>'', 'info[allow_comment]'=>1, 'info[readpoint]'=>'', 'info[paytype]'=>0, 'info[catid]'=>$catid, 'info[title]'=>$title, 'info[keywords]'=>$keywords, 'info[description]'=>'', 'info[content]'=>$content, 'info[paginationtype]'=>0, 'info[maxcharperpage]'=>10000, 'info[posids][0]'=>-1, 'info[groupids_view]'=>1, 'info[islink]'=>0, 'status'=>99, 'style_color'=>'', 'style_font_weight'=>'', 'page_title_value'=>'', 'add_introduce'=>1, 'introcude_length'=>200, 'auto_thumb'=>1, 'auto_thumb_no'=>1, 'dosubmit'=>'保存后自动关闭', 'pc_hash'=>'MW9EiM'); $backstr = PostData('phpcms.01h.net', 80, '/index.php?m=content&c=content&a=add', $arr, $siteid); if(@strpos($backstr,'HTTP/1.1 200 OK')!==false && @strpos($backstr,'数据添加成功!')!==false){ return 'ok'; }else{ return $backstr; } } //示例 $sign = articleInPc(1, 2, '文章标题', '文章关键词', '文章内容'); if($sign=='ok'){ echo '文章导入成功'; }else{ echo $sign; }
利用此种方式导入文章时需要将后台内容发布类文件中的权限检测取消掉,具体位置在phpcms\modules\content\content.php文件中第17行,将parent::__construct();注释掉即可,要不你还得多写一份模拟登录后台的代码,那又得麻烦了。