php 抓取页面

Curl

抓取页面 也就是把别人的页面抓回来分析  得出自己需要的东西 然后入库

简单点抓取 就是抓个 get请求的  不涉及到 post数据  也不涉及到登陆


一个最简单的抓取

	function getHtml($url){
		$opts = array(
				'http'=>array(
				'method'=>"GET",
				'header'=>"Content-Type: text/html; charset=utf-8" 
					)
				);        
		$context = stream_context_create($opts);        
		return file_get_contents($url, false, $context);   	
	}
	echo getHtml("http://www.baidu.com");

抓取回来的是页面 也就是由html css  js组成的东西,

一般要获取自己需要的东西,这是就得就分析页面结构,然后写正则来获取数据

一个例子(获取163财经频道的   本周点击最多  http://money.163.com/special/002526BH/rank.html)

	function getHtml($url){
		$opts = array(
				'http'=>array(
				'method'=>"GET",
				'header'=>"Content-Type: text/html; charset=utf-8" 
					)
				);        
		$context = stream_context_create($opts);        
		return file_get_contents($url, false, $context);   	
	}
	
	$url  = 'http://money.163.com/special/002526BH/rank.html';
	$file = getHtml($url);
	$reg = '/<div class="tabContents">([\s\S]*?)<\/div>/';

	if(preg_match_all($reg,$file,$matches)){
		$data = array();
		$news = $matches[1][1]; //$matches[1] 表示能够匹配改结构的所有的匹配项
		$reg = '/<a href="(?P<url>.*?)"\s*title="(?P<title>.*?)"\s*>(?P<subjet>.*?)<\/a>/';
		if(preg_match_all($reg,$news,$matches)){
			$len = count($matches["subjet"]);
			$subjet = $matches["subjet"];
			$url = $matches["url"];		
			for($i=0;$i<$len;$i++){
				$data[$i] = array("subjet"=>$subjet[$i],"url"=>$url[$i]);
				print_r($data[$i]);
			}
		}
	}else{
		echo "抓取失败";
	}

抓取结果

Array
(
    [subjet] => 王石回应离婚传闻:我没有背叛家庭
    [url] => http://money.163.com/12/1029/10/8EVOHHRV00253B0H.html
)
Array
(
    [subjet] => 浙江楼市从领涨到领跌 温州炒房客被套转投实业
    [url] => http://money.163.com/12/1105/01/8FGR7QQK00253B0H.html
)
Array
(
    [subjet] => 《时代周刊》评选2012最佳发明:谷歌眼镜上榜
    [url] => http://money.163.com/12/1102/15/8FAM06V600253G87.html
)
Array
(
    [subjet] => 网络盛传万科董事长王石已离婚
    [url] => http://money.163.com/12/1029/00/8EUPDERR00253B0H.html
)
Array
(
    [subjet] => 中粮上海楼盘单价21.6万元/平 刷新汤臣一品纪
    [url] => http://money.163.com/12/1030/10/8F2CUD73002534NU.html
)
Array
(
    [subjet] => 中国近10年来涌现13位首富 有人已锒铛入狱
    [url] => http://money.163.com/12/1029/14/8F06QTD700253G87.html
)
Array
(
    [subjet] => 2012全球25大最佳国家品牌:瑞士排名第一
    [url] => http://money.163.com/12/1030/19/8F3CH5AJ00253B0H.html
)
...........内容较多  省略掉

第二中抓取麻烦点,就要post数据,用到Curl 
一些Curl的介绍的文章

http://developer.51cto.com/art/200904/121739.htm

http://www.cmx8.cn/curl.html

一个例子 (抓取博客园  前端文章的例子      抓取地址    http://www.cnblogs.com/mvc/AggSite/PostList.aspx)  

抓取成功的页面很少, 因为博客园的博客皮肤太多 , 那个正则只支持几款皮肤,  所以失败率很高呀.ps博客园的东西真难抓取

	header("Content-type: text/html;charset=UTF-8");
	
	function postHtml($json,$url){
		$curlPost = http_build_query(json_decode($json,true));
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
		$data = curl_exec($ch);
		curl_close($ch);
		return $data;
	}

	function getHtml($url){
		$opts = array(
				'http'=>array(
				'method'=>"GET",
				'header'=>"Content-Type: text/html; charset=utf-8" 
					)
				);        
		$context = stream_context_create($opts);        
		return file_get_contents($url, false, $context);   	
	}

	$url = 'http://www.cnblogs.com/mvc/AggSite/PostList.aspx';
	$json = '{"CategoryType":"TopSiteCategory","ParentCategoryId":0,"CategoryId":108703,"PageIndex":3,"ItemListActionName":"PostList"}';
	$html = postHtml($json,$url); //抓取的原始页面
	$reg  = '/<a class="titlelnk" href="(?P<href>.*?)"[^>]+>(?P<subject>.*?)<\/a>[\s\S]*?<\/a>(?P<time>[\s\S]*?)<span class="article_comment">/';

	//因为上面的抓取 主要是提供的 标题  时间  有url  所有后面还要到url去抓取文章的内容
	if(preg_match_all($reg,$html,$matches)){
		$data = array();
		foreach($matches["href"] as $i=>$href){
			$html = getHtml($href);
			$reg = '/<div class="postText">(?P<content>[\s\S]*?)<\/div>\s*\r\s*<p class="postfoot">/';
			if(preg_match_all($reg,$html,$rs)){
				echo $matches["href"][$i]."----------------成功<br>";
				$data[$i] = array("href"=>$href,"subject"=>$matches["subject"][$i],"time"=>$matches["time"][$i],"body"=>$rs["content"][0]);
			}else{
				echo $matches["href"][$i]."----------------失败<br>";
			}			
		}
	}


第3中抓取是需要登录的,有些数据需要登录后才可见.  就需要模拟登陆.

http是无状态的,服务端要识别客户端的请求用户是否登陆,就需要用到cookie, 所以先抓包登陆请求地址需要post参数,然后讲cookie存起来放到其他文件,然后请求登陆后的页面的时候把cookie带上,就可以模拟登陆请求一些需要的东西了,(ps 有些网站似乎有限制  不管怎么请求都没有返回)

一个例子

<?php

$url = "http://passport.cnblogs.com/login.aspx";
$login = "xxxxx";  //账号和密码
$password = "xxxxx";

$post_data = array( "__EVENTTARGET" => "","__EVENTARGUMENT" => "","__VIEWSTATE" => "/wEPDwULLTE1MzYzODg2NzZkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBQtjaGtSZW1lbWJlcm1QYDyKKI9af4b67Mzq2xFaL9Bt" ,"__EVENTVALIDATION" => "/wEWBQLWwpqPDQLyj/OQAgK3jsrkBALR55GJDgKC3IeGDE1m7t2mGlasoP1Hd9hLaFoI2G05","tbUserName" => $login,"tbPassword" => $password,"btnLogin" => "登++录","txtReturnUrl" => "http://home.cnblogs.com/"); 
$cookie_jar = tempnam('./temp','cookie');//存放COOKIE的文件

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_POST, 1);

curl_setopt($ch, CURLOPT_HEADER, 0);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);

curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);  

curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_jar);  //保存cookie信息

curl_exec($ch);

curl_close($ch); 

//上面是登陆的请求  post的东西是我抓包获取的  主要是为了获得cookie
//下面的才是用登陆后的cookie  去获取登陆后的东西


$url = "http://home.cnblogs.com/";
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_REFERER, $url);       //伪装REFERER


curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);   //返回数据,而不是直接输出

curl_setopt($ch, CURLOPT_HEADER, 0);   // 设置是否显示header信息 0是不显示,1是显示  默认为0

curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_jar);  //发送cookie文件

$output2 = curl_exec($ch);    //发送HTTP请求
curl_close($ch); 

echo $output2;
?>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值