从零开始,学会 PHP 采集

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

通过修改 IP 值,你就可以获取任意 IP 对应的地址了

一个 IP 查询工具就这样诞生了!

然鹅,,你肯定也注意到了。以上获取到的数据内容似乎有点乱:

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

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

正则表达式入门

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

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

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

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

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

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

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

它的用法是这样的:

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

又到了上代码的时间:

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

结束语

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python爬虫与算法进阶

使用scrapy发送post请求的坑

Requests 简便的 API 意味着所有 HTTP 请求类型都是显而易见的。例如,你可以这样发送一个 HTTP POST 请求:

3482
来自专栏更流畅、简洁的软件开发方式

【开源】QuickPager ASP.NET2.0分页控件V2.0.0.1——支持多种数据库。让分页更加简单。

分页控件的源代码下载网址:http://www.cnblogs.com/jyk/archive/2008/04/25/1170979.html (在网页的下...

19210
来自专栏ChaMd5安全团队

巅峰极客 第二场 WriteUp

1 返回地址覆盖为printf(func_got)/write(1,func_got,4)来leak libc,并将printf/write返回地址设为game...

832
来自专栏lgp20151222

Error resolving template: template might not exist or might not be accessible是一句缩水报错?

thymeleaf在开发的时候本地调试正常,但是在测试环境打成jar包就报这个错误了。

1152
来自专栏转载gongluck的CSDN博客

超级强大的vim配置(vimplus)

最近在重新配置Vim,也在GitHub上找了三个star和fork数目很高的方案,在这里分享给大家: https://github.com/amix/vimr...

2.2K9
来自专栏西二旗一哥

iOS - Add apple document

803
来自专栏deepcc

页面缓存之Meta http-equiv属性详解

1255
来自专栏前端说吧

js - 预加载+监听图片资源加载制作进度条

这两天遇到一个新需求:一个一镜到底的h5动画。因为功能的特殊性,就要求我们提前监听页面的静态图片是否全部加载完毕。即处理预加载。

2001
来自专栏.NET后端开发

如何通过经纬度获取地址信息?

摘要 Google Maps API Web Services,是一个为您的地图应用程序提供地理数据的 Google 服务的 HTTP 接口集合。具体包括:Go...

37911
来自专栏james大数据架构

Android 命名规范 (提高代码可以读性)

android文件众多,根据名称来辨别用途很重要,因此命名要规范 这篇文章可参考:Android 命名规范 (提高代码可以读性) 刚接触android的时候,命...

1917

扫码关注云+社区