0

0

PHP如何使用CURL抓取网页_CURL数据抓取详细教程

星夢妙者

星夢妙者

发布时间:2025-09-21 10:56:01

|

1001人浏览过

|

来源于php中文网

原创

使用CURL抓取网页需初始化、设置选项(如URL、User-Agent)、执行请求并处理响应,关键在于模拟浏览器行为以绕过反爬机制,同时注意编码转换与DOM解析数据。

php如何使用curl抓取网页_curl数据抓取详细教程

PHP中使用CURL抓取网页,本质上就是模拟浏览器发送HTTP请求,然后接收服务器返回的数据。这就像你通过浏览器访问一个网站,但这次不是人眼去看,而是代码去“阅读”和处理。它能帮你实现很多自动化任务,比如数据采集、API交互、甚至是测试网站的可访问性。说实话,掌握CURL,就像给你的PHP应用装上了一双能触达互联网任何角落的手。

解决方案

使用PHP的CURL扩展来抓取网页,基本流程可以概括为初始化、设置选项、执行请求、获取结果和关闭会话。下面是一个基础的抓取示例,以及一些你几乎每次都会用到的关键配置。

这个例子展示了最核心的部分。

curl_setopt()
是设置CURL行为的关键函数,它接受一个CURL句柄、一个选项常量和对应的值。不同的选项能让你精细控制请求的各个方面,比如发送POST请求、设置Cookie、自定义HTTP头等等。我个人觉得,
CURLOPT_RETURNTRANSFER
CURLOPT_USERAGENT
是最最基础且不可或缺的两个选项。没有它们,你的抓取可能寸步难行,或者根本无法获取到期望的数据。

CURL抓取网页时常见的挑战与应对策略

说实话,CURL抓取网页这事儿,远不是设置几个参数那么简单。网站的反爬机制花样百出,你总会遇到各种各样的“拦路虎”。

立即学习PHP免费学习笔记(深入)”;

一个非常普遍的问题是User-Agent检测。很多网站会检查你的请求头,如果发现User-Agent是CURL默认的或者看起来不像真实浏览器,它可能直接拒绝你的请求,或者返回一个错误页面。我的经验是,模拟一个主流浏览器的User-Agent字符串是第一步,而且这个字符串最好定期更新,因为网站的反爬策略也在不断进化。

接着是IP限制与封禁。如果你在短时间内对同一个网站发起大量请求,网站的服务器很可能会认为你是一个恶意爬虫,然后直接封禁你的IP地址。这就像你敲别人家门,敲得太频繁,人家肯定不高兴。这时候,请求频率控制就变得至关重要。你得在每次请求之间设置一个合理的延迟,模拟人类的浏览行为。比如,随机延迟1到5秒,或者根据网站的实际负载和反爬强度来调整。如果真的需要大规模抓取,IP轮换是不可避免的,但这需要额外的基础设施支持。

再来就是重定向处理。有些网站在你访问一个URL时,会先重定向到另一个URL,可能是为了负载均衡,也可能是为了用户认证。

CURLOPT_FOLLOWLOCATION
这个选项就是为此而生,它能让CURL自动跟随这些重定向。但有时候,重定向链条太长或者重定向本身有问题,你就需要手动检查
curl_getinfo($ch, CURLINFO_REDIRECT_URL)
来理解发生了什么。

最后,Cookie管理也不容忽视。很多网站的会话状态、登录信息都依赖Cookie。如果你需要抓取需要登录的页面或者在不同请求之间保持会话,就必须学会发送和接收Cookie。你可以使用

CURLOPT_COOKIEJAR
CURLOPT_COOKIEFILE
来保存和加载Cookie,让CURL像浏览器一样管理会话。我发现,有时候手动解析响应头中的
Set-Cookie
,然后手动构建
CURLOPT_COOKIE
字符串,反而能更灵活地处理一些复杂的Cookie场景。

如何处理CURL抓取中的编码问题与数据解析

抓取到的网页内容,尤其是来自不同国家或地区、使用不同技术栈的网站,经常会遇到编码问题。你可能拿到一堆乱码,看起来就像是天书。这通常是因为服务器返回的内容编码(比如GBK、Big5)和你的PHP脚本默认处理的编码(通常是UTF-8)不一致。

处理编码问题,我的首选方法是检测并转换编码。你可以尝试从HTTP响应头中获取

Content-Type
字段,它通常会包含
charset
信息。如果响应头没有明确指出,或者不准确,你可能需要尝试一些启发式的方法,比如使用
mb_detect_encoding()
函数来猜测编码,但这并不总是可靠。

一旦你确定了原始编码,就可以使用

mb_convert_encoding()
函数将其转换为UTF-8。例如:

// 假设 $htmlContent 是抓取到的内容
// 假设我们检测到原始编码是GBK
$originalEncoding = 'GBK'; 
$targetEncoding = 'UTF-8';

// 如果没有明确的编码信息,可以尝试猜测
// $originalEncoding = mb_detect_encoding($htmlContent, array("UTF-8", "GBK", "BIG5", "EUC-CN"), true);
// if ($originalEncoding && $originalEncoding !== $targetEncoding) {
//     $htmlContent = mb_convert_encoding($htmlContent, $targetEncoding, $originalEncoding);
// }

// 明确知道是GBK的情况
if ($originalEncoding !== $targetEncoding) {
    $htmlContent = mb_convert_encoding($htmlContent, $targetEncoding, $originalEncoding);
}

echo $htmlContent; // 现在应该是UTF-8编码了

解决了编码问题,接下来就是数据解析。你拿到的是一整个HTML字符串,而你可能只想要其中的标题、链接或者某个表格数据。

Motiff
Motiff

Motiff是由猿辅导旗下的一款界面设计工具,定位为“AI时代设计工具”

下载

最简单粗暴的方式是正则表达式。对于简单的、结构化的数据,正则表达式确实快速有效。比如抓取所有

标签的
href
属性。

preg_match_all('/]*href=["\']([^"\']*)["\'][^>]*>(.*?)<\/a>/i', $htmlContent, $matches);
print_r($matches[1]); // 所有href属性
print_r($matches[2]); // 所有链接文本

但是,正则表达式在处理复杂、嵌套的HTML结构时,很快就会变得非常脆弱和难以维护。HTML本身就不是为正则匹配设计的。我的建议是,优先使用DOM解析器。PHP内置的

DOMDocument
DOMXPath
是处理HTML和XML的强大工具。虽然它们的API可能看起来有点“学院派”,但一旦你掌握了,你会发现它们在处理复杂结构时无比强大和稳定。

$dom = new DOMDocument();
// 抑制HTML解析错误,因为很多网页HTML不完全符合规范
@$dom->loadHTML($htmlContent); 

$xpath = new DOMXPath($dom);

// 示例:抓取所有h1标签的文本内容
$h1Nodes = $xpath->query('//h1');
foreach ($h1Nodes as $node) {
    echo "H1标题: " . $node->nodeValue . "\n";
}

// 示例:抓取所有class为"product-name"的div标签
$productNames = $xpath->query('//div[@class="product-name"]');
foreach ($productNames as $node) {
    echo "产品名称: " . $node->nodeValue . "\n";
}

使用

DOMDocument
DOMXPath
,你可以通过CSS选择器(需要一些转换,或者使用第三方库如
Symfony/DomCrawler
)或XPath表达式精确地定位到你想要的数据。这比正则匹配要健壮得多,也更符合HTML的结构化特性。

优化CURL抓取性能与避免被封禁的实践

要让CURL抓取既高效又“隐蔽”,这需要一些策略和技巧。毕竟,我们希望在完成任务的同时,不给目标网站带来太大负担,也不至于被直接拉黑。

优化性能,一个显而易见的点是并发请求。如果你需要抓取大量页面,一个接一个地请求效率会很低。PHP的

curl_multi_*
系列函数就是为了解决这个问题而生。它允许你同时管理多个CURL句柄,并行发送请求,大大缩短总的抓取时间。

$urls = [
    "https://www.example.com/page1",
    "https://www.example.com/page2",
    "https://www.example.com/page3",
];

$mh = curl_multi_init();
$chHandles = [];

foreach ($urls as $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 为每个请求设置超时
    curl_multi_add_handle($mh, $ch);
    $chHandles[$url] = $ch;
}

$running = null;
do {
    curl_multi_exec($mh, $running);
    // 可以适当加入usleep()来避免CPU空转
    // usleep(100); 
} while ($running > 0);

foreach ($chHandles as $url => $ch) {
    $response = curl_multi_getcontent($ch);
    if (curl_errno($ch)) {
        echo "抓取 {$url} 失败: " . curl_error($ch) . "\n";
    } else {
        echo "抓取 {$url} 成功,内容长度: " . strlen($response) . "\n";
    }
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}
curl_multi_close($mh);

这段代码展示了如何使用

curl_multi_init()
并行抓取多个URL。这就像你同时打开多个浏览器标签页一样,效率自然更高。

避免被封禁,这才是真正的艺术。除了前面提到的User-Agent和IP轮换,还有几个点值得注意:

尊重

robots.txt
文件。这是网站给爬虫的“君子协议”,它会告诉你哪些页面可以抓取,哪些不可以。虽然CURL本身不会自动遵守,但作为一个负责任的爬虫开发者,你应该在抓取前先解析并遵守它。这不仅是道德问题,也是避免被网站管理员发现并封禁的有效方式。

模拟真实用户行为。除了User-Agent,你还可以设置

Referer
头,模拟用户是从哪个页面点击过来的。甚至可以随机化请求头中的其他信息,比如
Accept-Language
Accept-Encoding
等,让你的请求看起来更像一个真实的浏览器。有时,网站还会检查Cookie和Session,确保你的请求符合一个正常的浏览会话。这意味着你可能需要先访问一个页面来获取必要的Cookie,然后在后续请求中带上它们。

错误处理与重试机制。网络请求总是会遇到各种问题,比如连接超时、服务器错误(5xx)。一个健壮的抓取程序应该能够识别这些错误,并根据错误类型采取不同的策略。例如,对于临时性的网络错误,可以设置一个指数退避(exponential backoff)的重试机制,等待一段时间后再次尝试。但对于永久性的错误(如404),则应直接跳过。

总之,CURL抓取是一个不断学习和调整的过程。没有一劳永逸的方案,你得像个侦探一样,分析目标网站的特点,然后灵活运用CURL的各种功能来达成你的目的。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2680

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1660

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1517

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

952

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1419

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1235

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1488

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1306

2023.11.13

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

12

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号