一个PHP实现的轻量级简单爬虫_php实例

最近需要收集资料,在浏览器上用另存为的方式实在是很麻烦,而且不利于存储和检索。所以自己写了一个小爬虫,在网上爬东西,迄今为止,已经爬了近百 万张网页。现在正在想办法着手处理这些数据。

爬虫的结构:
   爬虫的原理其实很简单,就是分析下载的页面,找出其中的连接,然后再下载这些链接,再分析再下载,周而复始。在数据存储方面,数据库是首选,便于检索,而 开发语言,只要支持正则表达式就可以了,数据库我选择了mysql,所以,开发脚本我选择了php。它支持perl兼容正则表达式,连接mysql很方 便,支持http下载,而且windows系统和linux系统都可以部署。

正则表达式:
  正则表达式是处理文字的基本工具,要取出html中的链接和图片,使用的正则表达式如下。

复制代码 代码如下:

   "#<a[^>]+href=(['\"])(.+)\\1#isU"   处理链接
    "#<img[^>]+src=(['\"])(.+)\\1#isU" 处理图片

其他问题:
  写爬虫还需要注意的一个问题是,对于已经下载过的url,不能重复进行下载,而有些网页的链接会形成环路,所以需要处理这个问题,我的处理方法是计算已经 处理的url的MD5 值,并存入数据库,这样就可以检验是否已经下载过。当然还有更好的算法,有兴趣的话,可以在网上找一下。

相关协议:
  爬虫也有自己的协议,有个robots.txt文件定义了那些是网站允许遍历的,但是由于我的时间有限,没有实现这个功能。

其他说明:
  php支持类编程,我写的爬虫主要的类.
  1.url处理web_site_info,主要用处理url,分析域名等。
  2.数据库操作mysql_insert.php,处理和数据库相关的操作。
  3.历史记录处理,记录已经处理的url。
  4.爬虫类。

存在的问题和不足

  这个爬虫在小数据量的情况下,运行良好,但是在大数据量的情况下,历史记录处理类的效率就不是很高,通过在数据库结构中,对相关字段进行了索引,速度有了 提高,但是需要不断得读取数据,可能和php本身的array实现有关系,如果一次加载10万条历史记录,速度非常慢。
  不支持多线程,每次只能处理一个url。
  php运行本身有内存使用量限制,有一次在抓取深度为20的页面的时候,内存用尽程序被杀。

下面的url是源码下载。

http://xiazai.jb51.net/201506/other/net_spider.rar

使用的时候,先在mysql中创建net_spider数据库,然后用db.sql创建相关表。再在config.php中设置mysql 的用户名口令。
最后

复制代码 代码如下:

php -f spider.php 深度(数值) url

就可以开始工作。如

复制代码 代码如下:

php -f spider.php 20 http://news.sina.com.cn

现在感觉下来,其实做个爬虫没那么复杂,难的是数据的存储和检索。我现在的数据库,最大一个数据表已经15G,正在想办处理这些数据,mysql进 行查询已经感觉有点力不从心了。这点上还真佩服google

<?php
#加载页面
function curl_get($url){
    $ch=curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch,CURLOPT_HEADER,1);
    $result=curl_exec($ch);
    $code=curl_getinfo($ch,CURLINFO_HTTP_CODE);
    if($code!='404' && $result){
     return $result;
    }
    curl_close($ch);
}
#获取页面url链接
function get_page_urls($spider_page_result,$base_url){
  $get_url_result=preg_match_all("/<[a|A].*?href=[\'\"]{0,1}([^>\'\"\]*).*?>/",$spider_page_result,$out);
  if($get_url_result){
    return $out[1];
  }else{
    return;
  }
}
#相对路径转绝对路径
function xdtojd($base_url,$url_list){
 if(is_array($url_list)){
  foreach($url_list as $url_item){
    if(preg_match("/^(http:\/\/|https:\/\/|javascript:)/",$url_item)){
      $result_url_list[]=$url_item;
    }else {
     if(preg_match("/^\//",$url_item)){
      $real_url = $base_url.$url_item;
     }else{
      $real_url = $base_url."/".$url_item;
     }
     #$real_url = 'http://www.sumpay.cn/'.$url_item;
     $result_url_list[] = $real_url;
    }
  }
   return $result_url_list;
 }else{
   return;
 }
}
#删除其他站点url
function other_site_url_del($jd_url_list,$url_base){
 if(is_array($jd_url_list)){
  foreach($jd_url_list as $all_url){
    echo $all_url;
    if(strpos($all_url,$url_base)===0){
     $all_url_list[]=$all_url;
    }
  }
  return $all_url_list;
 }else{
  return;
 }
}
#删除相同URL
function url_same_del($array_url){
   if(is_array($array_url)){
     $insert_url=array();
     $pizza=file_get_contents("/tmp/url.txt");
     if($pizza){
        $pizza=explode("\r\n",$pizza);
        foreach($array_url as $array_value_url){
         if(!in_array($array_value_url,$pizza)){
          $insert_url[]=$array_value_url;
         }
        }
        if($insert_url){
           foreach($insert_url as $key => $insert_url_value){
             #这里只做了参数相同去重处理
             $update_insert_url=preg_replace('/=[^&]*/','=leesec',$insert_url_value);
             foreach($pizza as $pizza_value){
                $update_pizza_value=preg_replace('/=[^&]*/','=leesec',$pizza_value);
                if($update_insert_url==$update_pizza_value){
                   unset($insert_url[$key]);
                   continue;
                }
             }
           }
        }
     }else{
        $insert_url=array();
        $insert_new_url=array();
        $insert_url=$array_url;
        foreach($insert_url as $insert_url_value){
         $update_insert_url=preg_replace('/=[^&]*/','=leesec',$insert_url_value);
         $insert_new_url[]=$update_insert_url;
        }
        $insert_new_url=array_unique($insert_new_url);
        foreach($insert_new_url as $key => $insert_new_url_val){
          $insert_url_bf[]=$insert_url[$key];
        }
        $insert_url=$insert_url_bf;
     }
     return $insert_url;
   }else{
    return;
   }
}

$current_url=$argv[1];
$fp_puts = fopen("/tmp/url.txt","ab");//记录url列表
$fp_gets = fopen("/tmp/url.txt","r");//保存url列表
$url_base_url=parse_url($current_url);
if($url_base_url['scheme']==""){
  $url_base="http://".$url_base_url['host'];
}else{
  $url_base=$url_base_url['scheme']."://".$url_base_url['host'];
}
do{
  $spider_page_result=curl_get($current_url);
  #var_dump($spider_page_result);
  $url_list=get_page_urls($spider_page_result,$url_base);
  #var_dump($url_list);
  if(!$url_list){
   continue;
  }
  $jd_url_list=xdtojd($url_base,$url_list);
  #var_dump($jd_url_list);
  $result_url_arr=other_site_url_del($jd_url_list,$url_base);
  var_dump($result_url_arr);
  $result_url_arr=url_same_del($result_url_arr);
  #var_dump($result_url_arr);
  if(is_array($result_url_arr)){
    $result_url_arr=array_unique($result_url_arr);
       foreach($result_url_arr as $new_url) {
         fputs($fp_puts,$new_url."\r\n");
       }
  }
}while ($current_url = fgets($fp_gets,1024));//不断获得url
preg_match_all("/<a[^>]+href=[\"']([^\"']+)[\"'][^>]+>/",$spider_page_result,$out);
# echo a href
#var_dump($out[1]);
?>

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索php
, 爬虫
, 简单
轻量级
scrapy 爬虫简单实例、python实现简单爬虫、轻量级爬虫、scrapy爬虫实例、python爬虫实例,以便于您获取更多的相关知识。

时间: 2024-12-12 09:43:07

一个PHP实现的轻量级简单爬虫_php实例的相关文章

分享一个PHP数据流应用的简单例子_php实例

复制代码 代码如下: <?php $count = 5; start: if($count < 5) echo "You can try {$count} time, "; echo "Put Password: "; $handle = fopen ("php://stdin","r"); $line = fgets($handle); if(trim($line) != '123456'){ $count--;

PHP与服务器文件系统的简单交互_php实例

1.php.ini中关于文件上传的设置指令 2.文件上传过程 (1)上传文件提交表单html代码: <!--向服务器上传文件的HTML表单(限制为文本文件)--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Adminstration - upoload new files</title>

一个用php3编写的简单计数器_php基础

php具有极其强大的图像处理能力,用它可以很轻易的动态生成web图像.  一下是一个使用php做成的一个简单计数器.   1. 总体思路:  把以往的访问人数记录在一个文本文件中,当网页被访问的时候,从打开该文件  并从中读出以往的访问人数,加 1,得到最新的访问人数,并把该数目格式化成  标准的格式,再调用图像处理函数,把该数字输出成图片,再把新的访问数字回  写到纪录访问人数的文件中.   2. 程序所用到的函数说明:  A. 相关的文件操作:  a. 打开文件:     函数的原型:int

PHP分页初探 一个最简单的PHP分页代码的简单实现_php实例

PHP分页代码在各种程序开发中都是必须要用到的,在网站开发中更是必选的一项. 要想写出分页代码,首先你要理解SQL查询语句:select * from goods limit 2,7.PHP分页代码核心就是围绕这条语句展开的,SQL语句说明:查询goods数据表从第2条数据开始取出7条数据.在分页代码中,7表示每页显示多少条内容,2通过公式计算表示翻页数,通过传入不同参数替换"2"的值,即可筛选出不同的数据. index.php: include 'conn.php'; //引入数据库

又一个PHP实现的冒泡排序算法分享_php实例

经典的冒泡排序法一直是许多程序沿用的其中一种排序法,话说冒泡排序法在效率上比PHP系统函数sort更高效.本章不讨论性能,所以就不拿它来跟系统性能做对比了. 冒泡排序大概的意思是依次比较相邻的两个数,然后根据大小做出排序,直至最后两位数.由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序.但其实在实际过程中也可以根据自己需要反过来用,大树往前放,小数往后放. <?php /** * PHP中的冒泡排序法使用 */ // 预先声明一个数组 $arr = array (1

CI框架入门之MVC简单示例_php实例

本文实例讲述了CI框架入门之MVC简单示例.分享给大家供大家参考,具体如下: 最简单的CI模型: 注意:模型需要用到数据库 配置文件在appcation/config.php 这里我们要用到数据库,需要将databases.php中的相关参数填写一下,具体不再赘述. 直接进入主题: MVC: 1.首先谈"M" 模型 CI中的模型存放在application/models文件夹里 命名规则是:类名_model.php 文件中只包含一个类: 如: class Nb_model extend

php socket通信简单实现_php实例

socket通信的原理在这里就不说了,它的用途还是比较广泛的,我们可以使用socket来做一个API接口出来,也可以使用socket来实现两个程序之间的通信,我们来研究一下在php里面如何实现socket通信. 由于socket服务端的代码要监听端口,等待接收请求,所以php在做socket服务的时候需要将php文件运行在CMD里面. 如果要使php文件可以在CMD里面运行,则需要进行如下设置: 1.添加环境变量,名字为PHP_HOME,值为php文件安装目录下的.exe文件地址,如D:\wam

WordPress中获取所使用的模板的页面ID的简单方法_php实例

什么是模板呢?默认情况 WordPress是使用主题目录下page.php来作为模板显示页面的,但是有时候我们需要不同的模板来显示页面,比如登录.注册和投稿页面等,这些页面跟普通的页面是有所区别,这时候WordPress提供了页面模板让开发者可以自定义WordPress页面外观甚至功能.页面模板php文件的匹配 WordPress中是通过自定义栏目来记录页面所使用的模板的,自定义栏目名称:_wp_page_template,值为模板的文件名: 如果是默认模板page.php,那么 _wp_pag

PHP实现页面静态化的超简单方法_php实例

为什么要页面静态化? 1.动态文件执行过程:语法分析-编译-运行 2.静态文件,不需要编译,减少了服务器脚本运行的时间,降低了服务器的响应时间,直接运行,响应速度快:如果页面中一些内容不经常改动,动态页面静态化是非常有效的加速方法.(纯静态,伪静态还是需要PHP解释器的) 3.生成静态URL利于SEO,利于蜘蛛抓取和收录,有利于提升排名 优化页面响应时间方法 1.动态页面静态化 2.优化数据库 3.负载均衡 4.使用缓存等等 //动态页面静态化一般用于不经常改动的地方,频繁改动的地方一般不适用静