今天跟大家分享两段php代码,一段是PHP实现简易爬虫,一段是PHP实现简易采集程序。代码都比较简单,适合会点php的SEO初学者。
PHP实现简易爬虫
代码中涉及两个表,urls和visited,分别代表已发现的URL和已抓取过的URL,这两个表是爬虫程序的必备部分。
<?php set_time_limit(0); //设置程序的运行上限时间为不限制 $conn = mysql_connect("localhost","用户","密码"); mysql_select_db("数据库名",$conn); mysql_query("set names 'utf8'"); //utf8是设置的编码,视具体情况而定 for($r=0;$r<=9999999999999;$r++) { //设置抓取页面总数,不设置的话,会持续抓取下去 $i = 0; while($i == 0) { $sql = "SELECT * FROM `urls` ORDER BY RAND() LIMIT 1"; $result = mysql_query($sql,$conn); while($row = mysql_fetch_array($result)) { $url = $row['urls']; } //选择url $sql = "SELECT COUNT(*) FROM `visited` WHERE urls='".$url."'"; $result = mysql_query($sql,$conn); while($row = mysql_fetch_array($result)) { $isVisited = $row['COUNT(*)']; } if ($isVisited == 0) break; //消除已抓取过的 } $content = file_get_contents($content); //此处需要根据具体情况加代码,比如把$content存入数据库中 $urls = getUrl($content); //提取URL的函数,自己写的版本不具备通用性,所以这里不补充了 foreach ($urls as $current) { $sql = "SELECT COUNT(*) FROM `urls` WHERE urls='".$current."'"; $result = mysql_query($sql,$conn); while($row = mysql_fetch_array($result)) { $isExisted = $row['COUNT(*)']; } if ($isExisted == 0) { $sql = "INSERT INTO urls set urls = '" . $current . "';"; mysql_query($sql,$conn); } } $sql = "INSERT INTO visited set urls = '" . $url . "';"; mysql_query($sql,$conn); sleep(1); //延时1秒继续循环 } ?>
PHP编写简易采集程序
1.先要用一个数组存放所需的网站url,依具体情况不同,url有时是通过之前的一段代码从某些网页上面采集过来,有时是存在在数据库里面,有些是就保存在记事本里面。这里就不展开了,以最后一个最简单的例子来:
$urls = array( 'sb.google.com', 'www.baidu.sb' );
就是向名为urls的数组里面,放进去两个url。
2.然后么就是要下载一个网页,就是平常site的时候出现的那个,在下载之前,当然先要确定它的url是什么,这里用$url变量来储存:
$url = 'http://www.baidu.com/s?wd=site%3A'.$current;
$current变量指的是当前查询收录量的那个网站的url。几个url都要查收录量嘛,一起上貌似也可以,技术上太麻烦了,所以分批一个个来。具体的在最后再总结下。
‘s?wd=’后面的就是查询的命令了,’%3A’在这里是冒号的转义符。
3.下载网页,很简单,PHP的方便之处显现出来了。
$content = file_get_contents($url);
4.用正则表达式在网页内提取自己需要的部分。不要问我什么是正则表达式,因为我也解释不清楚,自己也只会将就着用而已。
先看百度SERP的html源代码里面,需要的这部分长什么样的:
<span style=”margin-left:120px”>找到相关结果1,000,000,000个</span></p>
稍微再啰嗦点介绍这段文字的特性:
“margin-left:120px”这一块很纠结,不一定每次都是这样的,随着找到结果数量的不同,显示结果数量的位置也不同,所以这一块也会跟着不同,总之很麻烦。
而结果数量的那个数字后面的那些都是固定的,都是以“个”打头,总字数固定。
那么下面相应的PHP代码:
preg_match("/(<span class=\"nums.*?)([0-9,]*)(..<\/span><\/p>)/i",$content,$match); $index = $match[2];
preg_match里面有三个括号,第一个括号是想要的信息之前的信息,第三个是之后的信息,都是为了限定当中一个的范围的。而当中一个括号所匹配到的东西,就是需要的东西。
听上去估计有点绕口,那么理解这个的最好方法是去实际的写一下。
第一个括号中的后半部分.*?这个指的是匹配任意个所有的常规字符,因为之前提到的,这部分的内容是会变化的,所以只能这样把所有的情况都匹配掉。
第二个括号中,[0-9,]*的意思是匹配任意的字符,这些字符可以是数字,也可以是逗号(有没有留意到结果数字里面有逗号?)。那么收录量这个数字就全部被匹配进去了。
但问题是仔细的话就会发现,第一个括号所能限定的范围是模糊的,因为后面的.*?可以匹配任意长度的字符,假设是这样的话“margin-left:120px”里面的120也可能会被匹配。
这样子,既然第一个括号不能准确的限定范围,就要在第三个括号里面限定。第三个括号里面,’..’指的是任意两个常规字符,这里指的就是汉字“个”,因为每一个汉字都是两个字符组成的。之后的就不必解释了吧。
另外需要留意的是,/和”这两个符号在正则表达式里面不能直接用,要用转义符才行,即换做\/和\”。
正则表达式之后的一行,就是把$match[2](就是第二个括号所匹配到的内容),把它存入到$index中以备后用。
一个题外话,虽然这个例子里面没出现,但是偶尔的情况下,如果正则表达式匹配到的既有字符、也有数字,但是只要数字的话怎么办呢?这问题以前碰上过几次,一开始没能找到简单的解决方法,后面想出来一个小技巧,强制类型转换一下就行了:$a = (int)$b
最后,给一段完整版的查询收录量代码吧:
<?php set_time_limit(0); //设置程序的运行上限时间为不限,稍大规模的采集必备,不然默认运行5分钟后强制退出 $urls = array( 'sb.google.com', 'www.baidu.sb' ); foreach ($urls as $current) { $url = 'http://www.baidu.com/s?wd=site%3A'.$current; $content = file_get_contents($url); preg_match("/(<span class=\"nums.*?)([0-9,]*)..<\/span><\/p>)/i",$content,$match); $index = $match[2]; echo $index.'<br />'; //在屏幕上直接依次输出这些网站的收录量 } ?>
其中用到了foreach循环,如果不理解的话,就到一开始就介绍的W3SCHOOL的那个页面补充下知识吧。
最后,代码是死的,得出的数据也是死的,但人的需求是活的。根据不同的需求,采集不同的数据,用不同的方法进行分析才是应该去做到的。
采集的不一定是收录量,可以是外链、标题等等,分析不一定是用眼睛去看,可以用Excel排序、用统计学分析等等。所以只是介绍一个大概的方法,后面的视具体情况变通吧。
摘自:SEO技术领域