使用 PHP 进行网络抓取:网络抓取终极指南
索林-加布里埃尔-马里卡(Sorin-Gabriel Marica),2023 年 1 月 14 日
互联网是一个拥有超过 47 亿用户的广阔天地,而且还在不断增长。从这个角度来看,截至 2018 年,地球上有超过 50% 的人口在使用互联网。
当然,更多的用户也意味着更多的数据。现在,互联网已经非常庞大,据估计,仅谷歌、亚马逊、微软和 Facebook 就存储了约 120 万 TB 的数据。
即使是其中的一小部分信息,也能创造出新的商机。有鉴于此,网络搜索的流行也就不足为奇了。
了解网络搜索
互联网的大量数据分散在数十亿个网站上,非常分散。因此,开发人员需要一种收集和处理数据的方法,以便为用户提供新的创新产品。然而,人工收集信息绝对不是一个好主意,因为数据量往往太大,而且数据会不断变化。
解决办法就是自动提取。简而言之,这就是网络搜索的作用。
为什么要搜索数据
信息越多,想法、机会和效益也就越多。一旦处理完毕,这些信息对您或您的客户来说都是无价之宝。以下是一些使用网络搜索的方法:
- 价格比较工具 -通过搜索多个网站,了解某类产品的定价情况。
- 市场调研--了解谁是你最重要的竞争对手以及他们在做什么。
- 机器学习 -为机器学习模型收集训练和测试数据集。
- 任何需要获取大量数据的想法。
例如,一个可能的用例是建立一个营养应用程序,允许用户添加他们的膳食。理想情况下,用户只需打开应用程序,搜索他们吃过的产品,然后将其添加到工具中,并记录之后还能吃多少卡路里。
不过,该工具需要提供一个包含所有可能产品及其营养价值的广泛列表。该列表可通过从多个网站获取营养信息来创建和自动更新。
网络搜索的挑战
虽然网络抓取对使用机器人的人来说非常方便,但有时网站并不乐于分享它们的内容,它们可能会试图阻止你。他们可能会选择以下几种方式:
- 验证码 -任何页面都可以使用验证码,即使没有显示。当您多次请求时,验证码可能会显示出来,从而破坏您的网络搜刮工具。
- IP 屏蔽 -一些网站一旦发现来自您的流量过大,就会选择屏蔽您的 IP。
- 地理限制 -某些内容可能只在特定国家提供,或者当您想了解其他地区的信息时,可能会收到特定地区的数据。
- Javascript -当今的大多数网站都以这样或那样的方式使用 javascript。有些网站可能会动态显示其内容,这就使问题复杂化了,因为页面源与呈现的页面内容并不相同。
要克服这些挑战可能需要大量的工作,但我们还是有办法的。为了帮助您,我们创建了WebscrapingAPI,它可以解决所有这些问题,同时帮助您更快地构建解决方案,减少麻烦。
了解网络
每当互联网用户访问一个网站时,浏览器都会创建一个 HTTP(超文本传输协议)请求。您可以将请求视为从客户端(用户的计算机)到服务器(网站所在的计算机)的信息,其中客户端指定了他想要接收的内容。
每发送一个请求,就会收到一个响应。响应可能是成功的,也可能是错误的,比如著名的 "404 页面未找到错误代码"。网站的内容通常在服务器响应的正文中。

请求和响应都包含一个头部和一个用于交换信息的主体。此外,请求可以有多种方法,最常见的是 GET(访问网页时使用)。这些方法表示客户端想要执行的操作。
例如,在网站上注册或更新密码时,您希望您的数据隐藏在浏览器中,网站可以使用 POST 或 PUT 方法来处理此类请求。
请求头部包含多个属性。让我们来看看最重要的几个:
- Host -服务器的域名。
- User-Agent -发出请求的客户端的详细信息,如浏览器和操作系统。
- Cookie - 一组与客户端相关联的属性。
- Accept -用于接收服务器特定类型(如 text/plain 或 application/json)响应的参数。
不过,请求仅适用于网页。图像、样式和 javascript 代码也有请求,而且与网页无关。按下页面上的 F12 键,选择 "网络 "选项卡并刷新当前页面,就能一目了然地看到谷歌 Chrome 浏览器在访问网页时发出的所有请求。最后你应该会看到类似这样的内容:

了解 PHP
PHP 是用于应用程序后台的最古老、最流行的网络编程语言之一。它从 1995 年开始使用,现在已经是第 8 个版本了。
程序员之所以选择这种编程语言,是因为它的语法简单、运行方便,因为运行 PHP 代码只需要一台安装了 PHP 的机器。此外,由于 PHP 历史悠久,因此有很多资源和支持来解决和调试 PHP 错误。
PHP 也有许多流行的框架和 CMS(内容管理系统)都是基于这种编程语言构建的。著名的例子有 WordPress、Drupal、Magento 和 Laravel。
不过,它也有一些缺点。例如,与Python或Javascript 相比,它更难抓取动态内容。不过,如果你只需要简单页面中的信息,PHP 绝对是一个不错的解决方案,它可以帮助你更轻松地保存或存储搜刮到的数据。
您将需要
目前一切顺利吗?准备好创建你的第一个网络搜索器了吗?在开始之前,你应该有一个运行 PHP 代码的方法。你可以选择安装了 PHP 的 Apache/Nginx 服务器,直接从浏览器运行代码,也可以从命令行运行代码。
让我们使用库来处理搜刮到的内容,让我们的生活更轻松。一些流行的 PHP 搜刮库包括 Goutte、Simple HTML DOM、Panther 和 htmlSQL。或者,您也可以选择使用正则表达式来处理内容。
在本指南中,我们将使用简单 HTML DOM。不过,对于更高级的请求,我们还将使用名为CURL 的 PHP 库。
使用简单的 HTML Dom
Simple HTML Dom 是一个为 PHP 5.6 及以上版本开发的库,它允许我们以更简单的方式访问页面内容--使用选择器。你可以从这里下载该库,也可以阅读相关文档。
在下载链接中的压缩文件中,您只需要simple_html_dom.php文件,并将其放在您编写刮板代码的同一文件夹中。
要在代码中包含该库,只需要这一行代码:
include 'simple_html_dom.php'; // 如果程序库在其他文件夹下,则应 include 'path_to_library/simple_html_dom.php'.
安装 PHP-CURL
虽然并非总是必要,但您需要为更高级的请求发送不同的头信息。使用 PHP-CURL 库会有所帮助。
要在 Ubuntu 机器上安装,可以使用以下命令:
sudo apt-get install php-curl
安装完库后,不要忘记重启 Apache/Nginx 服务器。
制作自己的网络刮刀
现在我们已经掌握了所需的一切,是时候提取数据了!首先,你应该确定要抓取的网站和内容。在本文中,我们将从 IMDB 的 "最高评分电影列表 "中抓取内容。
1.检查网站内容
大多数网页内容都是使用 HTML 显示的。由于我们需要从 HTML 源中提取特定内容,因此也需要了解 HTML 源。我们首先需要检查页面源的外观,以了解要从页面中提取哪些元素。
您可以在 Google Chrome 浏览器中右键单击要提取的元素,然后选择 "检查元素"。这将在浏览器中打开一个窗口,其中包含页面源代码和元素的渲染样式。在这个窗口中,我们唯一需要检查的选项卡是 "元素",它将向我们展示页面的 HTML dom 结构。

例如,在上图中,页面包含一个类为 "chart "和 "full-width "的表格。在这个表格中,每个单元格都有自己的类(posterColumn、titleColumn 等),我们可以使用这些类创建一个选择器。然后,我们就可以只访问所需的数据了。
困惑?别担心,下面的步骤会让你豁然开朗。
2.从 PHP 发送请求
在这种情况下,发送请求基本上意味着用 PHP 代码直接访问页面的 HTML。有两种方法可以做到这一点。
首先,我们可以使用 PHP-CURL 库,它还允许我们修改请求中发送的标题和正文。
<?php
header("Content-Type: text/plain"); // We choose to display the content as plain text
$ch = curl_init("https://www.imdb.com/chart/top/");
curl_setopt($ch, CURLOPT_HEADER, 0);
$response = curl_exec($ch); // Running the request
if (curl_error($ch)) {
echo curl_error($ch); // Displaying possible errors from the request
} else {
echo $response; // Displaying the content of the response
}
curl_close($ch);
?>
另一种方法是使用file_get_contents($url) 方法进行单行处理,但这在某些情况下可能不够充分。要向该请求发送头信息,需要使用用stream_context_create方法创建的上下文。
<?php
header("Content-Type: text/plain"); // We choose to display the content as plain text
echo file_get_contents('https://www.imdb.com/chart/top/'); // We retrieve and display the contents of the response in a single line
?>
您应该根据要制作的刮刀的复杂程度来决定使用哪种方法。
上面的两段代码将显示我们正在搜刮的页面的 HTML 源代码,也就是在检查网站时可见的源代码。我们将使用第一行代码将结果显示为 text/plain。否则,将直接显示为 html。
如果 HTML 结构中存在任何差异,那么网站上就会运行 javascript 代码,并在用户访问网站时更改内容。我们将在本文后面介绍如何处理这种情况。
3.提取数据
从我们选择的页面中,我们将只提取电影的标题和与每部电影相关的评分。如前所述,这些内容显示在一个表格中,其中每个单元格都有自己的类。
利用这一点,我们可以选择提取表格的所有行。然后,我们在每一行中查找我们感兴趣的单元格。
下面的代码就可以做到这一点:
<?php
header("Content-Type: text/plain"); // We choose to display the content as plain text
include 'simple_html_dom.php';
$html_dom = file_get_html('https://www.imdb.com/chart/top/'); // We retrieve the contents using file_get_html from simple_html_dom
$table_rows = $html_dom->find('table.chart tbody tr'); // Getting all of the table rows
foreach($table_rows as $table_row) {
$title_element = $table_row->find('.titleColumn a', 0);
$rating_element = $table_row->find('.ratingColumn strong', 0);
if (!is_null($title_element) && !is_null($rating_element)) { // Checking if the row has a title and a rating column
echo $title_element->innertext . ' has rating ' . $rating_element->innertext . PHP_EOL; // If it does then we print it
}
}
?>
你可以注意到,我们使用了选择器 "table.chart tbody tr"来提取表格的所有行。使用尽可能具体的选择器是个好办法,这样你就能将需要的元素与其他元素区分开来。
检索行后,我们循环浏览这些行,寻找具有titleColumn或ratingColumn 类的元素。如果代码找到了,就会显示它们的 innerText 属性。
需要注意的是,我们在本例中使用了file_get_html ,而不是file_get_contents 。这是因为该函数来自simple_html_dom库,是 file_get_contents函数的封装器。
4.导出数据
在上述示例中,我们收集了网站数据并将其直接显示在屏幕上。不过,您也可以在 PHP 中轻松保存数据。
您可以将搜刮到的数据保存为 .txt 文件、JSON 文件、CSV 文件,甚至直接发送到数据库。PHP 在这方面非常擅长。我们只需将其存储到一个数组中,然后将数组的内容放入一个新文件即可。
<?php
include 'simple_html_dom.php';
$scraped_data = [];
$html_dom = file_get_html('https://www.imdb.com/chart/top/'); // We retrieve the contents using file_get_html from simple_html_dom
$table_rows = $html_dom->find('table.chart tbody tr'); // Getting all of the table rows
foreach($table_rows as $table_row) {
$title_element = $table_row->find('.titleColumn a', 0);
$rating_element = $table_row->find('.ratingColumn strong', 0);
if (!is_null($title_element) && !is_null($rating_element)) { // Checking if the row has a title and a rating column
$scraped_data[] = [
'title' => $title_element->innertext,
'rating' => $rating_element->innertext,
];
}
}
file_put_contents('file.json', json_encode($scraped_data)); // Saving the scraped data in a .json file
// Saving the scraped data as a csv
$csv_file = fopen('file.csv', 'w');
fputcsv($csv_file, array_keys($scraped_data[0]));
foreach ($scraped_data as $row) {
fputcsv($csv_file, array_values($row));
}
fclose($csv_file);
?>
上面的代码采用了我们之前提取的相同内容,并创建了两个文件,一个是 csv 文件,另一个是 json 文件,其中包含了所有评分最高的电影及其评分。
技巧和窍门
1.错误处理
在使用 PHP 编写代码并从随时可能更改的网站上获取数据时,出现错误是很正常的。以下三行代码是用于调试的好帮手,可以放在任何 PHP 脚本的开头:
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
这将帮助您更快地发现代码中的问题,并在必要时更新脚本。
2.在 PHP 请求中设置标头
有时,在发出请求时,您可能还需要发送一些标头。例如,在使用应用程序接口(API)时,可能需要授权令牌,或者希望内容以 JSON 格式而不是纯文本形式发送。你可以用curl和file_get_contents来添加头信息。下面是使用 curl 的方法:
$ch = curl_init("http://httpbin.org/ip");
curl_setopt($ch, CURLOPT_HEADER, [
'accept: application/json'
]);
$response = curl_exec($ch); // 运行请求
而对于 file_get_contents:
$opts = [
"http" => [
"method" => "GET",
"header" => "accept: application/json\r\n"
]
];
$context = stream_context_create($opts);
$result = file_get_contents("http://httpbin.org/ip", false, $context);
3.在 simple_html_dom 中使用 curl 或 file_get_contents
当我们从 IMDB 提取内容时,我们使用了simple_html_dom中的file_get_html函数来抓取。这种方法适用于简单的请求,但不一定适用于更复杂的请求。如果需要发送头信息,最好使用上一条提示中的方法。
要使用它们来代替 file_get_html,只需提取内容,然后使用str_get_html将其转换为 dom 对象,就像这样:
$opts = [
"http" => [
"method" => "GET",
"header" => "accept: text/html\r\n"
]
];
$context = stream_context_create($opts);
$result = file_get_contents("https://www.imdb.com/chart/top/", false, $context);
$html_dom = str_get_html($result);
此外,请注意 simple_html_dom 有一些默认限制(可在 simple_html_dom.php 文件中找到)。例如,网站内容最多可包含 600,000 个字符。如果你想更改这一限制,只需在包含 simple_html_dom 库之前在代码顶端定义即可:
define('MAX_FILE_SIZE', 999999999);
4.抓取动态内容
如果您要抓取动态网站,则需要像浏览器一样访问该网站。否则,您将无法提取实际数据,而只能得到 js 代码。
您需要安装浏览器驱动程序,如 chromium-chromedriver 或 firefox-geckodriver。在 PHP 中提取动态内容是一门更高深的课程,但如果你有兴趣,可以通过阅读黑豹库的文档来尝试一下。
另外,一个简单得多的解决方案是使用 WebScrapingAPI,它可以解决大部分问题。API 通过使用我们的代理网络克服了 IP 屏蔽和验证码问题,同时还能渲染 javascript。其结果是:您可以立即使用先进的刮擦工具,从而减少开发和等待时间。
下面是通过我们的 API 直接在 PHP 中显示https://httpbin.org/ip内容的代码示例:
$content =
file_get_contents("https://api.webscrapingapi.com/v1?pi_key=YOUR_API_KEY&url=". urlencode('https://httpbin.org/ip'));
echo $content;
结论
恭喜您已经完成!您现在应该已经掌握了使用 PHP 创建 Web Scraper 所需的一切。虽然我们在本文中只探讨了 simple_html_dom 库,但您也可以试试其他流行的库,看看哪个更适合您。
请记住,网站是不断变化的,其数据可能会在一夜之间更新。为了解决这个问题,你可以使用更具体的选择器。当然,这并不能保证你的搜刮工具永远有效,但这只是一个开始。这就是网络搜刮工具需要持续、耗时更新的原因。
如果你不想花那么多时间研究和修改代码,可以试试 WebScrapingAPI 免费试用版!
新闻和更新
订阅我们的时事通讯,了解最新的网络搜索指南和新闻。
We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

相关文章

通过我们的深入指南,探索刮擦亚马逊产品数据的复杂性。从最佳实践和亚马逊 Scraper API 等工具到法律注意事项,了解如何应对挑战、绕过验证码并高效提取有价值的见解。




