采集是很多公司都做最的一件事,能够快速的获取别人辛苦得来的数据,虽为不道义,但无法禁止!
PHP采集一般方式有:
正则采集。
使用DOM对象采集。
使用字符串函数提取。
这里只说下DOM对象采集的一些问题:
PHP有DOM对象专门用来处理HTML或XML文件,非常方便。
$dom = new DOMDocument('1.0','GBK');//创建DOM对象 @$dom->loadHTMLFile($url);//加载对应的URL地址HTML内容 $xpath=new DOMXPath($dom);//创建DOMXPath对象
DOMXPath对象是一个支持 XPath 路径表达式,http://www.w3school.com.cn/xpath/
XPath 路径表达式类似 JQuery选择器一样,可以方便的找到对应的节点然后提取内容,当然 XPath 的选择方式要远比 JQuery 多。而且还支持很多种函数处理。
注意:
@$dom->loadHTMLFile($url);//加载对应的URL地址HTML内容
这句代码前面最好加上 @ 符号,因为在加载解析HTML内容时,或多或少会出现错误,如:在HTML页面内一些 & 符号要转义成 & ,html实体符号必须以 ;结束等等 才能顺利解析。而这类要求在采集过程中是不可能的。
采集过程中最让人麻烦的是中文字符处理,使用正则采集时,中文字符加在正则内虽然方便但容易出错,正则中写入中文必须保证被采集的字符集与当前系统代码字符集是相同的,否则匹配很容易失败。
使用DOMDocument解析HTML内容,也容易出现中文问题,一般是乱码,其主要原因是HTML结构不标准,
出现乱码都是字符集的问题,一般在HTML的head标签要指定字符集
<meta http-equiv=Content-Type content="text/html;charset=gb2312">
当这个标签不存在时,DOMDocument在解析时就会以默认的方式去解析这个HTML内容,导致中文编码错误。
所以在使用DOMDocument采集时不要直接使用
@$dom->loadHTMLFile($url);//加载对应的URL地址HTML内容
方式直接加载HTML,这样只要所采集的HTML内容没有包含字符集的指定,整个HTML内容解析后中文就不能用。
最好使用:
$ch = curl_init($url);//创建连接 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);//输出内容 curl_setopt($ch, CURLOPT_TIMEOUT, 10);//设置超时时间 $html = curl_exec($ch);//执行连接,获取内容 if($err=curl_error($ch)){//判断是否出错 die($err); }else{ //判断是否存在这个标签 if(!stripos('"Content-Type"', $html)&&!stripos('content="text/html;', $html)){ $meta='<head><meta http-equiv="Content-Type" content="text/html; charset=GBK" />'; $html=str_replace('<head>', $meta, $html); } } curl_close($ch); $dom = new DOMDocument('1.0','GBK');//创建DOM对象 @$dom->loadHTML($html);//加载对应的URL地址HTML内容 $xpath=new DOMXPath($dom);//创建DOMXPath对象
对应所采集的页面字符集,必须核对好。
DOMXPath有两个函数用来操作内部节点:
query,和evaluate
query:取出给定的XPath表达式节点列表,只要表达式合法,返回DOMNodeList对象,否则返回false。
evaluate:取出给定XPath表达式节点列表,只要表达式合法并且有匹配的节点返回DOMNodeList对象,否则返回false。
两个函数都是提取节点,只是返回值上有些区别。
DOMNodeList 对象有一个函数和一个属性:
/* 属性,节点列表个数 */
readonly publicint $length ;
/* 方法获取第几个节点 */
DOMNode DOMNodelist::item ( int $index )
使用item函数获取的节点 DOMElement 对象 ,
可以使用 getAttribute 获取节点属性值,也可以使用 nodeValue 属性获取节点内容。