如何使用PHP进行网页抓取 | 终极教程

PHP 提供了构建网络爬虫所需的各种构建块,尽管它很快就会成为一项日益复杂的任务。方便的是,许多开源库可以使使用 PHP 进行网页抓取变得更容易。

这篇文章将指导您逐步编写各种 PHP 网络抓取例程,您可以使用这些例程从静态和动态网页中提取公共数据。

让我们开始吧!

PHP 可以用于网页抓取吗?

简而言之,是的,它当然可以,并且本文的其余部分将详细介绍网页抓取过程应该是什么样子。然而,询问它作为网络抓取语言是否是一个好的选择是一个完全不同的问题,因为存在许多编程语言替代方案。

请注意,PHP 已经很旧了。它自 90 年代以来就已经存在,并达到了重要的版本 8。然而,这是有利的,因为它使 PHP 成为一种相当易于使用的语言,并且已经解决了数十年的问题/错误。然而,简单性也是有代价的。当涉及复杂的动态网站时,PHP 的性能优于 Python 和 Javascript,但如果您的要求是从简单页面中抓取数据,那么 PHP 是一个不错的选择。

安装前提条件

首先,请保您已安装 PHP 和 Composer。

这里就不在此说明环境了。可以使用各种集成环境,如宝塔,PHPstudy或者其他

下一步是安装所需的库。

发出 HTTP GET 请求

PHP 网页抓取的第一步是加载页面。

在本教程中,我们将使用 books.toscrape.com。该网站是一个用于练习网络抓取的虚拟书店。

当在浏览器中查看网站时,浏览器首先会向 Web 服务器发送 HTTP GET 请求。 要使用 PHP 发送 HTTP GET 请求,可以使用内置函数file_get_contents 。 

此函数可以采用文件路径或 URL 并以字符串形式返回内容。

创建一个新文件并将其另存为 native.php 。在代码编辑器(例如Visual Studio Code)中打开此文件。输入以下代码行来加载 HTML 页面并在终端中打印 HTML:

<?php
    $html = file_get_contents('https://books.toscrape.com/');
    echo $html;

从终端执行此代码,如下所示:

php native.php

执行此命令后,将打印页面的整个 HTML。

到目前为止,很难在 HTML 中定位和提取特定信息。

这就是各种开源第三方库发挥作用的地方。

使用 Goutte 在 PHP 中进行网页抓取

有多种库可用于使用 PHP 进行网页抓取。在本教程中,将使用 Goutte,因为它易于访问、文档齐全且不断更新。尝试最流行的解决方案总是一个好主意。通常,支持内容和预先存在的建议都很丰富。

Goutte 可以处理大多数静态网站。对于动态站点,我们使用 Symfony Panther。

Goutte,发音为goot ,是 Symfony 组件的包装器,例如BrowserKit 、 CssSelector 、 DomCrawler和HTTPClient 。

Symfony 是一组可重用的 PHP 组件。Goutte使用的组件可以直接使用。然而,Goutte 使编写代码变得更容易。

要安装 Goutte,请创建一个要保存源代码的目录。导航到该目录并输入以下命令:

composer init --no-interaction --require="php >=7.1"
composer require fabpot/goutte
composer update

第一个命令将创建composer.json文件。第二个命令将添加 Goutte 条目以及下载和安装所需的文件。它还会创建composer.lock 文件。 

Composer update命令将确保依赖项的所有文件都是最新的。

使用 Goutte 发送 HTTP 请求

使用 Goutte 进行 PHP 网页抓取的最重要的类是充当浏览器的客户端。第一步是创建此类的对象:  

$client = new Client();

然后可以使用该对象发送请求。发送请求的方法称为request 。它需要两个参数——HTTP 方法和目标 URL,并返回 DOM 爬虫对象的实例: 

$crawler = $client->request('GET', 'https://books.toscrape.com');

这会将 GET 请求发送到 HTML 页面。要打印页面的整个 HTML,我们可以调用html() 方法。

将我们迄今为止构建的所有内容放在一起,代码文件如下所示:

<?php

require 'vendor/autoload.php';

use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'https://books.toscrape.com');
echo $crawler->html();

将这个新的 PHP 文件保存为books.php 并从终端运行它。这将打印整个 HTML: 

php books.php

接下来,我们需要一种从页面中定位特定元素的方法。

通过 CSS 选择器定位 HTML 元素

Goutte 使用 Symfony 组件CssSelector 。它有助于使用 CSS 选择器来定位 HTML 元素。 

CSS 选择器可以提供给过滤器方法。例如,要打印页面标题,请在我们正在使用的books.php文件中输入以下行:   

echo $crawler ->过滤器( '标题' ) ->文本();

请注意,title是 从 HTML 中选择<title>节点的 CSS 选择器。  

请记住,在这种特殊情况下,text() 返回 HTML 元素中包含的文本。在前面的示例中,我们使用html() 返回所选元素的整个 HTML。  

如果您更喜欢使用 XPath,请改用filterXPath() 方法。以下代码行产生相同的输出:

echo $crawler -> filterXPath ( '//title' ) -> text ();

现在,让我们继续提取书名和价格。

提取元素

打开在 Chrome 中 https://books.toscrape.com  ,右键单击一本书并选择“检查”。在编写网页抓取代码之前,我们需要首先分析页面的 HTML。

这些书位于 <article> 标签中

通过检查目标网页的 HTML,我们可以看到每本书都包含在一个article 标签中,该标签有一个product_pod 类。在这里,CSS 选择器是.product_pod 。  

在每个文章标签中,完整的书名作为alt属性值位于缩略图中 。书名的 CSS 选择器是.image_container img 。   

最后,图书价格的 CSS 选择器是.price_color 。 

要从此页面获取所有标题和价格,首先,我们需要找到容器,然后运行each循环 。

在此循环中,匿名函数将提取并打印标题和价格,如下所示:

function scrapePage($url, $client){

    $crawler = $client->request('GET', $url);

    $crawler->filter('.product_pod')->each(function ($node) {

            $title = $node->filter('.image_container img')->attr('alt');

            $price = $node->filter('.price_color')->text();

            echo $title . "-" . $price . PHP_EOL;

        });

    }

Web 数据提取的功能被隔离在一个函数中。相同的功能可用于从不同网站提取数据。

处理分页

此时,您的 PHP 网络抓取工具仅从单个 URL 执行数据提取。在现实生活中的网络抓取场景中,会涉及多个页面。

在此特定站点中,分页由“下一个 ”链接(按钮)控制。Next链接的 CSS 选择器 是.next > a 。

在我们之前创建的函数scrapePage中 ,添加以下行: 

try {

    $next_page = $crawler->filter('.next > a')->attr('href');

} catch (InvalidArgumentException) { // 没找到下一页

    return null;

}

return "https://books.toscrape.com/catalogue/" . $next_page;

此代码使用 CSS 选择器来定位“下一步” 按钮并提取href属性的值,返回后续页面的相对 URL。在最后一页上,这行代码将引发InvalidArgumentException 。 

如果找到下一页,该函数将返回其 URL。否则,它将返回null 。

从现在开始,您将使用不同的 URL 启动每个抓取周期。这将使从相对 URL 到绝对 URL 的转换变得更容易。

最后,您可以使用while 循环来调用此函数:

$client = new Client();
$nextUrl = "https://books.toscrape.com/catalogue/page-1.html";
while ($nextUrl) {
    $nextUrl = scrapePage($nextUrl, $client);
}
scrapePage($url, $client);

网页抓取代码已基本完成。

将数据写入 CSV 文件

PHP 网络抓取过程的最后一步是将数据导出到存储。PHP 的内置fputcsv 函数可用于将数据导出到 CSV 文件。

首先,以写入或追加模式打开 CSV 文件,并将文件句柄存储在变量中。

接下来,将变量发送到scrapePage 函数。然后,为每本书调用fputcsv 函数,将标题和价格写在一行中。  

最后,在while循环之后,通过调用fclose 关闭文件。 

最终的代码文件如下:

function scrapePage($url, $client, $file)

{

    $crawler = $client->request('GET', $url);

    $crawler->filter('.product_pod')->each(function ($node) use ($file) {

        $title = $node->filter('.image_container img')->attr('alt');

        $price = $node->filter('.price_color')->text();

        fputcsv($file, [$title, $price]);

    });

    try {

        $next_page = $crawler->filter('.next > a')->attr('href');

    } catch (InvalidArgumentException) { //Next page not found

        return null;

    }

    return "https://books.toscrape.com/catalogue/" . $next_page;

}


$client = new Client();

$file = fopen("books.csv", "a");

$nextUrl = "https://books.toscrape.com/catalogue/page-1.html";


while ($nextUrl) {

    echo "<h2>" . $nextUrl . "</h2>" . PHP_EOL;

    $nextUrl = scrapePage($nextUrl, $client, $file);

}

fclose($file);

从终端运行此文件,也可以直接浏览器环境访问:

php books.php

这将创建一个 包含 1,000 行数据的books.csv文件

使用 Guzzle、XML 和 XPath 进行网页抓取

Guzzle 是一个 PHP 库,它向网页发送 HTTP 请求以获得响应。换句话说,Guzzle 是一个可用于抓取数据的 PHP HTTP 客户端。请注意,在使用网页之前,您需要了解另外两个概念:XML 和 XPath。

XML 代表可扩展标记语言。它将用于创建用于存储结构化数据的文件。然后可以传输这些文件并构建数据。

存在读取 XML 文件的问题,这就是 XPath 发挥作用的地方。

XPath 代表 XML Path,用于导航和选择 XML 节点。

HTML 文件与 XML 文件非常相似。在某些情况下,您可能需要解析器来调整细微差别并使 HTML 至少在一定程度上符合 XML 文件标准。有些解析器甚至可以读取格式很差的 XML。

无论如何,解析器都会进行必要的 HTML 修改,以便您可以使用 XPath 来查询和导航 HTML。

设置 Guzzle 项目

要安装 Guzzle,请创建一个要保存源代码的目录。导航到该目录并输入以下命令:

composer init --no-interaction --require="php >=7.1"
composer require guzzlehttp/guzzle

除了 Guzzle 之外,我们还可以使用一个解析 HTML 代码的库。有许多可用的 PHP 库,例如简单的 HTML dom 解析器和 Symphony DOMCrawler。

在本教程中,选择 Symphony DOMCrawler。它的语法与 Goutte 非常相似,您将能够应用本节中已经了解的内容。

DomCrawler 优于简单 HTML dom 解析器的另一点是,它很好地支持处理无效的 HTML 代码。那么,让我们开始吧。

使用以下命令安装 DOMCrawler:

composer require symfony/dom-crawler

这些命令将下载所有必需的文件。下一步是创建一个新文件并将其另存为scraper.php 。

使用 Guzzle 发送 HTTP 请求

与 Goutte 类似,Guzzle 最重要的类是 Client。首先创建一个新文件 scraper.php 并输入以下 PHP 代码行:

<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

use Symfony\Component\DomCrawler\Crawler;

现在我们准备创建 Client 类的对象:

$client = new Client();

然后您可以使用客户端对象发送请求。发送请求的方法方便地称为请求。它需要两个参数——HTTP 方法和目标 URL,并返回响应:

$response = $client->request('GET', 'https://books.toscrape.com&amp');

从这个响应中,我们可以提取网页的 HTML,如下所示:

$html = $response->getBody()->getContents();
echo $html

请注意,在此示例中,响应包含 HTML 代码。如果您正在使用返回 JSON 的网页,则可以将 JSON 保存到文件并停止脚本。仅当响应包含 HTML 或 XML 数据时,下一部分才适用。

接下来,DomCrawler 将用于从此网页中提取特定元素。

通过 XPath 定位 HTML 元素

导入 Crawler 类并创建 Crawler 类的实例,如以下 PHP 代码片段所示:

use Symfony\Component\DomCrawler\Crawler;

我们可以创建一个爬虫类的实例,如下所示:

$crawler = new Crawler($html);

现在我们可以使用filterXPath 方法来提取任何XML 节点。例如,以下行仅打印页面标题: 

echo $crawler->filterXPath('//title')->text();

关于 XML 节点的简要说明:在 XML 中,一切都是节点——元素是节点,属性是节点,文本也是节点。filterXPath方法返回一个 节点。因此,要从元素中提取文本,即使您使用XPath 中的text() 函数,您仍然必须调用 text() 方法将文本提取为字符串。

换句话说,以下两行代码将返回相同的值:

echo $crawler->filterXPath('//title')->text();
echo $crawler->filterXPath('//title/text()')->text();

现在,让我们继续提取书名和价格。

提取元素

在编写网页抓取代码之前,让我们首先分析页面的 HTML。

打开网页在 Chrome 中 https://books.toscrape.com  ,右键单击一本书并选择Inspect 。

这些书籍位于 <article> 元素中,其 class 属性设置为product_pod。选择这些节点的 XPath 如下:

// [@class="product_pod"]

在每个文章标签中,完整的书名作为 alt 属性值位于缩略图中。书名和书价的 XPath 如下:

//[@class="image_container"]/a/img/@alt
//[@class="price_color"]/text()

要从此页面获取所有标题和价格,您首先需要找到容器,然后使用循环获取包含所需数据的每个元素。

在此循环中,匿名函数将提取并打印标题和价格,如以下 PHP 代码片段所示:

$crawler->filterXpath('//[@class="product_pod"]')->each(function ($node) {

    $title = $node->filterXpath('.//[@class="image_container"]/a/img/@alt')->text();
    
    $price = $node->filterXPath('.//[@class="price_color"]/text()')->text();
    
    echo $title . "-" . $price . PHP_EOL;

});

这是如何使用 Guzzle 或 DOMCrawler 解析器从任何页面抓取数据的简单演示。请注意,此方法不适用于动态网站。这些网站使用 DOMCrawler 无法处理的 JavaScript 代码。在这种情况下,您需要使用 Symphony Panther。

提取数据后的下一步是保存它。

将提取的数据保存到文件中

要存储提取的数据,您可以更改脚本以使用内置 PHP 并创建 CSV 文件。

将以下 PHP 代码片段编写如下:

$file = fopen("books.csv", "a");

$crawler->filterXpath('//[@class="product_pod"]')->each(function ($node) use ($file) {

$title = $node->filterXpath('.//[@class="image_container"]/a/img/@alt')->text();

$price = $node->filterXPath('.//*[@class="price_color"]/text()')->text();

fputcsv($file, [$title, $price]);

});

fclose($file);

此代码片段在运行时会将所有数据保存到books.csv文件中。

使用 Symfony Panther 进行网页抓取

动态网站使用 JavaScript 来呈现内容。对于此类网站,Goutte 不是合适的选择。

对于这些网站,解决方案是使用浏览器来呈现页面。它可以使用 Symfony 的另一个组件 – Panther来完成。Panther 是一个独立的 PHP 库,用于使用真实浏览器进行网页抓取。

在本节中,我们从Quotes.toscrape.com中抓取引用和作者。这是一个用于学习抓取动态网页基础知识的虚拟网站。

安装 Panther 及其依赖项

要安装 Panther,请打开终端,导航到将存储源代码的目录,然后运行以下命令:

composer init --no-interaction --require="php >=7.1" 
composer require symfony/panther
composer update

这些命令将创建一个新的composer.json文件并安装Symfony/Panther。 

另外两个依赖项是浏览器和驱动程序。常见的浏览器选择是 Chrome 和 Firefox。您很可能已经安装了这些浏览器之一。

可以使用任何包管理器下载浏览器的驱动程序。

在 Windows 上,运行:

choco install chromedriver

在 macOS 上,运行:

brew install chromedriver

使用 Panther 发送 HTTP 请求

Panther 使用Client 类公开get() 方法。此方法可用于加载 URL,或者换句话说,发送 HTTP 请求。

第一步是创建 Chrome客户端。创建一个新的 PHP 文件并输入以下代码行: 

<?php

require 'vendor/autoload.php';

use \Symfony\Component\Panther\Client;

$client = Client::createChromeClient();

然后可以使用$client对象 加载网页:

$client->get('https://quotes.toscrape.com/js/&amp;#39;);

此行将在无头 Chrome 浏览器中加载页面。

通过 CSS 选择器定位 HTML 元素

要定位元素,首先,您需要获取 爬虫 对象的引用。获取对象的最佳方法是使用waitFor()方法等待页面上的特定元素 。它将 CSS 选择器作为参数:

$crawler = $client->waitFor('.quote');

该代码行等待带有此选择器的元素变得可用,然后返回爬虫的实例。

其余代码与 Goutte 类似,因为两者都使用 Symfony 的相同CssSelector 组件。

引用的容器 HTML 元素

首先, CSS 选择器提供 过滤方法来获取所有引用元素。然后,为每个引用提供匿名函数以提取作者和文本:

$crawler->filter('.quote')->each(function ($node) {

        $author = $node->filter('.author')->text();

        $quote = $node->filter('.text')->text();

       echo $autor." - ".$quote

    });

处理分页

要从本网站的所有后续页面中抓取数据,您只需单击“下一步” 按钮即可。要单击链接, 可以使用clickLink()方法。此方法直接作用于链接文本。


文章来源地址https://www.toymoban.com/diary/php/485.html

在最后一页上,链接不会出现,调用此方法将引发异常。这可以通过使用 try-catch 块来处理:

while (true) {

    $crawler = $client->waitFor('.quote');

…

    try {

        $client->clickLink('Next');

    } catch (Exception) {

        break;

    }

}

将数据写入 CSV 文件

使用 PHP 的fputcsv()函数将数据写入 CSV 非常简单 。在while循环之前打开 CSV 文件,使用fputcsv()函数 写入每一行 ,并在循环之后关闭文件。

这是最终的代码:

$file = fopen("quotes.csv", "a");

while (true) {

    $crawler = $client->waitFor('.quote');

    $crawler->filter('.quote')->each(function ($node) use ($file) {

        $author = $node->filter('.author')->text();

        $quote = $node->filter('.text')->text();

        fputcsv($file, [$author, $quote]);

    });

    try {

        $client->clickLink('Next');

    } catch (Exception) {

        break;

    }

}

fclose($file);

执行此 PHP 脚本中包含的网络抓取工具后,您将获得一个quotes.csv 文件,其中包含所有引言和作者,可供进一步分析。

结论

在使用 Goutte 处理大多数静态网页时,您不应该遇到重大问题,因为这个流行的库提供了足够的功能和广泛的文档。然而,如果典型的 HTML 提取方法无法胜任动态元素发挥作用时的任务,那么 Symfony Panther 是处理更复杂负载的正确方法。

如果您正在使用使用 Laravel、Code Igniter 或纯 PHP 开发的网站,那么直接用 PHP 编写网页抓取部分可能非常有用,例如,在创建您自己的 WordPress 插件时。由于 PHP 也是一种脚本语言,因此即使不打算将其部署到网站,您也可以编写 Web 抓取代码。


到此这篇关于如何使用PHP进行网页抓取 | 终极教程的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

原文地址:https://www.toymoban.com/diary/php/485.html

如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用
使用 Golang 构建实时通知系统 - 分步通知系统设计指南
上一篇 2023年10月29日 14:04
下一篇 2023年10月31日 01:45

相关文章

  • 如何使用Python的Selenium库进行网页抓取和JSON解析

    随着互联网的快速发展,网页抓取和数据解析在许多行业中变得越来越重要。无论是电子商务、金融、社交媒体还是市场调研,都需要从网页中获取数据并进行分析。Python的Selenium库作为一种自动化测试工具,已经成为许多开发者的首选,因为它提供了强大的功能和灵活性。

    2024年02月10日
    浏览(23)
  • 如何使用 Python 爬虫抓取动态网页数据

    随着 Web 技术的不断发展,越来越多的网站采用了动态网页技术,这使得传统的静态网页爬虫变得无能为力。本文将介绍如何使用 Python 爬虫抓取动态网页数据,包括分析动态网页、模拟用户行为、使用 Selenium 等技术。 在进行动态网页爬取之前,我们需要先了解动态网页和静

    2023年04月24日
    浏览(24)
  • 如何使用Puppeteer进行金融数据抓取和预测

    Puppeteer是一个基于Node.js的库,可以用来控制Chrome或Chromium浏览器,实现网页操作、截图、PDF生成等功能。本文将介绍如何使用Puppeteer进行金融数据抓取和预测,以及如何使用亿牛云爬虫代理提高爬虫效果。 金融数据抓取是指从网上获取金融相关的数据,如股票、基金、期货、

    2024年02月09日
    浏览(22)
  • 如何使用Puppeteer进行新闻网站数据抓取和聚合

    Puppeteer是一个基于Node.js的库,它提供了一个高级的API来控制Chrome或Chromium浏览器。通过Puppeteer,我们可以实现各种自动化任务,如网页截图、PDF生成、表单填写、网络监控等。本文将介绍如何使用Puppeteer进行新闻网站数据抓取和聚合,以网易新闻和杭州亚运会为例。 数据抓取

    2024年02月10日
    浏览(25)
  • 大数据企业如何使用IP代理进行数据抓取

    目录 一、引言 二、IP代理概述 三、为什么大数据企业需要使用IP代理 四、使用IP代理进行数据抓取的步骤 1、获取可用的代理IP 2、配置代理IP 3、设置请求头部信息 4、开始数据抓取 5、错误处理和重试 五、IP代理的注意事项 六、总结 随着互联网的快速发展,大数据已经成为

    2024年02月02日
    浏览(36)
  • 如何使用PHP开发网页定时刷新功能

    如何使用PHP开发网页定时刷新功能 随着互联网的发展,越来越多的网站需要实时更新显示数据。而实时刷新页面是一种常见的需求,它可以让用户在不刷新整个页面的情况下获得最新的数据。本文将介绍如何使用PHP开发网页定时刷新功能,并提供代码示例。 1.使用Meta标签定

    2024年02月12日
    浏览(24)
  • 如何抓取网页数据

    如何抓取网页数据,每当我们在网上找到自己想到的数据,都需要复制粘贴或下载然后一步一步地整理。 今天教大家如何快速地免费获取网页数据信息,只需要输入域名点选你需要的数据,软件全自动抓取。支持导出各种格式并且已整理归类。详细参考图片教程。 SEO是一种

    2023年04月15日
    浏览(24)
  • 7种有效安全的网页抓取方法,如何避免被禁止?

    网页抓取是一种从互联网上抓取网页内容的过程,但在网络抓取种相信您也经常遇到障碍?尤其是做跨境业务的,在抓取国外的网站时更有难度。但我们站在您的立场上,提供七种有效的方法来进行网页抓取而不被阻止,最大限度地降低网站禁令的风险,并帮助您应对相关风

    2024年02月14日
    浏览(19)
  • 使用Selenium抓取网页动态内容

    Selenium 是一个自动化测试工具,支持多种浏览器,包括 Chrome、Firefox、Edge 等,具有强大的浏览器自动化能力,可以用于Web应用程序的自动化测试、数据挖掘等领域。Selenium的主要特点有: 支持多种浏览器 Selenium支持多种浏览器,包括Chrome、Firefox、Edge、Safari等,可以满足不同

    2023年04月25日
    浏览(30)
  • ElasticSearch与PHP的集成:如何使用PHP与ElasticSearch进行交互

    Elasticsearch是一个基于Lucene库的搜索引擎,它提供了实时、可扩展和可伸缩的搜索功能。它通常用于构建实时搜索、分析和数据可视化应用程序。PHP是一种广泛使用的服务器端脚本语言,它可以与Elasticsearch集成以实现高效的搜索功能。 在本文中,我们将讨论如何使用PHP与Ela

    2024年02月22日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包