Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[B05]PHP 中的 cURL 爬虫实战基础 #37

Open
hylerrix opened this issue Sep 19, 2017 · 0 comments
Open

[B05]PHP 中的 cURL 爬虫实战基础 #37

hylerrix opened this issue Sep 19, 2017 · 0 comments

Comments

@hylerrix
Copy link
Owner

hylerrix commented Sep 19, 2017

最近准备入手 PHP 爬虫,发现 PHP 的 cURL 这一知识点不可越过。本文探讨基础实战,需要提前了解命令行的使用并会进行 PHP 的环境搭建。

cURL 的概念

cURL,Client URL Library Functions,是利用 URL 语法在命令行方式下工作的开源文件传输工具,被广泛应用在 Unix、 Linux 发行版本中,并且有 Win32、Win64 下的移植版本。常用的 cURL 库 libcurl 支持 http、https、ftp、gopher、telnet、dict、file 和 ldap 协议。libcurl 同时也支持 HTTPS 认证、HTTP POST、HTTP PUT、 FTP 上传(这个也能通过PHP的FTP扩展完成)、HTTP 基于表单的上传、代理、cookies 和用户名+密码的认证。

cURL 官方文档

简而言之,cURL 便是客户端发起的,支持绝大多数互联网协议族的,能对网络文件进行下载或上传的管理程式。

命令行下的 cURL 能做什么

爬取网页源代码

打开命令行,输入如下命令,可以向百度服务器发送获取首页源代码的请求,> 命令将源代码输出保存到当前目录的 baidu.html 下。

curl https://www.baidu.com > baidu.html

获取表单 · GET 或 POST 方法

网页中的

标签常用来生成一个表单。当我们点击表单中的提交按钮时,浏览器会讲所有表单中填入的参数分析并包装,最终用指定的 HTTP 方式发送到目标网络地址。

如下所示代码将用户在输入框填写的参数信息 加入 URL 地址之后,并向目标服务器下的 judge.php 发送 GET 方法。GET 方法中,值和表单内各个字段一一对应。

<form method="GET" action="judge.php">
    <input type=text name="year">
    <input type=submit name=press value="OK">
</form>

GET 方法中的参数会出现在 URL 地址中,因此,我们同样在基于命令行 cURL 下模拟这一点。

curl www.example.com/judge.php?year=1997&press=ok

URL 语法指明,一个通用的 URL 地址格式如下,不难看出,上例代码中的 year 字段及其取值是 的实例。

 <scheme>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>

与 GET 方法不同的是,HTTP 中的 POST 求求向服务器传送数据,由于常有账号密码等私密信息,这些数据通常加入 HTML Header,而在 URL 地址中不可见,并向目标服务器传送数据。

命令行中 cURL 对 POST 方法的处理方法为 -d 参数。

curl -d "year=1997&press=OK" www.example.com/judge.php

上传文件 · POST 或 PUT 方法

1995年年末,RFC 1867 定义了一种新的POST方法,用来上传文件。主要用于把本地文件上传到服务器。此时页面是这样写的:

<form method="POST" enctype='multipart/form-data' action="upload.php">
    <input type=file name=upload>
    <input type=submit name=press value="OK">
</form>

对应的 cURL 命令中用 -F 作为命令参数如下。

curl -F upload=@localfilename -F press=OK URL

HTTP协议文件上传的标准方法是使用 PUT,此时 cURL 命令使用 -T 参数:

curl -T uploadfile www.uploadhttp. com/receive.php

伪装成指定的客户端

有些网络资源首先需要判断用户使用的是什么浏览器,符合标准了才能够下载或者浏览。此时curl可以把自己“伪装”成任何其他浏览器:

curl -A "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" URL

这个指令表示 cURL 伪装成了 IE5.0,用户平台是 Windows 2000。

curl -A "Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)" URL

此时 cURL 变成了 Netscape,运行在 PIII 平台的 Linux 上了。

以及更多

正如 cURL 的概念一节所说,cURL 的功能除了请求网页、上传文件和伪装,还包括携带 cookie 访问目标服务器(参数 -b)、访问加密的 HTTP 页面(HTTPS)、用本地证书访问需要证书认证的 HTTP 地址(参数 -E)、授权、断点续传、设置代理与网络限速等等,所有网络上的资源都可以用 cURL 访问和下载到。

在 PHP 中使用 cURL

PHP 支持的由 Daniel Stenberg 创建的 libcurl 库允许我们与各种的服务器使用各种类型的协议进行连接和通讯。

为了使用 cURL 函数你需要安装 cURL 包。PHP 需要我们使用 cURL 7.0.2-beta 或更高版。如果 cURL 的版本低于 7.0.2-beta,PHP 将不工作。

要使用 PHP 的 CURL 支持,我们必须用带有 --with-curl[=DIR] 参数重新编译 PHP ( DIR 是包含库和头文件的目录)。

在之前讲到的命令行下 cURL 的实现,我们不难理解 PHP 中 cURL 函数:首先使用 curl_init() 函数初始化 cURL 会话,而后可以设置有关此次 cURL 过程的所有选项,通过 curl_exec() 函数执行,最后我们可以用 curl_close() 函数来结束当前会话,节省资源。以下是慕课网上有关 PHP 中 cURL 过程的图解。

慕课网:PHP中的数据传输神器cURL

安装 cURL

Mac 下自带的 PHP 环境对 cURL 提供了良好的支持。如果不是 Macintosh,或许这些能有所帮助:

通用 Linux 下的 cURL 安装

获得安装包,从网上直接下载或者其他途径,这里直接 wget

# wget http://curl.haxx.se/download/curl-7.17.1.tar.gz

解压到当前目录并进入

# tar -zxf curl-7.17.1.tar.gz & cd curl-7.17.1

配置,指定安装的目录,这里是 “/usr/local/curl”

# ./configure –prefix=/usr/local/curl

编译并安装

# make  & make install

安装完毕,将 curl 命令加入环境变量中。

# export PATH=$PATH:/usr/local/curl/bin

Ubuntu 小的 cURL 安装

Ubuntu 自带的 apt-get 包管理器可以帮我们解决一切依赖。

sudo apt-get install curl libcurl3 libcurl3-dev php5-curl

然后重启服务器,这里是 apache 服务器。

sudo /etc/init.d/apache2 restart

Windows 下的拓展

在 Windows 下安装好 PHP 后,将PHP文件夹下的三个文件php_curl.dll , libeay32.dll , ssleay32.dll 复制到system32下,再将php.ini (c:WINDOWS 目录下) 中的 ;extension=php_curl.dll 中的分号去掉后,重启服务器即可。

开始实战

这里从简单到较为复杂的小 Demo ,循序渐进。

用 cURL 做一个简单的网页爬虫

将如下 PHP 代码保存为 example1.php,并在命令行中执行。

<?php
    $curl = curl_init("https://www.baidu.com");
    curl_exec($curl);
    curl_close($curl);
?>
php -f example1.php > baidu1.html
open baidu1.html

用 cURL 抓去网页信息并替换部分内容

将如下 PHP 代码保存为 example2.php,并在命令行中执行。

<?php
    $curlobj = curl_init();
    curl_setopt($curlobj, CURLOPT_URL, "http://www.baidu.com");
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, true); // 只是下载页面内容,不直接
打印
    $output = curl_exec($curlobj);
    echo str_replace("百度", "谷歌", $output); // 将“百度”替换为"谷歌"
?>
php -f example2.php > baidu2.html
open baidu2.html

用 cURL 获取天气信息

将如下 PHP 代码保存为 example2.php,并在命令行中执行。

<?php
    $data = "theCityName=西安";
    $curlobj = curl_init();
    curl_setopt($curlobj, CURLOPT_URL, "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName");
    curl_setopt($curlobj, CURLOPT_HEADER, 0); // 不显示 Header
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 只是下载页面内容,不直接打印
    curl_setopt($curlobj, CURLOPT_POST, 1); // 此请求为 post 请求
    curl_setopt($curlobj, CURLOPT_POSTFIELDS, $data); // 传递 post 参数
    curl_setopt($curlobj, CURLOPT_HTTPHEADER, array(
        "application/x-www-form-urlencoded;charset=utf-8",
        "Content-length: ".strlen($data)
        )); // 设置 HTTP Header
    curl_setopt($curlobj, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36'); // 伪造一个 HTTP_USER_AGENT 信息,解决为将对象引用设置到对象的实例问题
    $rtn = curl_exec($curlobj);

    if(!curl_errno($curlobj)) {
        // $info = curl_getinfo($curlobj);
        // print_r($info);
        echo $rtn;
    } else {
        echo 'Curl error: ' . curl_error($curlobj);
    }
?>
php -f example2.php > weather.html
open weather.html

本文介绍了 cURL 的基础知识和 PHP 中 cURL 的基础实战,对于更高阶的用法,尽请期待。

@hylerrix hylerrix changed the title [B11]Vue.js 作者尤大知乎 live 笔记 | 不吹不黑聊聊前端框架 [B05]PHP 中的 cURL 爬虫实战基础 Sep 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant