本文为原创作品,引用请注明出处,欢迎转载。
最近在学PHP后台,想要在网络上爬取一些健康资讯,尽管知道PHP爬取数据的能力不如Python,但还是想试试用PHP爬取网页。
这里首先介绍PHP的一个库:curl,接下来我们将主要用到这个库来爬取网页数据。
还会用到的是正则表达式,不清楚的同学可以自行上网学习相关知识。
1. 首先要初始化curl,并对其做一些基本的设置,这里将其封装成一个get()函数。
public function get($url)
{
//初使化curl
$ch = curl_init();
//请求的url,由形参传入
curl_setopt($ch, CURLOPT_URL, $url);
//将得到的数据返回
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//不处理头信息
curl_setopt($ch, CURLOPT_HEADER, 0);
//连接超过10秒超时
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
//执行curl
$output = curl_exec($ch);
//关闭资源
curl_close($ch);
//返回内容
return $output;
}
curl的步骤分为以上7步:
1.初使化curl资源
2.参数设置请求的协议地址
3.参数设置是否返回请求结果
4.设置发送数据(无发送数据可不设置)
5.其他的参数信息设置(按实际工作需要决定)
6.执行或执行得到返回结果
7.关闭curl资源
第二步至第五步本质上,应该统称为curl参数设置。
所有curl设置参数设置都是通过curl_setopt都完成
2. 分析网站源码,爬取文章列表中每篇文章的标题、图片和url
下面找一个网站来爬取数据,这里选择新浪健康网来爬取数据。
找了一下该网站的文章列表,有很多篇文章,就来爬取他们的数据。
查看该网页的源码,定位到该文章列表的代码处。
………中间文章列表还有很多,这里省略,一共有390篇文章。
选取要爬取文章的区域,为方便使用正则匹配,这里选取从<div class="seo_data_list">
到<div class="footer">
的区域
$html = $this->get('http://health.sina.com.cn/');
preg_match('/<div class="seo_data_list">(.*?)<div class="footer">/mis', $html, $match);
使用正则匹配对其进行处理,获取该html区域,使用var_dump($match)
函数来看一下爬取的结果:
返回的是两个数组,这里要使用第二个数组再对其进行正则匹配,先看之前源代码种文章列表每一项的源代码:
可以看出,它分为两种,一种是有新闻图片的,一种是没有的,这里再使用正则匹配对其进行处理:
$area = $match[1];
preg_match_all('/<div class="news-item .*?">(.*?)<\/div>/s', $area, $find);
在正则匹配条件中,截取到的是<div class="news-item .*?">
到第一个<\/div>
的区域,包含所有要提取的元素。
(本人不知道怎样用正则表达式获取成对的<div>
标签,如果有知道的大神欢迎评论一下)。
再调用var_dump($match)
函数来看一下这次处理的结果:
现在可以很清楚地看到已经把每篇文章的内容都给分出来了,下面就是对每项文章进行处理,获取自己想要的内容,还是要用到正则匹配:
$url = array();
$title = array();
$imgurl = array();
for ($n = 0; $n < sizeof($find[1]); $n++) {
//获取标题和url
preg_match_all('/<h2><a href="(.*?)" target="_blank">(.*?)<\/a><\/h2>/', $area, $utitle);
array_push($url, $utitle[1][$n]);
array_push($title, $utitle[2][$n]);
//取出图片
preg_match_all('/<img.*?src="(.*?)".*?>/is', $find[0][$n], $image);
array_push($imgurl, $image[1]);
}
dump($title);
dump($url);
dump($imgurl);
通过dump()
函数可以看到我们获取到了标题,每篇文章的url,图片的url:
到这里基本就完成了大半的工作了,接下来要根据每篇文章的url获取每篇文章的内容。
3. 分析网站源码,根据url爬取每篇文章的内容
同样地步骤,先选取要爬取的区域,这里以第一篇文章作为示例:
接着查看其源代码:
这里选取<div class="article" id="artibody" data-sudaclick="blk_content">
到<div id="left_hzh_ad">
的区域进行处理:
//根据url获取每篇资讯的具体内容
for ($n = 0; $n < sizeof($url); $n++) {
//获取content
$html1 = $this->get($url[$n]);
preg_match('/<div.*?id="artibody"(.*?)<div id="left_hzh_ad">/mis', $html1, $mat);
//将正则匹配到的内容赋值给$area
$area1 = $mat[1];
//(.*?)随意字符匹配
preg_match_all('/<p(.*?)>(.*?)<\/p>/', $area1, $find1);
//获取所有文章的内容并将其连接在一个字符串之中
$content = join($find1[0]);
var_dump($content);
}
原理和爬取文章列表的内容是一样的,这里就不多说了,就是要注意的一点是,爬取的源代码中<p>
标签是放在数组之中的,需要用join()
函数将文本内容连接起来放在一个字符串之中。
本人在爬取这些数据中遇到的最大的问题就是用正则表达式获取自己想要的网页源代码,还有很多不理解的地方,尤其是不同文章的网页标签可能还不大一样,所以会出现爬取过程中有的爬取不到的问题,自己还要好好努力,将正则表达式学精学深一点才行。