使用 PHP 进行网络抓取:逐步教程
在本指南中,我将指导你使用 PHP 创建一个简单的网络搜刮器。如果你是新手,也不用担心;我会一步一步来。到最后,你将知道如何从网站上获取数据并将其存储到文件中,以备将来使用。让我们开始吧!
什么是网络抓取?
网络抓取 是通过从网站的 HTML 结构中提取有用信息来获取数据的过程。它允许开发人员从没有提供应用程序接口或应用程序接口不足以满足特定用例的数据源访问数据。
例如,您可能想从电子商务网站上抓取产品价格、描述或图片。这些数据可用于比较、分析,或只是存储起来以备后用。
为什么使用 PHP 进行网络抓取?
虽然 Python 和 JavaScript 有许多刮库,如 ScrapyPHP、BeautifulSoup 和 Puppeteer 也擅长网络刮擦,原因有几个:
- 简单设置:PHP 易于设置,不像其他编程语言那样需要额外安装。
- 内置工具:PHP 提供了 cURL,这是一个内置的 HTTP 请求库,对于网络搜索来说是必不可少的。
- HTML 解析:PHP 提供了简单 HTML DOM 解析器等库,可轻松提取和处理 HTML 数据。
- 广泛可用性:PHP 常用于许多主机平台,因此无需特殊权限或服务器配置,就能方便地执行网络搜索任务。
阅读我关于 最佳 PHP 网络搜索库.
利用高级代理
有时,网络搜索会遇到一些障碍,例如 IP 屏蔽 或验证码。当出现这种情况时,集成高级代理服务可以保证您的搜刮器顺利运行。 Bright Data 的代理解决方案 提供自动 IP 轮换和智能功能,帮助绕过反僵尸措施。这意味着您可以专注于使用 PHP 提取和分析数据,而不必受困于连接问题。
查看我的 用于网络搜刮的最佳代理提供商.
现在,让我们来了解一下如何使用 PHP 设置您的第一个网络搜刮器。
步骤 1:设置 PHP 环境
要开始使用 PHP 进行网络搜刮,您需要具备以下条件:
- PHP: 从官方网站或通过软件包管理器安装最新版本的 PHP(8.3 或以上)。
- IDE: 使用任何集成开发环境,但我们推荐使用 Visual Studio Code,因为它易于使用,并提供丰富的扩展支持。如果你想要一个专门为网络搜索而设计的集成开发环境,可以试试 此工具.
- 图书馆 您需要使用 Simple HTML DOM Parser 和 cURL(PHP 已预装)来发出 HTTP 请求和解析 HTML 内容。
安装 PHP 和所需库函数
- 从以下网址下载并安装 PHP PHP 官方网站.
- 对于 Windows,您可以使用 XAMPP 或 WAMP 等工具,它们为 PHP 开发提供了易于使用的环境。
- 下载 简单的 HTML DOM 分析器 from SourceForge 并将其添加到项目文件夹中。
设置好 PHP 和所需的库后,项目目录应该如下所示:
/web-scraping-project
├── scraper.php
└── simple_html_dom.php
第 2 步:使用 cURL 发送 HTTP 请求
要从网站上抓取数据,首先需要向网站服务器发送 HTTP 请求。PHP 的 cURL 库非常适合做这件事。下面介绍如何使用 cURL 获取网页的 HTML 内容。
基本 cURL 请求示例
<?php
// 您要搜索的网站的 URL
$url = "https://example.com";
// 初始化 cURL 会话
$curl = curl_init();
// 设置 cURL 选项
curl_setopt($curl, CURLOPT_URL、 $url); // 指定 URL
curl_setopt($curl, curlopt_returntransfer、 true); // 以字符串形式返回响应
curl_setopt($curl, curlopt_followlocation、 true); // 跟踪重定向
// 执行 cURL 会话
$htmlContent = curl_exec($curl);
// 检查错误
if ($htmlContent === false) {
echo "Error: " . curl_error($curl);
出口;
}
// 关闭 cURL 会话
curl_close($curl);
// 输出获取的 HTML 内容
echo $htmlContent;
?>
这段代码会向 https://example.com 并打印原始 HTML 响应。这就是网络搜索的第一步:获取所需数据。
步骤 3:解析 HTML 内容
获取原始 HTML 后,下一步就是对其进行解析并提取所需信息。PHP 没有内置的 HTML 解析功能,但简单 HTML DOM 解析器可以轻松完成这项工作。
让我们使用这个库从网页中提取数据。首先在脚本中加入该库,然后使用其函数来浏览 HTML 结构。
使用简单的 HTML DOM 分析器提取数据
<?php
// 加入简单 HTML DOM 解析器库
include_once('simple_html_dom.php'(简体中文);
// 使用 cURL 获取 HTML 内容(如前所述)
$htmlContent = file_get_contents('https://example.com');
// 创建一个简单的 HTML DOM 对象
$html = str_get_html($htmlContent);
// 使用 CSS 选择器提取数据
$title = $html->find('title', 0)->纯文本; // 提取页面标题
$heading = $html->find('h1', 0)->纯文本; // 提取第一个 h1 标记
// 输出提取的数据
echo "页面标题: $title\n";
echo "标题: $heading\n";
?>
在本例中,我们从网页中提取标题和第一个标题 (h1)。Simple HTML DOM Parser 中的查找方法与 jQuery 的工作原理类似,您可以通过 CSS 选择器来提取特定元素。
步骤 4:搜索多个项目
在大多数情况下,你需要提取的不仅仅是一条数据。让我们扩展前面的示例,抓取多个项目。我们将从一个电子商务网站抓取产品数据(名称、价格和图片 URL)。
搜索多个产品
<?php
// 包括简单 HTML DOM 解析器
include_once('simple_html_dom.php'(简体中文);
// 电子商务网站的 URL
$url = 'https://example.com/products';
// 使用 cURL 获取 HTML 内容
$htmlContent = file_get_contents($url);
// 创建一个简单的 HTML DOM 对象
$html = str_get_html($htmlContent);
// 查找所有产品容器
$ 产品 = $html->find('.product'); // 为产品项目使用适当的 CSS 选择器
// 循环浏览每个产品并提取数据
foreach ($ 产品 as $ 产品) {
$name = $ 产品->find('.product-title', 0)->纯文本;
$price = $ 产品->find('.product-price', 0)->纯文本;
$image = $ 产品->find(图像, 0)->源文件;
// 输出提取的产品信息
echo "Product: $name\n";
echo "价格 $price\n";
echo "图像 URL: $image\n";
echo " - - - - - - - - - - - -\n";
}
?>
在这里,我们使用 .product 选择器查找页面上的每个产品,然后提取每个产品的名称、价格和图片 URL。您可以根据所搜索网站的实际结构调整 CSS 选择器。
步骤 5:在 CSV 文件中存储数据
提取数据后,您可能希望将其保存起来以备后用。常用的方法是将数据导出为 CSV 文件。PHP 有处理 CSV 文件的内置函数,因此可以很容易地做到这一点。
将数据导出为 CSV
<?php
// 产品数据扫描数组
$productData = [
[名称 => 产品 1, 'Price' => '$10.00', 图像 URL => 'https://example.com/image1.jpg'],
[名称 => 产品 2, 'Price' => '$20.00', 图像 URL => 'https://example.com/image2.jpg'],
];
// 指定 CSV 文件的路径
$csvFilePath = 'products.csv';
// 打开 CSV 文件以便写入
$file = fopen($csvFilePath, 'w');
// 编写列标题
fputcsv($file, 数组键($productData[0]));
// 将每个产品的数据写入 CSV 文件
foreach ($productData as $ 产品) {
fputcsv($file, $ 产品);
}
// 关闭 CSV 文件
fclose($file);
// 输出成功信息
echo "CSV 文件创建成功: $csvFilePath\n";
?>
该代码从数组中获取产品数据并将其写入 CSV 文件。数据 fputcsv 函数 用于将每一行数据写入文件。运行脚本后,您将得到一个包含刮擦信息的 products.csv 文件。
步骤 6:处理错误和改进刮刀
上述示例涵盖了网络搜刮的基本要素,而现实世界中的搜刮通常涉及更复杂的任务,如处理错误、处理验证码、尊重 robots.txt 以及搜刮大量数据。
下面是一些补充提示:
- 错误处理:经常检查 cURL 请求中的错误,并妥善处理。
- 尊重 Robots.txt:网站的 robots.txt 文件中可能有防止刮擦的规则。请务必检查并遵守这些规则。
- 速率限制:避免在短时间内发送过多请求,以免被阻止。您可以使用 PHP 中的 sleep() 增加请求之间的延迟。
- User-Agent:有些网站会阻止来自非浏览器客户端的请求。设置一个 User-Agent 标头来模拟网络浏览器。
curl_setopt($curl, curlopt_useragent、 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36');
使用 PHP 的高级网络抓取技术
从网站上抓取大量数据需要的不仅仅是基本的抓取技术。要想高效、大规模地抓取数据,您需要采用先进的方法,包括网络抓取、处理动态内容和规避反僵尸保护。让我们来探讨如何用 PHP 来应对这些挑战。
1.使用 PHP 进行网络抓取
网络爬行是指系统地浏览网站的所有页面并从每个页面中提取所需数据的过程。对于内容分散在多个页面的分页网站,网络爬虫是必不可少的。
你在前几节中创建的刮擦器可以从单个页面中提取数据。现在,让我们通过抓取网站上的所有页面并从每个页面中抓取数据来增强它。
步骤 1:检查分页机制
开始之前,先确定网站如何处理分页。大多数情况下,分页链接由 HTML 元素提供,如 "下一页 "按钮或一系列页码。通过检查页面的 HTML,您可以找到指向下一页的链接,并利用它进一步抓取。
步骤 2:实施网络抓取
让我们修改之前的抓取器,以抓取分页内容。
<?php
include_once("simple_html_dom.php");
$url = "https://scrapingcourse.com/ecommerce/";
$productData = 矩阵();
function 刮刀($url) {
echo "扫描页面: $url\n";
// 初始化 cURL 会话
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL、 $url);
curl_setopt($curl, curlopt_returntransfer、 true);
curl_setopt($curl, curlopt_followlocation、 true);
curl_setopt($curl, curlopt_ssl_verifypeer、 false);
$htmlContent = curl_exec($curl);
if ($htmlContent === false) {
$error = curl_error($curl);
echo "cURL 错误:" . $error;
出口;
}
curl_close($curl);
// 解析 HTML 内容
$html = str_get_html($htmlContent);
$ 产品 = $html->find(".产品");
foreach ($ 产品 as $ 产品) {
$name = $ 产品->find(".woocommerce-loop-产品__标题", 0);
$image = $ 产品->find("img", 0);
$price = $ 产品->find("span.price", 0);
if ($name && $price && $image) {
$decodedPrice = html_entity_decode($price->plaintext);
$ 产品信息 = 矩阵(
"姓名" => $name->plaintext、
"Price" => $decodedPrice,
"图像 URL" => $image->src
);
全球 $productData;
$productData[] = $ 产品信息;
}
}
// 查找 "下一页 "链接
$nextPageLink = $html->find("a.下一个", 0);
if ($nextPageLink) {
$nextPageUrl = $nextPageLink->href;
刮刀($nextPageUrl); // 递归刮取下一页
}
}
// 从第一页开始扫描
刮刀($url);
// 输出收集到的数据
打印($productData);
?>
该脚本使用 cURL 抓取 HTML 内容,使用简单 HTML DOM 解析器进行解析,并查找产品数据(名称、价格和图片 URL)。然后,它会查找 "下一页 "链接,递归搜索所有页面,直到没有更多链接为止。
2.用 PHP 处理动态内容
有些网站在初次加载页面后使用 JavaScript 动态加载内容。简单的 HTML DOM 解析器无法处理此类网站,因为它只能处理静态 HTML。对于动态内容,我们需要像 Selenium 这样可以呈现 JavaScript 的无头浏览器。
步骤 1:在 PHP 中使用 Selenium
Selenium 允许你通过程序控制浏览器来模拟真实用户。对于 PHP,您可以使用 php-webdriver 软件包与 Selenium WebDriver 进行交互。
要在 PHP 中设置 Selenium,请按以下步骤操作:
安装 Composer (如果尚未安装)。
为 PHP 安装 Selenium WebDriver 使用作曲家
composer require php-webdriver/webdriver
composer require symfony/css-selector
下载 Selenium 服务器 并在本地启动它:
java -jar selenium-server-.jar standalone - selenium-manager true
第 2 步:使用 Selenium 实施动态抓取
下面介绍如何使用 Selenium 从动态加载的页面中抓取数据:
<?php
namespace Facebook\WebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Chrome\ChromeOptions;
require_once("vendor/autoload.php");
$host = "http://localhost:4444/"; // 本地 Selenium 服务器
$capabilities = DesiredCapabilities::chrome();
$chromeOptions = new ChromeOptions();
$chromeOptions->addArguments([" - headless"]); // 在无头模式下运行 Chrome 浏览器
$capabilities->setCapability(ChromeOptions::CAPABILITY_W3C, $chromeOptions);
$driver = RemoteWebDriver::create($host, $capabilities);
function 刮刀($driver) {
$driver->管理()->window()->最大化();
$ 产品 = $driver->findElements(WebDriverBy::cssSelector(".产品容器"));
foreach ($ 产品 as $ 产品) {
$name = $ 产品->findElement(WebDriverBy::cssSelector(".产品名称"))->getText();
$price = $ 产品->findElement(WebDriverBy::cssSelector(".产品价格"))->getText();
$image_url = $ 产品->findElement(WebDriverBy::cssSelector("img"))->获取属性("src");
echo "姓名: $name\n";
echo "价格 $price\n";
echo "图像 URL: $image_url\n";
}
}
// 打开目标页面
$driver->get("https://www.scrapingcourse.com/infinite-scrolling");
$lastHeight = $driver->executeScript("返回 document.body.scrollHeight");
while (true) {
$driver->executeScript("window.scrollTo(0,document.body.scrollHeight);");
sleep(2);
$newHeight = $driver->executeScript("返回 document.body.scrollHeight");
if ($newHeight == $lastHeight) {
刮刀($driver);
break;
}
$lastHeight = $newHeight;
}
// 关闭浏览器
$driver->quit();
?>
在这段代码中,我们使用 Selenium 打开网页、滚动网页并提取由 JavaScript 动态呈现的数据。在滚动到页面底部并确保所有内容都已加载后,刮擦器会提取产品名称、价格和图片 URL。
3.使用 PHP 抓取时避免阻塞
许多网站都采用了 IP 拦截、验证码或速率限制等反机器人措施来防止刮擦。要绕过这些措施,我们可以使用 IP 轮换和模仿合法用户行为等技术。
步骤 1:使用代理服务器避免检测
避免被拦截的一个有效方法是使用代理。每次请求时轮流使用代理服务器,可以避免触发反僵尸系统标记来自同一 IP 的多个请求。
您可以使用 Bright Data 等服务,这些服务提供自动代理轮换,并绕过验证码和 JavaScript 挑战等反僵尸系统。
步骤 2:模仿合法用户
另一种避免被检测的方法是模仿真实浏览器的标头。例如,你可以设置 User-Agent 标头来冒充真正的浏览器,如 Chrome 或 Firefox。
下面是一个示例,说明如何将自定义 User-Agent 标头添加到您的 scraper 中:
<?php
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL、 "https://www.example.com");
curl_setopt($curl, curlopt_returntransfer、 true);
curl_setopt($curl, curlopt_followlocation、 true);
curl_setopt($curl, curlopt_ssl_verifypeer、 false);
// 设置自定义用户代理,以模拟真实浏览器
curl_setopt($curl, curlopt_useragent、 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");
$htmlContent = curl_exec($curl);
curl_close($curl);
echo $htmlContent;
?>
步骤 3:使用网络抓取 API
对于更高级的反僵尸保护(如 Cloudflare 或 Akamai),您可能需要使用 Bright Data 这样的专用网络搜刮 API。它可以自动处理代理轮换、绕过验证码和 JavaScript 渲染等问题,即使是最具挑战性的网站也能更轻松地进行搜刮。
<?php
$apiUrl = "https://api.Bright Data.com/v1/?apikey=&url=" . urlencode("https://www.example.com");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL、 $apiUrl);
curl_setopt($ch, curlopt_returntransfer、 true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
结论
Bright Data 可将整个搜索过程自动化,让您专注于数据提取,而不是处理拦截器。
使用 PHP 进行网络抓取是一种从网站中提取数据的强大方法,而 cURL 和 Simple HTML DOM Parser 的组合使这一过程变得简单而有效。无论您是要抓取产品数据、新闻文章还是社交媒体提要,PHP 都能轻松完成任务。
刮擦网站时,请注意法律和道德问题,包括尊重网站的 robots.txt 文件和服务条款。能力越大,责任越大!