邵珠庆の日记 生命只有一次,你可以用它来做很多伟大的事情–Make the world a little better and easier


136月/10

PHP开源框架

发布在 邵珠庆

国外的开源技术也影响和推动了国内开源程序的发展,上文我介绍的《国外优秀开源PHP建站程序一览》中,很多国外开源程序并不太符合中国人的使用习惯,而 国内有一些厂家或个人也做了一些不错的产品,不少程序是提供源代码下载的,虽然有些在许可协议上和开源许可证有些出入,但其在使用上还是挺符合中国人的使 用习惯,今天我就介绍一些国内的PHP“开源”建站程序。

论坛: Discuz

Discuz非常流行,也是中国地区最多用户使用的论坛程序,论坛搭建非常简单易用,使用风格符合中国人的口味。另一个流行的论坛程序是 PHPWind。

SNS: Ucenter Home

UCenter Home是采用PHP+MySQL构建的社会化网络软件(Social Network Software,简称SNS)。 通过 UCenter Home,建站者可以轻松构建一个以好友关系为核心的交流网络,用户可以使用迷你博客记录;方便快捷地发布日志、上传图片;与其好友们一起分享信息、讨论 话题;了解好友最新动态。

E-Commerce: ECSHOP

ECSHOP是一款开源免费的网上商店系统,用户可以根据自己的商务特征对ECSHOP进行定制,增加自己商城的特色功能。另一个流行的网上商 城系统是shopex。

点评: Modoer

Modoer一款PHP点评系统,可针对多种行业进行点评,可以自由调控点评项目,类型,采用Web 2.0的建站方式,网站会员能让快速上手。

Digg: PBDigg

PBDigg是基于PHP+MYSQL的开源Digg社区资讯系统,融合了社会性标签、主题评论、Rss订阅等多种WEB2.0元素,是一个高 效、快速的网站解决方案。

Wiki: HDWiki

HDWiki是专为中文用户设计和开发的开源、高效的中文百科建站解决方案,免费、易用、功能强大,和UCenter可无缝整合。

RSS: IXNA

IXNA是国内开源PHP新闻聚合程序,支持RSS多核心切换,默认支持lastrss、simplepie、magpierss,支持 RDF、RSS、ATOM,支持智能识别。

CMS: 关于CMS的PHP产品很多,这里主要介绍下面三个。

SupeSite

SupeSite 是一套独立的内容管理系统(CMS),并且拥有对Discuz!论坛信息和UCenter Home个人空间信息聚合的功能,是一个不错的社区门户解决方案。

DedeCMS

DedeCMS是一个比较老的PHP CMS系统,很多早期的用户都是使用这个建立网站的。

KingCMS

KingCMS是一套简单易学,操作简单的开源内容管理系统(CMS),KingCMS分为PHP+MySQL和 ASP+MSSQL/ACCESS两种语言版本的系统。

245月/10

介绍使用php发送邮件类(html格式及附件)

发布在 邵珠庆

以下为邮件类代码:
<?PHP
class Email {
//---设置全局变量
var $mailTo = ""; // 收件人
var $mailCC = ""; // 抄送
var $mailBCC = ""; // 秘密抄送
var $mailFrom = ""; // 发件人
var $mailSubject = ""; // 主题
var $mailText = ""; // 文本格式的信件主体
var $mailHTML = ""; // html格式的信件主体
var $mailAttachments = ""; // 附件
/* 函数setTo($inAddress) :用于处理邮件的地址 参数 $inAddress
为包涵一个或多个字串,email地址变量,使 用逗号来分割多个邮件地址
默认返回值为true
**********************************************************/
function setTo($inAddress){
//--用explode()函数根据”,”对邮件地址进行分割
$addressArray = explode( ",",$inAddress);
//--通过循环对邮件地址的合法性进行检查
for($i=0;$icheckEmail($addressArray[$i])==false) return false; }
//--所有合法的email地址存入数组中
$this->mailTo = implode($addressArray, ",");
return true; }
/**************************************************
函数 setCC($inAddress) 设置抄送人邮件地址
参数 $inAddress 为包涵一个或多个邮件地址的字串,email地址变量,
使用逗号来分割多个邮件地址 默认返回值为true
**************************************************************/
function setCC($inAddress){
//--用explode()函数根据”,”对邮件地址进行分割
$addressArray = explode( ",",$inAddress);
//--通过循环对邮件地址的合法性进行检查
for($i=0;$icheckEmail($addressArray[$i])==false) return false; }
//--所有合法的email地址存入数组中
$this->mailCC = implode($addressArray, ",");
return true; }
/***************************************************
函数setBCC($inAddress) 设置秘密抄送地址 参数 $inAddress 为包涵一个或多
个邮件地址的字 串,email地址变量,使用逗号来分割多个邮件地址 默认返回值为
true
******************************************/
function setBCC($inAddress){
//--用explode()函数根据”,”对邮件地址进行分割
$addressArray = explode( ",",$inAddress);
//--通过循环对邮件地址的合法性进行检查
for($i=0;$i<COUNT($ADDRESSARRAY);$I++)
{ if($this->checkEmail($addressArray[$i])==false)
return false;
}
//--所有合法的email地址存入数组中
$this->mailBCC = implode($addressArray, ",");
return true;
}
/*****************************************************************
函数setFrom($inAddress):设置发件人地址 参数 $inAddress 为包涵邮件
地址的字串默认返回值为 true
***************************************/
function setFrom($inAddress){
if($this->checkEmail($inAddress)){
$this->mailFrom = $inAddress;
return true;
} return false; }
/**********************
函数 setSubject($inSubject) 用于设置邮件主题参数$inSubject为字串,
默认返回的是true
*******************************************/
function setSubject($inSubject){
if(strlen(trim($inSubject)) > 0){
$this->mailSubject = ereg_replace( "n", "",$inSubject);
return true; }
return false; }
/****************************************************
函数setText($inText) 设置文本格式的邮件主体参数 $inText 为文本内容默
认返回值为true
****************************************/
function setText($inText){
if(strlen(trim($inText)) > 0){
$this->mailText = $inText;
return true; }
return false;
}
/**********************************
函数setHTML($inHTML) 设置html格式的邮件主体参数$inHTML为html格式,
默认返回值为true
************************************/
function setHTML($inHTML){
if(strlen(trim($inHTML)) > 0){
$this->mailHTML = $inHTML;
return true; }
return false; }
/**********************
函数 setAttachments($inAttachments) 设置邮件的附件 参数$inAttachments
为一个包 涵目录的字串,也可以包涵多个文件用逗号进行分割 默认返回值为true
*******************************************/
function setAttachments($inAttachments){
if(strlen(trim($inAttachments)) > 0){
$this->mailAttachments = $inAttachments;
return true; }
return false; }
/*********************************
函 数 checkEmail($inAddress) :这个函数我们前面已经调用过了,主要就是
用于检查email地址的合法性
*****************************************/
function checkEmail($inAddress){
return (ereg( "^[^@ ]+@([a-zA-Z0-9-]+.)+([a-zA-Z0-9-]{2}|net|com|gov|mil|org|edu|int)$",$inAddress));
}
/*************************************************
函数 loadTemplate($inFileLocation,$inHash,$inFormat) 读取临时文件并且
替换无用的信息参 数$inFileLocation用于定位文件的目录
$inHash 由于存储临时的值 $inFormat 由于放置邮件主体
***********************************************************/
function loadTemplate($inFileLocation,$inHash,$inFormat){
/* 比如邮件内有如下内容: Dear ~!UserName~,
Your address is ~!UserAddress~ */
//-- 其中”~!”为起始标志”~”为结束标志
$templateDelim = "~";
$templateNameStart = "!";
//--找出这些地方并把他们替换掉
$templateLineOut = ""; //--打开临时文件
if($templateFile = fopen($inFileLocation, "r")){
while(!feof($templateFile)){
$templateLine = fgets($templateFile,1000);
$templateLineArray = explode($templateDelim,$templateLine);
for( $i=0; $i<COUNT($TEMPLATELINEARRAY);$I++){
//--寻找起始位置
if(strcspn($templateLineArray[$i],$templateNameStart)==0){
//--替换相应的值
$hashName = substr($templateLineArray[$i],1);
//-- 替换相应的值
$templateLineArray[$i] = ereg_replace($hashName,(string)$inHash[$hashName],$hashName);
}
}
//--输出字符数组并叠加
$templateLineOut .= implode($templateLineArray, "");
} //--关闭文件fclose($templateFile);
//--设置主体格式(文本或html)
if( strtoupper($inFormat)== "TEXT" )
return($this->setText($templateLineOut));
else if( strtoupper($inFormat)== "HTML" )
return($this->setHTML($templateLineOut));
} return false;
}
/*****************************************
函数 getRandomBoundary($offset) 返回一个随机的边界值
参数 $offset 为整数 – 用于多管道的调用 返回一个md5()编码的字串
****************************************/
function getRandomBoundary($offset = 0){
//--随机数生成
srand(time()+$offset);
//--返回 md5 编码的32位 字符长度的字串
return ( "----".(md5(rand()))); }
/********************************************
函数: getContentType($inFileName)用于判断附件的类型
**********************************************/
function getContentType($inFileName){
//--去除路径
$inFileName = basename($inFileName);
//--去除没有扩展名的文件
if(strrchr($inFileName, ".") == false){
return "application/octet-stream";
}
//--提区扩 展名并进行判断
$extension = strrchr($inFileName, ".");
switch($extension){
case ".gif": return "image/gif";
case ".gz": return "application/x-gzip";
case ".htm": return "text/html";
case ".html": return "text/html";
case ".jpg": return "image/jpeg";
case ".tar": return "application/x-tar";
case ".txt": return "text/plain";
case ".zip": return "application/zip";
default: return "application/octet-stream";
}
return "application/octet-stream";
}
/**********************************************
函数formatTextHeader把文本内容加上text的文件头
*****************************************************/
function formatTextHeader(){ $outTextHeader = "";
$outTextHeader .= "Content-Type: text/plain;
charset=us-asciin";
$outTextHeader .= "Content-Transfer-Encoding: 7bitnn";
$outTextHeader .= $this->mailText. "n";
return $outTextHeader;
} /************************************************
函数 formatHTMLHeader()把邮件主体内容加上html的文件头
******************************************/
function formatHTMLHeader(){
$outHTMLHeader = "";
$outHTMLHeader .= "Content-Type: text/html;
charset=us-asciin";
$outHTMLHeader .= "Content-Transfer-Encoding: 7bitnn";
$outHTMLHeader .= $this->mailHTML. "n";
return $outHTMLHeader;
}
/**********************************
函数 formatAttachmentHeader($inFileLocation) 把邮件中的附件标识出来
********************************/
function formatAttachmentHeader($inFileLocation){
$outAttachmentHeader = "";
//--用上面的函数getContentType($inFileLocation)得出附件类型
$contentType = $this->getContentType($inFileLocation);
//--如果附件是文本型则用标准的7位编码
if(ereg( "text",$contentType)){
$outAttachmentHeader .= "Content-Type: ".$contentType. ";n";
$outAttachmentHeader .= ' name="'.basename($inFileLocation). '"'. "n";
$outAttachmentHeader .= "Content-Transfer-Encoding: 7bitn";
$outAttachmentHeader .= "Content-Disposition: attachment;n";
$outAttachmentHeader .= ' filename="'.basename($inFileLocation). '"'. "nn";
$textFile = fopen($inFileLocation, "r");
while(!feof($textFile)){
$outAttachmentHeader .= fgets($textFile,1000);
}
//--关闭文件 fclose($textFile);
$outAttachmentHeader .= "n";
}
//--非文本格式则用64位进行编码
else{ $outAttachmentHeader .= "Content-Type: ".$contentType. ";n";
$outAttachmentHeader .= ' name="'.basename($inFileLocation). '"'. "n";
$outAttachmentHeader .= "Content-Transfer-Encoding: base64n";
$outAttachmentHeader .= "Content-Disposition: attachment;n";
$outAttachmentHeader .= ' filename="'.basename($inFileLocation). '"'. "nn";
//--调用外部命令uuencode 进行编码
exec( "uuencode -m $inFileLocation nothing_out",$returnArray);
for ($i = 1; $i<(count($returnArray)); $i++){
$outAttachmentHeader .= $returnArray[$i]. "n";
}
} return $outAttachmentHeader;
}
/******************************
函数 send()用于发送邮件,发送成功返回值为true
************************************/
function send(){
//--设置邮件头为空
$mailHeader = "";
//--添加抄送 人
if($this->mailCC != "")
$mailHeader .= "CC: ".$this->mailCC. "n";
//--添加秘密抄送人
if($this->mailBCC != "")
$mailHeader .= "BCC: ".$this->mailBCC. "n";
//--添加发件人
if($this->mailFrom != "")
$mailHeader .= "FROM: ".$this->mailFrom. "n";
//--------------------------- 邮件格式------------------------------
//--文本格式
if($this->mailText != "" && $this->mailHTML == "" && $this->mailAttachments == ""){
return mail($this->mailTo,$this->mailSubject,$this->mailText,$mailHeader);
}
//--html或text格式
else if($this->mailText != "" && $this->mailHTML != "" && $this->mailAttachments == ""){
$bodyBoundary = $this->getRandomBoundary();
$textHeader = $this->formatTextHeader();
$htmlHeader = $this->formatHTMLHeader();
//--设置 MIME-版本
$mailHeader .= "MIME-Version: 1.0n";
$mailHeader .= "Content-Type: multipart/alternative;n";
$mailHeader .= ' boundary="'.$bodyBoundary. '"';
$mailHeader .= "nnn";
//--添加邮件主体 和边界
$mailHeader .= "--".$bodyBoundary. "n";
$mailHeader .= $textHeader;
$mailHeader .= "--".$bodyBoundary. "n";
//--添加html标 签
$mailHeader .= $htmlHeader;
$mailHeader .= "n--".$bodyBoundary. "--";
//--发送邮件
return mail($this->mailTo,$this->mailSubject, "",$mailHeader);
}
//-- 文本加html加附件
else if($this->mailText != "" && $this->mailHTML != "" && $this->mailAttachments != ""){
$attachmentBoundary = $this->getRandomBoundary();
$mailHeader .= "Content-Type: multipart/mixed;n";
$mailHeader .= ' boundary="'.$attachmentBoundary. '"'. "nn";
$mailHeader .= "This is a multi-part message in MIME format.n";
$mailHeader .= "--".$attachmentBoundary. "n";
$bodyBoundary = $this->getRandomBoundary(1);
$textHeader = $this->formatTextHeader();
$htmlHeader = $this->formatHTMLHeader();
$mailHeader .= "MIME-Version: 1.0n";
$mailHeader .= "Content-Type: multipart/alternative;n";
$mailHeader .= ' boundary="'.$bodyBoundary. '"';
$mailHeader .= "nnn";
$mailHeader .= "--".$bodyBoundary. "n";
$mailHeader .= $textHeader;
$mailHeader .= "--".$bodyBoundary. "n";
$mailHeader .= $htmlHeader;
$mailHeader .= "n--".$bodyBoundary. "--";
//--获取附件值
$attachmentArray = explode( ",",$this->mailAttachments);
//--根据附件的个数进行循环
for($i=0;$i<COUNT($ATTACHMENTARRAY);$I++){
//--分割 $mailHeader .= "n--".$attachmentBoundary. "n";
//--附件信息
$mailHeader .= $this->formatAttachmentHeader($attachmentArray[$i]);
}
$mailHeader .= "--".$attachmentBoundary. "--";
return mail($this->mailTo,$this->mailSubject, "",$mailHeader);
}
return false;
}
}
?>

使用方法:
<?
Include “email.class”

$mail->setTo("a@a.com "); //收件人
$mail-> setCC("b@b.com ,[url=mailto:c@c.com]c@c.com[/url]"); //抄送
$mail-> setCC("d@b.com , [url=mailto:e@c.com]e@c.com[/url]"); //秘密抄送
$mail->setFrom(“[url=mailto:f@f.com]f@f.com[/url]”); //发件人
$mail->setSubject(“主题”) ; //主题
$mail->setText(“文本格 式”) ;//发送文本格式也可以是变量
$mail->setHTML(“html格式”) ;//发送html格式也可以是变量
$mail->setAttachments(“c:a.jpg”) ;//添加附件,需表明路径
$mail->send(); //发送邮件
?>

263月/10

PHP中文件读写操作

发布在 邵珠庆

以下为文件读写操作的 基本PHP函数及模式(看不明白就记住他)

关于模式:
'r' - 只读方式打开, 文件指针置于文件头
'r+' - 读写方式打开,文件指针置于文件头
'w' - 只写打开,文件指针置于文件头, 文件被剪切为0字节, 如果文件不存在, 尝试建立文件
'w+' - 读写打开,文件指针置于文件头, 文件大小被剪切为0字节,如果文件不存在, 尝试建立文件
'a' - 只写方式打开,文件指针置于文件尾,如果文件不存在,尝试建立文件
'a+' - 读写打开,文件指针置于文件尾,如果文件不存在, 尝试建立文件
fgets —  从文件指针中读取一行
fgetss — 从文件指针中读取一行并过滤掉 HTML 标记
file — 把整个文件读入一个数组中
fgetcsv — 从文件指针中读入一行并解析 CSV 字段

你一定用过“网络硬盘”吧,利用它可以按自己的需要新建文件夹来分门别类地把自己的一些文件保存起来,有的还可以在线编辑文件。

PHP中提供了一系列的I/O函数,能简捷地实现我们所需要的功能,包括文件系统操作和目录操作(如“复制[copy]”)。下面给大家介绍的是基本的文件读写操作:(1)读文件;(2)写文件;(3)追加到文件。

TEXT 代码:

  1. 作者: Mukul
  2. 翻译: 无伤 <goghs@mail.com>

读文件:

  1. <?php
  2. $file_name="data.dat";
  3. // 要读取的文件的绝对路径: homedata.dat
  4. $file_pointer=fopen($file_name,"r");
  5. // 打开文件,"r" 是一种模式,或者说我们要进行的操作方法,详见本文后面的介绍
  6. $file_read=fread($file_pointer,filesize($file_name));
  7. // 通过文件指针读取文件内容
  8. fclose($file_pointer);
  9. // 关闭文件
  10. print"读取到的文件内容是: $file_read";
  11. // 显示文件内容
  12. ?>

写文件:

  1. <?php
  2. $file_name="data.dat";
  3. // 绝对路径: homedata.dat
  4. $file_pointer=fopen($file_name,"w");
  5. // "w"是一种模式,详见后面
  6. fwrite($file_pointer,"what you wanna write");
  7. // 先把文件剪切为0字节大小, 然后写入
  8. fclose($file_pointer);
  9. // 结束
  10. print"数据成功写入文件";
  11. ?>

追加到文件后面:

  1. <?php
  2. $file_name="data.dat";
  3. // 绝对路径: homedata.dat
  4. $file_pointer=fopen($file_name,"a");
  5. // "w"模式
  6. fwrite($file_pointer,"what you wanna append");
  7. // 不把文件剪切成0字节, 把数据追加到文件最后
  8. fclose($file_pointer);
  9. // 结束
  10. print"数据成功追加到文件";
  11. ?>

以上只是简单介绍,下面我们要讨论一些更深层的。

有时候会发生多人写入的情况(最常见是在流量较大的网站),会产生无用的数据写入文件, 例如:

info.file文件内容如下 ->

|1|Mukul|15|Male|India (n)
|2|Linus|31|Male|Finland (n)

现在两个人同时注册,引起文件破坏->

info.file ->

|1|Mukul|15|Male|India
|2|Linus|31|Male|Finland
|3|Rob|27|Male|USA|
Bill|29|Male|USA

上例中当PHP写入Rob的信息到文件的时候,Bill正好也开始写入,这时候正好需要写入Rob纪录的'n',引起文件破坏。

我们当然不希望发生这样的情况, 所以让我们看看文件锁定:

复制内容到剪贴板

PHP 代码:
  1. <?php
  2. $file_name="data.dat";
  3. $file_pointer=fopen($file_name,"r");
  4. $lock=flock($file_pointer, LOCK_SH);
  5. // 我使用4.0.2,所以用LOCK_SH,你可能需要直接写成 1.
  6. if($lock){
  7. $file_read=fread($file_pointer,filesize($file_name));
  8. $lock=flock($file_pointer, LOCK_UN);
  9. // 如果版本小于PHP4.0.2, 用 3 代替 LOCK_UN
  10. }
  11. fclose($file_pointer);
  12. print"文件内容为 $file_read";
  13. ?>

上例中,如果两个文件read.php和read2.php都要存取该文件,那么它们都可以读取,但是当一个程序需要写入的时候,它必须等待,直到读操作完成,文件所释放。

  1. <?php
  2. $file_name="data.dat";
  3. $file_pointer=fopen($file_name,"w");
  4. $lock=flock($file_pointer, LOCK_EX);
  5. // 如果版本低于PHP4.0.2, 用 2 代替 LOCK_EX
  6. if($lock){
  7. fwrite($file_pointer,"what u wanna write");
  8. flock($file_pointer, LOCK_UN);
  9. // 如果版本低于PHP4.0.2, 用 3 代替 LOCK_UN
  10. }
  11. fclose($file_pointer);
  12. print"数据成功写入文件";
  13. ?>

虽然"w"模式用来覆盖文件, 单我觉得不适用。

  1. <?php
  2. $file_name="data.dat";
  3. $file_pointer=fopen($file_name,"a");
  4. $lock=flock($file_pointer, LOCK_EX);
  5. // 如果版本低于PHP4.0.2, 用 2 代替 LOCK_EX
  6. if($lock){
  7. fseek($file_pointer,0, SEEK_END);
  8. // 如果版本小于PHP4.0RC1, 使用 fseek($file_pointer, filsize($file_name));
  9. fwrite($file_pointer,"what u wanna write");
  10. flock($file_pointer, LOCK_UN);
  11. // 如果版本低于PHP4.0.2, 用 3 代替 LOCK_UN
  12. }
  13. fclose($file_pointer);
  14. ?>

Hmmm..., 对于追加数据与其他操作有点不同,就是FSEEK! 确认文件指针在文件尾部总是一个好习惯。

如果是在Windows系统下, 上面的文件中文件名前面需要加上''.

213月/10

PHP抓取网页和分析

发布在 邵珠庆

<?PHP

//$url = "http://news.google.cn/news/section?pz=1&cf=all&ned=ccn&topic=i&ict=ln";
$url = "http://news.google.cn/news/section?pz=1&cf=all&ned=ccn&topic=t&ict=ln";
$lines_array = file($url);
$lines_string = implode('', $lines_array);

eregi('<head>(.*)</head>', $lines_string, $head1);
eregi('<table>(.*)</table>', $lines_string, $head2);
eregi('<div>(.*)</div>', $head2[0], $head3);
echo $head1[0];
echo $head3[0];

?>

 

译者:limodou
抓取和分析一个文件是非常简单的事。这个教程将通过一个例子带领你一步一步地去实现它。让我们开
始吧!

首先,我首必须决定我们将抓取的URL地址。可以通过在脚本中设定或通过$QUERY_STRING传递。为了简
单起见,让我们将变量直接设在脚本中。

<? $url = 'http://www.php.net'; ?>

第二步,我们抓取指定文件,并且通过file()函数将它存在一个数组里。

<? $url = 'http://www.php.net'; $lines_array = file($url); ?>

好了,现在在数组里已经有了文件了。但是,我们想分析的文本可能不全在一行里面。为了解决这个文
件,我们可以简单地将数组$lines_array转化成一个字符串。我们可以使用implode(x,y)函数来实现它。如
果在后面你想用explode(将字符串变量数组),将x设成"|"或"!"或其它类似的分隔符可能会更好。但是出于
我们的目的,最好将x设成空格。y是另一个必要的参数,因为它是你想用implode()处理的数组。

<? $url = 'http://www.php.net'; $lines_array = file($url); $lines_string = implode('', $lines_array); ?>

现在,抓取工作就做完了,下面该进行分析了。出于这个例子的目的,我们想得到在<head>到</head>
之间的所有东西。为了分析出字符串,我们还需要叫做正规表达式的东西。

<? $url = 'http://www.php.net'; $lines_array = file($url); $lines_string = implode('', $lines_array); eregi("<head>(.*)</head>", $lines_string, $head); ?>

让我们看一下代码。正如你所见,eregi()函数按下面的格式执行:

eregi("<head>(.*)</head>", $lines_string, $head);

"(.*)"表示所有东西,可以解释为,"分析在<head>和</head>间的所以东西"。$lines_string是我们正
在分析的字符串,$head是分析后的结果存放的数组。
最后,我们可以输数据。因为仅在<head>和</head>间存在一个实例,我们可以安全的假设数组中仅存
在着一个元素,而且就是我们想要的。让我们把它打印出来吧。

<? $url = 'http://www.php.net'; $lines_array = file($url); $lines_string = implode('', $lines_array); eregi("<head>(.*)</head>", $lines_string, $head); echo $head[0]; ?>

这就是全部的代码了。

<?php

//获取所有内容url保存到文件
function  get_index ( $save_file ,  $prefix = "index_" ){
$count  =  68 ;
$i  =  1 ;
if ( file_exists ( $save_file )) @ unlink ( $save_file );
$fp  =  fopen ( $save_file ,  "a+" ) or die( "Open " .  $save_file  . " failed" );
while( $i < $count ){
$url  =  $prefix  .  $i  . ".htm" ;
echo  "Get " .  $url  . "..." ;
$url_str  =  get_content_url ( get_url ( $url ));
echo  " OK/n" ;
fwrite ( $fp ,  $url_str );
++ $i ;
}
fclose ( $fp );
}

//获取目标多媒体对象
function  get_object ( $url_file ,  $save_file ,  $split = "|--:**:--|" ){
if (! file_exists ( $url_file )) die( $url_file  . " not exist" );
$file_arr  =  file ( $url_file );
if (! is_array ( $file_arr ) || empty( $file_arr )) die( $url_file  . " not content" );
$url_arr  =  array_unique ( $file_arr );
if ( file_exists ( $save_file )) @ unlink ( $save_file );
$fp  =  fopen ( $save_file ,  "a+" ) or die( "Open save file " .  $save_file  . " failed" );
foreach( $url_arr  as  $url ){
if (empty( $url )) continue;
echo  "Get " .  $url  . "..." ;
$html_str  =  get_url ( $url );
echo  $html_str ;
echo  $url ;
exit;
$obj_str  =  get_content_object ( $html_str );
echo  " OK/n" ;
fwrite ( $fp ,  $obj_str );
}
fclose ( $fp );
}

//遍历目录获取文件内容
function  get_dir ( $save_file ,  $dir ){
$dp  =  opendir ( $dir );
if ( file_exists ( $save_file )) @ unlink ( $save_file );
$fp  =  fopen ( $save_file ,  "a+" ) or die( "Open save file " .  $save_file  . " failed" );
while(( $file  =  readdir ( $dp )) !=  false ){
if ( $file != "."  &&  $file != ".." ){
echo  "Read file " .  $file  . "..." ;
$file_content  =  file_get_contents ( $dir  .  $file );
$obj_str  =  get_content_object ( $file_content );
echo  " OK/n" ;
fwrite ( $fp ,  $obj_str );
}
}
fclose ( $fp );
}

//获取指定url内容
function  get_url ( $url ){
$reg  =  '/^http:////[^//].+$/' ;
if (! preg_match ( $reg ,  $url )) die( $url  . " invalid" );
$fp  =  fopen ( $url ,  "r" ) or die( "Open url: " .  $url  . " failed." );
while( $fc  =  fread ( $fp ,  8192 )){
$content  .=  $fc ;
}
fclose ( $fp );
if (empty( $content )){
die( "Get url: " .  $url  . " content failed." );
}
return  $content ;
}

//使用socket获取指定网页
function  get_content_by_socket ( $url ,  $host ){
$fp  =  fsockopen ( $host ,  80 ) or die( "Open " .  $url  . " failed" );
$header  =  "GET /" . $url  . " HTTP/1.1/r/n" ;
$header  .=  "Accept: */*/r/n" ;
$header  .=  "Accept-Language: zh-cn/r/n" ;
$header  .=  "Accept-Encoding: gzip, deflate/r/n" ;
$header  .=  "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; InfoPath.1; .NET CLR 2.0.50727)/r/n";
$header  .=  "Host: " .  $host  . "/r/n" ;
$header  .=  "Connection: Keep-Alive/r/n" ;
//$header .= "Cookie: cnzz02=2; rtime=1; ltime=1148456424859; cnzz_eid=56601755-/r/n/r/n";
$header  .=  "Connection: Close/r/n/r/n" ;

fwrite ( $fp ,  $header );
while (! feof ( $fp )) {
$contents  .=  fgets ( $fp ,  8192 );
}
fclose ( $fp );
return  $contents ;
}

//获取指定内容里的url
function  get_content_url ( $host_url ,  $file_contents ){

//$reg = '/^(#|JavaScript.*?|ftp:////.+|http:////.+|.*?href.*?|play.*?|index.*?|.*?asp)+$/i';
//$reg = '/^(down.*?/.html|/d+_/d+/.htm.*?)$/i';
$rex  =  "/([hH][rR][eE][Ff])/s*=/s*['/"]*([^>'/"/s]+)[/"'>]*/s*/i" ;
$reg  =  '/^(down.*?/.html)$/i' ;
preg_match_all  ( $rex ,  $file_contents ,  $r );
$result  =  "" ;  //array();
foreach( $r  as  $c ){
if ( is_array ( $c )){
foreach( $c  as  $d ){
if ( preg_match ( $reg ,  $d )){  $result  .=  $host_url  .  $d . "/n" ; }
}
}
}
return  $result ;
}

//获取指定内容中的多媒体文件
function  get_content_object ( $str ,  $split = "|--:**:--|" ){
$regx  =  "/href/s*=/s*['/"]*([^>'/"/s]+)[/"'>]*/s*(.*?<//b>)/i" ;
preg_match_all ( $regx ,  $str ,  $result );

if ( count ( $result ) ==  3 ){
$result [ 2 ] =  str_replace ( "多媒体: " ,  "" ,  $result [ 2 ]);
$result [ 2 ] =  str_replace ( " " ,  "" ,  $result [ 2 ]);
$result  =  $result [ 1 ][ 0 ] .  $split  . $result [ 2 ][ 0 ] .  "/n" ;
}
return  $result ;
}

?>

43月/10

PHP小偷程序原理、实例及改进

发布在 邵珠庆

优点:通过PHP小偷,我们可以借用别人网站上的信息而不用自己辛苦地去采集。
缺点:需要把整页的HTML代码读取到本地,然后通过匹配获取到想要的信息再进行显示,这样大大影响网页的加载速度。
改进:通过AJAX异步读取HTML代码,后台进行匹配获取到想要的信息,再显示到前台页面。
预备知识:PHP、AJAX、正则表达式。
关键字:file_get_contents()、fopen()、fwrite()、eregi(),前三个关键字都是关于PHP文件处理的函数,eregi()是关于正则表达式的函数。

一、PHP小偷原理的实现:

1、file_get_contents()、fopen()、fwrite()的应用

咱们用华夏黑客牛刀小试吧,把主页的全部信息获取过来。

建立一个PHP文件:
<?php
$url='http://www.77169.com';
//file_get_contents()函数获取网页的html文档
$file=file_get_contents($url);
//建立一个新文件ImitationIndex.htm
$newfile=fopen('ImitationIndex.htm','w');
//把内容读取进去
fwrite($newfile,$file);
//关闭打开的文件
fclose($newfile);
?>

ImitationIndex.htm获取主页全部的HTML(保存好,以备下次使用)。

2、eregi()函数的应用

通过eregi()获取里的内容:
<?php
$url='http://www.77169.com';
//file_get_contents()函数获取网页的html文档
$file=file_get_contents($url);
//通过eregi()匹配获取想要的信息
eregi('<title>(.*)</title>',$file,$rg);
//建立一个新文件
$newfile=fopen('title.htm','w');
//把内容读取进去
fwrite($newfile,$rg[1]);
?>

打开title.htm可以看到已经获取了<title></title>之间的内容

从上面的两个例子,已经知道PHP小偷的实现原理,从中也知道它的不足之处,但通过AJAX可以完善它,使它可以用于实践项目中。

二、PHP小偷技术的实用和改进:

目的:获取华夏黑客的最新资讯,并实时更新查看示例。

实际中可能只用到三个页面:showNews.php、Update.php、HackNews.htm,但为了能看到实时更新的效果,这里用到了模拟主页的页面ImitationIndex.htm。

showNews.php:
<style type="text/css">
body{background:#c60;}
a{color:#444;font:12px Courier New;padding:8px;}
a:hover{color:#f00}
#hei_content{width:400px;background:#ccc;border:2px solid #000;border-bottom:5px solid #000;}
</style>
<?php
echo('<div id="hei_content">');
include('HackNews.htm');
echo('</div>');
?>
<script type="text/javascript">
window.onload=UpdateNews;
function GetXmlHttp()
{
var xmlhttp;
try
{
//IE7.0 ect
xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch(a)
{
try
{
//ie6.0 ect
xmlhttp=new ActiveXObject("Mscrosoft.XMLHTTP");
}
catch(b)
{
//非IE
xmlhttp=new XMLHttpRequest();
}
}
return xmlhttp;
}
function StateChange()
{
if(xmlhttp.readyState==4&&xmlhttp.status==200)
{
document.getElementById("hei_content").innerHTML=xmlhttp.responseText;
}
}
function UpdateNews()
{
xmlhttp=GetXmlHttp();
xmlhttp.onreadystatechange=StateChange;
var url='Update.php';
url=url+"?sid="+Math.random();
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
</script>

HackNews.htm是已经缓存的文件,这样不用加载主页上的整个HTML再显示,这个工作留给AJAX:
document.getElementById("hei_content").innerHTML=xmlhttp.responseText

xmlhttp.responseText就是加载更新后的内容。

Update.php:
<?php
$url='ImitationIndex.htm';
//file_get_contents()函数获取网页的html文档
$file=file_get_contents($url);
//$regx为正则表达式的内容,用于匹配获取想要的信息
$regx='<td background=http://hack.77169.com/UploadFiles_8057/200902/20090220100422648.gif colSpan=3 height=100>
(.*)</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colSpan=3><IMG height=8 src=/"http://hack.77169.com/UploadFiles_8057/200902/20090220100422568.gif';
//eregi()获取匹配到的内容,赋值给数组变量$rg;
eregi($regx,$file,$rg);
//建立一个新文件HackNews.htm
$newfile=fopen('HackNews.htm','w');
//把内容读取进去
fwrite($newfile,$rg[1]);
fclose($newfile);
//用iconv编码转换后,输出匹配的HTML内容
$rg[1]=iconv('gb2312','utf-8',$rg[1]);
echo($rg[1]);
?>
Update.php是异步更新的后台页面,“$newfile=fopen('HackNews.htm','w');”和“fwrite($newfile,$rg[1]);”把更新的内容重新保存在HackNews.htm中,下次在index.php中include时就直接调用这个页面,“$url='ImitationIndex.htm'”在实际应用中应该是“$url='http://www.77169.com'”,但为了便于调试,建立一个ImitationIndex.htm模拟页面,如果对ImitationIndex.htm页面中最新资讯中的内容改改,就可以看到实时更新效果。

总结:通过AJAX改进的PHP小偷技术,在采集多个网站的大量信息下,页面的加载速度并不会受多大影响。