将HTML页面转行成word并且保存

这里用使用到一个PHP的工具叫:PHPWord。

生成Word的原理是,将堆规定好了的xml压缩成一个zip包,并且把后缀名改成doc或者docx即可。

所以使用PHPWord,需要你的PHP环境安装zip.dll压缩扩展,我写了一个demo.

Deom演示:http://www.dengwz.com/phpword/index.html 往里面贴一个URL就可以了

功能说明:

20150507 — HTML中的<p>标签和<ol>列表标签的获取

20150508 — 新增获取文章中的图片功能

20150509 — 新增行间距,并且过滤一下错误图片

20150514 — 新增表格处理,并且将代码改成面向对象

20150519 — 新增GD库处理网络图片


&amp;nbsp;require_once 'PHPWord.php';
 require_once 'SimpleHtmlDom.class.php';

 class Word{

 private $url;
 private $LinetextArr = array();
 public $CurrentDir;
 public $error = array(); //错误数组
 public $filename = null;
 public $Allowtag = "p,ol,ul,table";

 /**数据统计**/
 public $DownImg = 0;
 public $expendTime = 0;
 public $HttpRequestTime = 0;
 public $ContentLen = 0;
 public $HttpRequestArr = array();
 public $expendmemory = 0;

 public function __construct($url)
 {
 $startTime = $this-&amp;gt;_Time();
 $startMemory = $this-&amp;gt;_memory();

 $this-&amp;gt;url = $url;

 $UrlArr = parse_url($this-&amp;gt;url);

 $this-&amp;gt;host = $UrlArr["scheme"]."://".$UrlArr['host'];

 $this-&amp;gt;CurrentDir = getcwd();

 $this-&amp;gt;LinetextArr["table"] = array();

 $html = new simple_html_dom($this-&amp;gt;url);

 $this-&amp;gt;HttpRequestArr[] = $this-&amp;gt;url;
 $this-&amp;gt;HttpRequestTime++;

 foreach($html-&amp;gt;find($this-&amp;gt;Allowtag) as $key=&amp;gt;$value)
 {
 if($value-&amp;gt;tag == "table")
 {
 $this-&amp;gt;ParseTable($value,0,$this-&amp;gt;LinetextArr["table"]);
 }
 else
 {
 $this-&amp;gt;AnalysisHtmlDom($value);
 }

 $this-&amp;gt;error[] = error_get_last();

 }

 $endTime = $this-&amp;gt;_Time();
 $endMemory = $this-&amp;gt;_memory();

 $this-&amp;gt;expendTime = round(($endTime-$startTime),2); //微秒
 $this-&amp;gt;expendmemory = round(($endMemory-$startMemory)/1000,2); //bytes

 $this-&amp;gt;CreateWordDom();

 }

 private function _Time()
 {
 return array_sum(explode(" ", microtime()));
 }

 private function _memory()
 {
 return memory_get_usage();
 }

 /**
 * 解析HTML中的Table,这里考虑到多层table嵌套的情况
 * @param $value HTMLDOM
 * @param $i 遍历层级
 * **/
 private function ParseTable($value,$i,$Arr)
 {
 if($value-&amp;gt;firstChild() &amp;amp;&amp;amp; in_array($value-&amp;gt;firstChild()-&amp;gt;tag,array("table","tbody","thead","tfoot","tr")))
 {
 foreach($value-&amp;gt;children as $k=&amp;gt;$v)
 {
 $this-&amp;gt;ParseTable($v,$i++,$Arr);
 }
 }
 else
 {
 foreach($value-&amp;gt;children as $k=&amp;gt;$v)
 {

 if($v-&amp;gt;firstChild() &amp;amp;&amp;amp; $v-&amp;gt;firstChild()-&amp;gt;tag != "table")
 {
 $Arr[$i][] = array("tag"=&amp;gt;$v-&amp;gt;tag,"text"=&amp;gt;trim($v-&amp;gt;plaintext));
 }

 if(!$v-&amp;gt;firstChild())
 {
 $Arr[$i][] = array("tag"=&amp;gt;$v-&amp;gt;tag,"text"=&amp;gt;trim($v-&amp;gt;plaintext));
 }
 }

 }
 }

 /**
 * 解析HTML里面的表情
 * @param $value HTMLDOM
 * **/
 private function AnalysisHtmlDom($value)
 {
 $tmp = array();
 if($value-&amp;gt;has_child())
 {
 foreach($value-&amp;gt;children as $k=&amp;gt;$v)
 {
 $this-&amp;gt;AnalysisHtmlDom($v);
 }
 }
 else
 {
 if($value-&amp;gt;tag == "a")
 {
 $tmp = array("tag"=&amp;gt;$value-&amp;gt;tag,"href"=&amp;gt;$value-&amp;gt;href,"text"=&amp;gt;$value-&amp;gt;innertext);
 }
 else if($value-&amp;gt;tag == "img")
 {
 $src = $this-&amp;gt;unescape($value-&amp;gt;src);
 $UrlArr = parse_url($src);

 if(!isset($UrlArr['host']))
 {
 $src = $this-&amp;gt;host.$value-&amp;gt;src;
 $UrlArr = parse_url($src);
 }

 $src = $this-&amp;gt;getImageFromNet($src,$UrlArr); //表示有网络图片,需要下载

 if($src)
 {
&amp;nbsp;  $imgsArr = $this-&amp;gt;GD($src);
   $tmp = array("tag"=&amp;gt;$value-&amp;gt;tag,"src"=&amp;gt;$src,"text"=&amp;gt;$value-&amp;gt;alt,"width"=&amp;gt;$imgsArr['width'],"height"=&amp;gt;$imgsArr['height']); }
 }
 else
 {
 $tmp = array("tag"=&amp;gt;$value-&amp;gt;tag,"text"=&amp;gt;strip_tags($value-&amp;gt;innertext));
 } 

 $this-&amp;gt;LinetextArr[] = $tmp;
 }

 }

 /**
 * 根据GD库来获取图片的如果太多,进行比例压缩
 * **/
 private function GD($src)
 {
 list($width, $height, $type, $attr) = getimagesize($src);

 if($width &amp;gt; 800 || $height &amp;gt; 800 )
 {
 $width = $width/2;
 $height = $height/2;
 }

 return array("width"=&amp;gt;$width,"height"=&amp;gt;$height);
 }

 /**
 * 将Uincode编码转移回原来的字符
 * **/
 public function unescape($str) {

 $str = rawurldecode($str);

 preg_match_all("/(?:%u.{4})|&amp;amp;#x.{4};|&amp;amp;#\d+;|.+/U",$str,$r);

 $ar = $r[0];

 foreach($ar as $k=&amp;gt;$v) {

 if(substr($v,0,2) == "%u"){

 $ar[$k] = iconv("UCS-2BE","UTF-8",pack("H4",substr($v,-4)));
 }

 elseif(substr($v,0,3) == "&amp;amp;#x"){

 $ar[$k] = iconv("UCS-2BE","UTF-8",pack("H4",substr($v,3,-1)));

 }
 elseif(substr($v,0,2) == "&amp;amp;#"){

 $ar[$k] = iconv("UCS-2BE","UTF-8",pack("n",substr($v,2,-1)));
 }
 }

 return join("",$ar);

}

 /**
 * 图片下载
 * @param $Src 目标资源
 * @param $UrlArr 目标URL对应的数组
 * **/
 private function getImageFromNet($Src,$UrlArr)
 {
 $file = basename($UrlArr['path']);

 $ext = explode('.',$file);

 $this-&amp;gt;ImgDir = $this-&amp;gt;CurrentDir."/".$UrlArr['host'];

 $_supportedImageTypes = array('jpg', 'jpeg', 'gif', 'png', 'bmp', 'tif', 'tiff');

 if(isset($ext['1']) &amp;amp;&amp;amp; in_array($ext['1'],$_supportedImageTypes))
 {
 $file = file_get_contents($Src);

 $this-&amp;gt;HttpRequestArr[] = $Src;
 $this-&amp;gt;HttpRequestTime++;

 $this-&amp;gt;_mkdir(); //创建目录,或者收集错误

 $imgName = md5($UrlArr['path']).".".$ext['1'];

 file_put_contents($this-&amp;gt;ImgDir."/".$imgName,$file);

 $this-&amp;gt;DownImg++;

 return $UrlArr['host']."/".$imgName;
 }

 return false;
 }

 /**
 * 创建目录
 * **/
 private function _mkdir()
 {

 if(!is_dir($this-&amp;gt;ImgDir))
 {
 if(!mkdir($this-&amp;gt;ImgDir,"7777"))
 {
 $this-&amp;gt;error[] = error_get_last();
 }
 }
 }

 /**
 * 构造WordDom
 * **/
 private function CreateWordDom()
 {

 $PHPWord = new PHPWord();

 $PHPWord-&amp;gt;setDefaultFontName('宋体');
 $PHPWord-&amp;gt;setDefaultFontSize("11");

 $styleTable = array('borderSize'=&amp;gt;6, 'borderColor'=&amp;gt;'006699', 'cellMargin'=&amp;gt;120);
 // New portrait section
 $section = $PHPWord-&amp;gt;createSection();

 $section-&amp;gt;addText($this-&amp;gt;Details(),array(),array('spacing'=&amp;gt;120));

 //数据进行处理
 foreach($this-&amp;gt;LinetextArr as $key=&amp;gt;$lineArr)
 {
 if(isset($lineArr['tag']))
 {
 if($lineArr['tag'] == "li")
 {
 $section-&amp;gt;addListItem($lineArr['text'],0,"","",array('spacing'=&amp;gt;120));
 }
 else if($lineArr['tag'] == "img")
 {
 $section-&amp;gt;addImage($lineArr['src'],array('width'=&amp;gt;$lineArr['width'], 'height'=&amp;gt;$lineArr['height'], 'align'=&amp;gt;'center'));
 }
 else if($lineArr['tag'] == "p")
 {
 $section-&amp;gt;addText($lineArr['text'],array(),array('spacing'=&amp;gt;120));
 }
 }
 else if($key == "table")
 {
 $PHPWord-&amp;gt;addTableStyle('myOwnTableStyle', $styleTable);
 $table = $section-&amp;gt;addTable("myOwnTableStyle");
 foreach($lineArr as $key=&amp;gt;$tr)
 {
 $table-&amp;gt;addRow();
 foreach($tr as $ky=&amp;gt;$td)
 {
 $table-&amp;gt;addCell(2000)-&amp;gt;addText($td['text']);
 }
 }
 }
 }

 $this-&amp;gt;downFile($PHPWord);
 }

 public function Details()
 {
 $msg = "一共请求:{$this-&amp;gt;HttpRequestTime}次,共下载的图片有{$this-&amp;gt;DownImg}张,并且下载完成大约使用时间:{$this-&amp;gt;expendTime}秒,整个程序执行大约消耗内存是:{$this-&amp;gt;expendmemory}KB,";

 return $msg;
 }

 public function downFile($PHPWord)
 {
 if(empty($this-&amp;gt;filename))
 {
 $UrlArr = parse_url($this-&amp;gt;url);
 $this-&amp;gt;filename = $UrlArr['host'].".docx";
 }

 // Save File
 $objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
 $objWriter-&amp;gt;save($this-&amp;gt;filename);

 header("Pragma: public");
 header("Expires: 0");
 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
 header("Cache-Control: public");
 header("Content-Description: File Transfer");

 //Use the switch-generated Content-Type
 header('Content-type: application/msword');//输出的类型

 //Force the download
 $header="Content-Disposition: attachment; filename=".$this-&amp;gt;filename.";";
 header($header);
 @readfile($this-&amp;gt;filename);
 }
}

上面的代码重点感觉不是word生成,而是Simplehtmldom的使用,这是一个开源的HTML解析器,之前有提到,这几天在看他的代码,

引出了两个学习方向

  1. 正在表达式
  2. 这个扩展的函数整理

看源代码的收获:

PHP的异常是可以捕获的,而且PHP的错误也是可以捕获的。


error_get_last() &amp;nbsp;//用这个函数可以捕获页面中的PHP错误,不谢。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

(Spamcheck Enabled)