从零开始,学会 PHP 采集

mengkun 26K 49

今天通过两个具体的实例,教大家从零开始使用 PHP 来抓取需要的数据。

准备工作

首先,你需要准备一个 Html 编辑器(如 notepad++),以及一个支持 PHP 的网站空间。

新建一个 PHP 文件,命名为 get.php

第一行代码

打开 get.php ,在里面输入

  1. <?php
  2. echo 'hello php';
  3. ?>

保存,然后将这个 PHP 文件上传至你的网站空间,通过浏览器访问这个 PHP 文件,浏览器输出 “hello php”。恭喜你!已经写下了第一行 PHP 代码!

别看只有小小的三行代码,其实包含了很多知识点!(敲黑板……)

第一行代码的 尖括号+问号+php 是 PHP 语言的开始标记,所有的 PHP 代码都要写在开始标记的后面。

第二行代码是一个输出语句,用 echo 输出一个字符串。字符串用单引号包起来。其实用双引号也是一样的。双引号与单引号的区别是双引号中可以直接放变量。每一句 PHP 代码的结尾都用半角的分号表示结束。

第三行的 问号+反尖括号 是 PHP 的结束标记,用于表示 PHP 代码到这里就全部结束了。如果后面没有了其它的 HTML 代码,那么结束标记可以省略

初试信息抓取

以下内容以抓取 图灵机器人 的 Api 接口内容为例:

图灵机器人 提供了一个虚拟聊天机器人数据接口,它的调用方式如下:

  1. http://www.tuling123.com/openapi/api?key=e825286159f9f57db1b597995d72ae2b&info=你要说的话

我们可以直接在浏览器中访问这个接口地址。浏览器会显示如下内容:

  1. {"code":100000,"text":"我有话要对谁说呢"}

这种用大括号括起来的数据格式叫 JSON。待会我们再谈如何去解析 JSON 数据。

现在我们要做的是通过 PHP 来抓取上述接口的内容。

PHP 有一个很方便的文件读取函数:file_get_contents()。我们可以直接用 file_get_contents('要抓取的网址') 来获取指定网址(接口)的内容

代码示例:

  1. <?php
  2. $data = file_get_contents('http://www.tuling123.com/openapi/api?key=e825286159f9f57db1b597995d72ae2b&info=你好');
  3. echo $data;
  4. ?>

运行这行代码,浏览器中显示的应该是和直接去访问原接口地址类似的内容。这就说明我们已经成功地从图灵的接口抓取到了数据。

JSON 数据的解析

下面,我们需要从原始的 JSON 中解析出 "text" 这个键值的内容,也就是机器人回复你的内容。

同样的,PHP 也提供了一个非常方便的用于解析 JSON 的函数:json_decode()。这个函数有两个参数,第一个参数是原始 JSON 数据,第二个参数 assoc 用于指定返回数据的格式,如果为 true 返回数组格式,如果为 false 则返回一个对象。

我们这里将 JSON 解析成数组来使用。

代码如下:

  1. <?php
  2. $data = file_get_contents('http://www.tuling123.com/openapi/api?key=e825286159f9f57db1b597995d72ae2b&info=你好');    // 从图灵的接口获取数据
  3. $arr = json_decode($data, true);    // 将获取到的 JSON 数据解析成数组
  4. echo $arr['text'];        // 输出数组中的 “text” 值(也就是之前 JSON 中的“text”键值中的内容)
  5. ?>

现在我们去运行代码,浏览器中只会显示机器人回复的内容了,没有了其它的 json 内容。

参数获取

上面的代码中,接口中发送的字符串(也就是我们发给机器人)的文字是固定的,如果要给机器人发不同的内容,那么只能修改代码……这样很不方便。

其实,我们可以通过 get 的方式传递给 PHP 一些参数,以此来动态改变内容。

PHP 中可以使用 $_GET() 来获取 get 方式发送的数据。

那么问题来了,什么是 get 发送数据呢?仔细研究一下图灵的接口,它的数据传递方式是 图灵接口+你要说的话 这种数据传送方式就是 get。你如果直接在浏览器里访问可以在地址栏看到全部的 get 发送的数据。

加了 get 数据传递后的代码如下:

  1. <?php
  2. $get = $_GET['says'];    // 获取 get 数据
  3. $data = file_get_contents('http://www.tuling123.com/openapi/api?key=e825286159f9f57db1b597995d72ae2b&info='.$get);    // 从图灵的接口获取数据
  4. $arr = json_decode($data, true);    // 将获取到的数据解析成 JSON 格式
  5. echo $arr['text'];        // 输出数组中的 “text” 值(也就是之前 JSON 中的“text”键值中的内容)
  6. ?>

现在,你可以直接跟你的机器人“对话”了。

方法就是访问

  1. http://你的网址/get.php?says=你想说的话

至此,你已经学会了抓取 Api 接口的内容并解析 JSON 数据。

但是有时我们抓取到的数据格式并不是 JSON,那该怎么办呢?且听我慢慢说来……

初识 Curl

上面介绍了一个抓取网页数据的 PHP 函数:file_get_contents() ,这个函数使用起来非常简单,但却不是万能的。

下面以 126 的 IP 定位接口为例:

  1. http://ip.ws.126.net/ipquery  

直接访问这个接口地址,你会发现浏览器返回了你当前的 省份 和 城市 信息。

我们再尝试用 file_get_contents() 来抓取这个接口的内容。

  1. <?php  
  2. $data = file_get_contents('http://ip.ws.126.net/ipquery');    // 从接口获取数据  
  3. echo $data;  
  4. ?>  

运行这行代码,你会发现浏览器中输出的并不是你本地的地址,而是服务器的地址。

你用 PHP 从服务器去抓取,接口那边获取到的是你服务器的 IP,然后返回服务器的地址,没毛病!

那么,可不可以在服务器那边伪造一个 IP 地址,然后去抓取呢?

当然可以~这时就得是 Curl 上场了。Curl 的参数有很多,用法也很复杂。具体的可以百度去了解。我这里直接提供一个封装好的函数,可以拿来直接使用。

  1. /** 
  2.  * Curl 伪造 IP 并从指定网址获取数据 
  3.  * @param $url 接口地址 
  4.  * @param $ip 伪造的 IP 
  5.  * @return 抓取到的内容 
  6.  */  
  7. function myCurl($url$ip){   
  8.     $ch = curl_init();     // Curl 初始化  
  9.     $timeout = 30;     // 超时时间:30s  
  10.     $ua='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36';    // 伪造抓取 UA  
  11.     curl_setopt($ch, CURLOPT_URL, $url);              // 设置 Curl 目标  
  12.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);      // Curl 请求有返回的值  
  13.     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);     // 设置抓取超时时间  
  14.     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);        // 跟踪重定向  
  15.     curl_setopt($ch, CURLOPT_ENCODING, "");    // 设置编码  
  16.     curl_setopt($ch, CURLOPT_REFERER, $url);   // 伪造来源网址  
  17.     curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:'.$ip, 'CLIENT-IP:'.$ip));  //伪造IP  
  18.     curl_setopt($ch, CURLOPT_USERAGENT, $ua);   // 伪造ua   
  19.     curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); // 取消gzip压缩  
  20.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts  
  21.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);  
  22.     $content = curl_exec($ch);   
  23.     curl_close($ch);    // 结束 Curl  
  24.     return $content;    // 函数返回内容  
  25. }  

有了这个函数你就可以直接通过 myCurl('目标网址', '伪造的IP') 来伪造 IP 并获取数据了。

示例如下:

  1. <?php  
  2. $data = myCurl('http://ip.ws.126.net/ipquery', '223.81.141.38');    // 伪造 IP 并获取数据  
  3. echo $data;  
  4.   
  5. /** 
  6.  * Curl 伪造 IP 并从指定网址获取数据 
  7.  * @param $url 接口地址 
  8.  * @param $ip 伪造的 IP 
  9.  * @return 抓取到的内容 
  10.  */  
  11. function myCurl($url$ip){   
  12.     $ch = curl_init();     // Curl 初始化  
  13.     $timeout = 30;     // 超时时间:30s  
  14.     $ua='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36';    // 伪造抓取 UA  
  15.     curl_setopt($ch, CURLOPT_URL, $url);              // 设置 Curl 目标  
  16.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);      // Curl 请求有返回的值  
  17.     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);     // 设置抓取超时时间  
  18.     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);        // 跟踪重定向  
  19.     curl_setopt($ch, CURLOPT_ENCODING, "");    // 设置编码  
  20.     curl_setopt($ch, CURLOPT_REFERER, $url);   // 伪造来源网址  
  21.     curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:'.$ip, 'CLIENT-IP:'.$ip));  //伪造IP  
  22.     curl_setopt($ch, CURLOPT_USERAGENT, $ua);   // 伪造ua   
  23.     curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); // 取消gzip压缩  
  24.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts  
  25.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);  
  26.     $content = curl_exec($ch);   
  27.     curl_close($ch);    // 结束 Curl  
  28.     return $content;    // 函数返回内容  
  29. }  
  30.   
  31. ?>  

通过修改 IP 值,你就可以获取任意 IP 对应的地址了 [坏笑] 一个 IP 查询工具就这样诞生了!

然鹅,,你肯定也注意到了。以上获取到的数据内容似乎有点乱:
从零开始,学会 PHP 采集

如果我只想获取到其中的省份和城市信息,该怎么办呢?

细心的你肯定发现了,这个数据并不是 JSON 格式的,因此也就不能通过上文的 解析 JSON 的方法来进行解析。那该怎么办呢?

正则表达式入门

每到要从一堆杂乱的内容中获取内容,就是正则表达式登场的时候了!

仔细观察返回的数据,其实内容中除了城市和省份,其它的内容是固定的,格式如下:

var lo="省份", lc="城市";

我们可以以此来编写正则表达式。推荐使用 站长工具的正则表达式测试工具(http://tool.chinaz.com/regex/),可以实时测试匹配结果,很方便。没接触过正则表达式的也可以查阅工具中的正则表达式语法说明来现学。

这是我写好的正则表达式内容。可以完美地匹配出需要的内容

  1. lo="(.*)", lc="(.*)";  

从零开始,学会 PHP 采集

有了正则表达式,再就需要用 PHP 来从原始数据中来匹配出来了。于是乎我们又用上了一个新的 PHP 函数:preg_match()

它的用法是这样的:

  1. preg_match('正则表达式', '输入内容', '存储匹配结果的变量’)  

又到了上代码的时间:

  1. <?php  
  2. $data = myCurl('http://ip.ws.126.net/ipquery', '223.81.141.38');    // 伪造 IP 并获取数据  
  3.   
  4. preg_match('/lo="(.*)", lc="(.*)";/', $data$arr);    // 正则提取  
  5.   
  6. /** 
  7. 注: 
  8. 正则表达式中括号括起来的部分代表要匹配的内容, 
  9. 像上面这个正则表达式中有两个括号括起来的部分,自然就代表会匹配出两个内容。 
  10.  
  11. 正则匹配的结果会以【数组】的形式赋值给第三个参数,也就是 $arr 
  12.  
  13. 那么……  
  14. $arr[0]是整个正则表达式匹配出的内容(无视括号) 
  15. $arr[1]是第一个括号中匹配出的内容 
  16. $arr[2]是第二个括号中匹配出的内容 
  17. . 
  18. . 
  19. $arr[n]是第N个括号中匹配出的内容(如果有的话。。) 
  20. **/   
  21.   
  22. echo $arr[1].' - '.$arr[2];    // 输出  
  23.   
  24.   
  25.   
  26. /** 
  27.  * Curl 伪造 IP 并从指定网址获取数据 
  28.  * @param $url 接口地址 
  29.  * @param $ip 伪造的 IP 
  30.  * @return 抓取到的内容 
  31.  */  
  32. function myCurl($url$ip){   
  33.     $ch = curl_init();     // Curl 初始化  
  34.     $timeout = 30;     // 超时时间:30s  
  35.     $ua='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36';    // 伪造抓取 UA  
  36.     curl_setopt($ch, CURLOPT_URL, $url);              // 设置 Curl 目标  
  37.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);      // Curl 请求有返回的值  
  38.     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);     // 设置抓取超时时间  
  39.     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);        // 跟踪重定向  
  40.     curl_setopt($ch, CURLOPT_ENCODING, "");    // 设置编码  
  41.     curl_setopt($ch, CURLOPT_REFERER, $url);   // 伪造来源网址  
  42.     curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:'.$ip, 'CLIENT-IP:'.$ip));  //伪造IP  
  43.     curl_setopt($ch, CURLOPT_USERAGENT, $ua);   // 伪造ua   
  44.     curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); // 取消gzip压缩  
  45.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts  
  46.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);  
  47.     $content = curl_exec($ch);   
  48.     curl_close($ch);    // 结束 Curl  
  49.     return $content;    // 函数返回内容  
  50. }  
  51.   
  52. ?>  

结束语

本文从零开始,大致地讲了下使用 PHP 抓取数据并进行解析、获取自己想要的内容的方法,旨在起到一个抛砖引玉的作用。因为时间及水平有限,可能有些地方说得比较笼统。

如果还要不懂的地方,可以尝试通过百度来解惑,百度上的很多教程都比较详细。

如果有百度了还没解决的问题,可以直接在下面留言。

发表评论 取消回复
表情 图片 链接 代码

  1. 干饭王阿牛
    干饭王阿牛 Lv 2

    相当于爬虫了吧

  2. Sakura
    Sakura Lv 2

    {"code":200,"msg":"OK","data":[{"name":"test1","test2":"测试","id":"123","time":240,"pic":"http://www.7k7k.com/1.jpg","lrc":"http://www.4399.com/1.lrc","url":"http://www.baidu.com"}]}

    data里面的数组怎么获取呢?

    • wlkjyy
      wlkjyy Lv 1

      @Sakura用foreach函数
      遍历出来就行 还有正则表达式也可以

  3. zhdown
    zhdown Lv 1

    MK大侠真是古道热肠,哈哈,如果能帮写一个完整的采集插件,就更棒了,其实做成收费的也可以。

  4. 佩奇
    佩奇 Lv 1

    感谢,这篇文章解决了困扰我好几天的问题[aru_16]

  5. 莫斯科
    莫斯科 Lv 1

    遇到一个问题,采集文章以后,某些网站上的设置不能直接显示出来,非要再手动打开每一篇文章,编辑保存一次,然后就都正常了.这是什么情况,怎么破解这个难题?

分享