PHP爬虫(3)PHP DOM开源代码里的大坑和字符编码

一、开源代码的问题

PHP爬虫(2中介绍了开源工程Sunra.PhpSimple.HtmlDomParser。在实际工作中发现一个问题,例如http://www.163.com的网页数据怎么也抓取不下来。

$url = "http://www.163.com";
$content = Http::request($url);
$dom = str_get_html($content);//dom返回值为false

检查simple_html_dom.php代码发现,

 if (empty($str) || strlen($str) > MAX_FILE_SIZE)
 {
       $dom->clear();
       return false;
 }

要判断加载字符串的长度。此处可以将MAX_FILE_SIZE修改更大一些,或者去除这个判断。

二、字符编码

网页抓取必然要处理网页内容,网页内容的编码有很多种,常见的UTF-8,GBK,GB2312等。通常处理的过程,首先判断字符编码,再转化成统一编码。

判断编码的代码,

function ws_mb_detect_encoding ($string, $enc=null, $ret=null) {       

        static $enclist = array( 

            ‘UTF-8‘, ‘GBK‘, ‘GB2312‘, ‘GB18030‘

        );
        $result = false;
        foreach ($enclist as $item) {
            //$sample = iconv($item, $item, $string);
            $sample = mb_convert_encoding($string,$item, $item);
            if (md5($sample) == md5($string)) {
                if ($ret === NULL) { $result = $item; } else { $result = true; }
                break;
            }
        }
return $result;
}

转化成UTF-8编码

$html = mb_convert_encoding($html,"UTF-8",$enc);
//enc是ws_mb_detect_encoding返回值

下面的代码,是从一个导航页面,抓取全部链接,找到链接文档的title信息

<?php
    Vendor(‘Sunra.PhpSimple.HtmlDomParser‘);
    $url = "http://hao.360.cn/";
    $html = file_get_html($url);
    $links = $html->find(‘a‘);
    $num = 0;
    $array = array();
    foreach ($links as $l) {
      if(strpos($l->href,"http")===0)
      {
        $url = $l->href;
        $pattern = "/(http|https):\/\/\S+?\//";//查找http,https开头
        $ret = preg_match($pattern, $url,$m);
        $url =$ret?$m[0]:$url;
        if(!array_search($url, $array))
        {
          $array[] = $url;
        }
        if(count($array)>30)
        {
          break;
        }
      }
    }
    foreach ($array as $url) {
      $html = false;
      $num = 0;
      while($html==false && $num<3)
      {
        $num++;
        $html = \Home\Wsn\Http::request($url);
      }
      if($html == false)
      {
        echo "无法获取网页数据<br>";continue;
      }
      $enc = ws_mb_detect_encoding($html);
      echo $enc."<br>";
      if($enc==false)
      {
        echo "编码错误<br>";continue;
      }
      elseif($enc!=‘UTF-8‘)
      {
        $html = mb_convert_encoding($html,"UTF-8",$enc);
      }
      $dom = str_get_html($html);
      $title = $dom->find(‘title‘,0);
      if($title){
        echo "标题".$title->innertext."<br>";
      }
      else{
        echo "没找到标题<br>";
      }
      echo "<hr>";
    }
?>

附录

封装好的HTTP类如下,喜欢的同学可以拿去直接使用。

<?php
  public static function request($url, $params = array(), $method = ‘GET‘, $multi = false, $extheaders = array()) {
        if (!function_exists(‘curl_init‘)) exit(‘Need to open the curl extension‘);
        $method = strtoupper($method);
        $ci = curl_init();

        curl_setopt($ci, CURLOPT_USERAGENT, ‘PHP-SDK OAuth2.0‘);
        curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ci, CURLOPT_TIMEOUT, 3);
        curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ci, CURLOPT_HEADER, false);

        $headers = (array)$extheaders;
        switch ($method) {
            case ‘POST‘:
                curl_setopt($ci, CURLOPT_POST, TRUE);
                if (!empty($params)) {
                    if ($multi) {
                        foreach ($multi as $key => $file) {
                            $params[$key] = ‘@‘ . $file;
                        }
                        curl_setopt($ci, CURLOPT_POSTFIELDS, $params);
                        $headers[] = ‘Expect: ‘;
                    } else {
                        curl_setopt($ci, CURLOPT_POSTFIELDS, http_build_query($params));
                    }
                }
                break;
            case ‘DELETE‘:
                $method == ‘DELETE‘ && curl_setopt($ci, CURLOPT_CUSTOMREQUEST, ‘DELETE‘);
                break;
            case ‘GET‘:
                if (!empty($params)) {
                    $url = $url . (strpos($url, ‘?‘) ? ‘&‘ : ‘?‘)
                        . (is_array($params) ? http_build_query($params) : $params);
                }
                break;
        }
        curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE);
        curl_setopt($ci, CURLOPT_URL, $url);

        if ($headers) {
            curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
        }

        $response = curl_exec($ci);
        curl_close($ci);
        return $response;
    }
?>
时间: 2024-10-11 04:39:53

PHP爬虫(3)PHP DOM开源代码里的大坑和字符编码的相关文章

反-反爬虫:用几行代码写出和人类一样的动态爬虫

欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:李大伟 Phantomjs简介 什么是Phantomjs Phantomjs官网介绍是:不需要浏览器的完整web协议栈(Full web stack No browser required),也就是常说的无头浏览器--或者好听点叫做:无界面的web解析器. Phantomjs的特点 由于"无头"--免去了渲染可视化的网页界面,她的速度要比一般的浏览器快不少,又因为她是完整的web协议栈,所以不仅仅提供了JavaScri

C++开源代码项目汇总

Google的C++开源代码项目 v8  -  V8 JavaScript EngineV8 是 Google 的开源 JavaScript 引擎.V8 采用 C++ 编写,可在谷歌浏览器(来自 Google 的开源浏览器)中使用.V8 根据 ECMA-262 第三版中的说明使用 ECMAScript,并在使用 IA-32 或 ARM 处理器的 Windows XP 和 Vista.Mac OS X 10.5 (Leopard) 以及 Linux 系统中运行.V8 可以独立运行,也可以嵌入任何

GitHub同步已经Fork的开源代码

最近Fork了一个很不错的C++实现的算法集(https://github.com/xtaci/algorithms),如何与开源代码同步的问题也就产生了,同步方式如下: 1 首先,在自己的GitHub上Fork此开源代码,然后Clone到本地 git clone https://github.com/lanbing510/algorithms.git 2 需要同步时,执行以下命令 #添加一个远程库连接到本地,命名为algorithms git remote add algorithms htt

开源代码欣赏

Google的C++开源代码项目 v8  -  V8 JavaScript Engine V8 是 Google 的开源 JavaScript 引擎. V8 采用 C++ 编写,可在谷歌浏览器(来自 Google 的开源浏览器)中使用. V8 根据 ECMA-262 第三版中的说明使用 ECMAScript,并在使用 IA-32 或 ARM 处理器的 Windows XP 和 Vista.Mac OS X 10.5 (Leopard) 以及 Linux 系统中运行. V8 可以独立运行,也可以嵌

Google的C++开源代码项

转:http://blog.csdn.net/wenrenhua08/article/details/40040903 v8  -  V8 JavaScript EngineV8 是 Google 的开源 JavaScript 引擎.V8 采用 C++ 编写,可在谷歌浏览器(来自 Google 的开源浏览器)中使用.V8 根据 ECMA-262 第三版中的说明使用 ECMAScript,并在使用 IA-32 或 ARM 处理器的 Windows XP 和 Vista.Mac OS X 10.5

最大开源代码sourceforge 简介 及视音频方面常用的开源代码

所有的音视频凯源代码在这里:http://sourceforge.net/directory/audio-video/os:windows/,你可以下载分析,视频不懂请发邮件给我,帮你分析. 0.视频项目 0.1  VLC media player VLC 多媒体播放器(最初为VideoLAN Client,是VideoLAN计划的开放源代码多媒体播放器.)支援众多音讯与视讯解码器及档案格式,并支援DVD影音光碟,VCD影音光碟及各类串流协定.它也能作为单播 或 多播的串流服务器在IPv4 或I

Facebook在代码里下毒,百度身受重伤。。。

白首相知犹按剑     前两天看到有朋友分享说,WordPress停用了react.今天,在逛知乎时看到了另一个问题别细看这图,我赌你看不懂... 嗯...用人话来说就是百度内部要求他们的程序猿不要再使用一个叫 React的开源产品的代码了.而且,现有的已经使用过这些代码的产品要改写!(其实几乎有很多要重写了) 有朋友会问 React 是毛啊?这是 Facebook 搞的一套贼好用的前端开发工具,它能提供一些很好的效果,别的开发者可以免费拿来在它的基础上去做自己的产品,为了更多人更好的使用它,F

CocoaPods的使用(管理iOS项目中第三方开源代码)

CocoaPods是一个负责管理iOS项目中第三方开源代码的工具.可以节省设置和更新第三方开源库的时间,提高工作效率. 下面是CocoaPods的使用步骤,强烈建议在家里的网络做以下操作,公司的网太慢了,除非你觉得很快!! 1.打开终端 sudo gem install cocoapods 命令解释:用gem安装cocoapods工具包 输入这行命令后,会让你输入电脑密码 接下来就是一大堆安装操作,耐心等待. 然后会出现下面的情况 Installing ri documentation for

iOS流行的开源代码库

本文介绍一些流行的iOS的开源代码库 1.AFNetworking 更新频率高的轻量级的第三方网络库,基于NSURL和NSOperation,支持iOS和OSX.https://github.com/AFNetworking/AFNetworking 2.GPUImage 图像处理库,基于OpenGL ES,图像处理效率高.https://github.com/BradLarson/GPUImage 3.Masonry 自动布局库.https://github.com/SnapKit/Mason