PHP实现简易爬虫与简易采集程序

今天跟大家分享两段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技术领域

贾定强微信

微信扫一下,或点击链接添加好友