一个PHP实现的轻量级简单爬虫
Posted qq^^614136809
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个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运行本身有内存使用量限制
使用的时候,先在mysql中创建net_spider数据库,然后用db.sql创建相关表。再在config.php中设置mysql 的用户名口令。
最后
代码如下:
php -f spider.php 深度(数值) url
就可以开始工作。如
代码如下:
php -f spider.php 20
现在感觉下来,其实做个爬虫没那么复杂,难的是数据的存储和检索。我现在的数据库,最大一个数据表已经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简单爬虫 基于QueryList采集库 和 ezsql数据库操作类
QueryList是一个基于phpQuery的PHP通用列表采集类,得益于phpQuery,让使用QueryList几乎没有任何学习成本,只要会CSS3选择器就可以轻松使用QueryList了,它让PHP做采集像jQuery选择元素一样简单。
官方地址:https://querylist.cc/
ezSQL PHP 是用php开发的一套轻量级的数据库类,这个数据库类占用服务器资源小,代码简洁,同时支持多种数据库的使用,安全性高。
下载地址:sjolzy.cn/php/ezSQL/bak/ez_sql_2.05.zip
搭建一个简单的框架目录结构:
db里放得是ezsql类相关文件
lib里放得是querylist相关文件
index.php 为主程序
以采集猫眼电影TOP100为例代码如下:
index.php
<?php require \'lib/phpQuery.php\'; require \'lib/QueryList.php\'; require "db/shared/ez_sql_core.php"; require "db/mysql/ez_sql_mysql.php"; use QL\\QueryList; //抓取猫眼电影TOP100榜单内容 $db = new ezSQL_mysql(\'root\', \'root\', \'spider\', \'localhost\'); $offset=0; for($i=0;$i<10;$i++){ $gurl="http://maoyan.com/board/4?offset=".$offset; // echo $gurl.PHP_EOL; $rules = array( //采集id为one这个元素里面的纯文本内容 \'url\' => array(\'.movie-item-info .name a\',\'href\',\'\',function($content){ return \'http://maoyan.com\'.$content; }),//链接 ); $data = QueryList::Query($gurl,$rules)->data; // print_r($data); foreach ($data as $key => $val) { getContents($db,$val[\'url\']); } $offset+=10; echo "弟".($i+1)."页完成".PHP_EOL; } //取电影内容 传入内容页的链接地址 function getContents($db,$url){ $rules = array( //采集id为one这个元素里面的纯文本内容 \'name\' => array(\'.movie-brief-container .name\',\'text\'),//电影名 \'ename\' => array(\'.movie-brief-container .ename\',\'text\',\'\',function($content){ return str_replace("\'","\\\'",$content); }),//英文名 \'type\' => array(\'.movie-brief-container ul li:eq(0)\',\'text\'),//电影类型 \'area\' => array(\'.movie-brief-container ul li:eq(1)\',\'text\',\'\',function($content){ return trim(explode("/", $content)[0]); }),//产地 \'timelen\' => array(\'.movie-brief-container ul li:eq(1)\',\'text\',\'\',function($content){ return trim(explode("/", $content)[1]); }),//片长 \'addtime\' => array(\'.movie-brief-container ul li:eq(2)\',\'text\',\'\',function($content){ return substr($content,0,10); }),//上映时间 \'addarea\' => array(\'.movie-brief-container ul li:eq(2)\',\'text\',\'\',function($content){ return substr($content,10); }),//上映地点 ); $data = QueryList::Query($url,$rules)->data; print_r($data); $name=$data[0]["name"]; $ename=$data[0]["ename"]; $area=$data[0]["area"]; $type=$data[0]["type"]; $timelen=$data[0]["timelen"]; $addtime=$data[0]["addtime"]; $addarea=$data[0]["addarea"]; $db->query("INSERT INTO maoyan (name, ename,type,area,timelen,addtime,addarea) VALUES (\'$name\',\'$ename\',\'$area\',\'$type\',\'$timelen\',\'$addtime\',\'$addarea\')"); }
采集的结果:
项目下载:https://files.cnblogs.com/files/wordblog/spider.rar
以上是关于一个PHP实现的轻量级简单爬虫的主要内容,如果未能解决你的问题,请参考以下文章