本文教你从零搭建ThinkPHP采集环境并完成首次网页抓取:安装框架、验证服务、创建控制器、用cURL发HTTP请求、处理gzip压缩、正则提取标题,全程跳过理论直接跑通。

想用ThinkPHP写一个网页采集脚本,但连框架都没装好、连第一个HTTP请求都发不出去?这篇文章带你从零开始,跳过所有冗余概念,直接完成一次真实页面的抓取——不讲MVC原理,不画架构图,只做能跑通的事。
安装ThinkPHP并验证环境
打开终端(Windows用PowerShell或CMD,macOS/Linux用Terminal),确保已安装PHP 7.4+和Composer。
执行命令创建项目:composer create-project topthink/think tp-crawl。这一步会自动下载框架、解析依赖、初始化目录结构,耗时约15~60秒,取决于网络。
进入项目目录:cd tp-crawl。
立即学习“PHP免费学习笔记(深入)”;
启动内置服务器:php think run。如果终端输出Swoole server started或监听在http://127.0.0.1:8000,说明环境就绪;若报错command not found: php,请先配置系统PATH指向PHP可执行文件。
浏览器访问http://127.0.0.1:8000,看到ThinkPHP欢迎页即为成功。【注意:不要跳过这步验证,很多后续采集失败源于基础环境未就绪】
创建采集专用控制器
在app/controller目录下新建文件Crawl.php,内容如下:
<?php<br>namespace app\controller;<br>use think\Controller;<br>class Crawl extends Controller<br>{<br> public function index()<br> {<br> return '采集模块已激活';<br> }<br>}
保存后,在浏览器访问http://127.0.0.1:8000/crawl,应显示“采集模块已激活”。这证明控制器注册成功,路由已生效。
若返回404,请检查文件名是否为Crawl.php(首字母大写)、类名是否为Crawl、命名空间是否为app\controller——三者必须严格一致,ThinkPHP对大小写敏感。
发起首次HTTP请求(不带gzip)
修改app/controller/Crawl.php中的index()方法:
第一步:引入Curl类支持:use think\Http;(加在use think\Controller;下方)
第二步:替换return语句为:
$response = Http::get('https://httpbin.org/get');<br>return json(['status' => 'success', 'body' => $response->getBody()->getContents()]);这行代码会向测试接口发起GET请求,并把原始响应体转为JSON返回。访问http://127.0.0.1:8000/crawl,你将看到包含origin、headers等字段的JSON数据。
若报错Class 'think\Http' not found,说明你使用的是TP6.1+版本——该版本已移除think\Http,需改用think\facade\Http,或直接使用原生cURL。此处采用兼容写法:$ch = curl_init('https://httpbin.org/get'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $data = curl_exec($ch); curl_close($ch); return json(['raw' => $data]);
处理gzip压缩页面(安居客/知乎等常见场景)
很多目标网站(如安居客列表页)默认启用gzip压缩,直接用file_get_contents或基础cURL会返回乱码二进制数据。必须显式声明接受gzip编码。
方法一:使用ThinkPHP 6.1+内置Http门面(推荐)
$response = \think\facade\Http::withHeaders(['Accept-Encoding' => 'gzip'])->get('https://httpbin.org/gzip');
方法二:手写兼容cURL函数(适用于所有TP版本)
在app/controller/Crawl.php顶部class Crawl extends Controller上方添加:
function https_request($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); $data = curl_exec($ch); curl_close($ch); return $data; }
然后在index()中调用:$html = https_request('https://httpbin.org/gzip');。此时$html是解压后的明文字符串,可安全用于后续正则或DOM解析。
【关键点:CURLOPT_ENCODING必须设为'gzip',不能写成'gzip,deflate'或留空,否则部分服务器仍返回压缩流】
用正则提取标题文本(最小可行采集)
现在我们抓取一个真实页面:https://httpbin.org/html。它返回一段含<h1>Herman Melville</h1>的HTML。
在index()方法中追加:
$html = https_request('https://httpbin.org/html');<br>$pattern = '/<h1>(.*?)<\/h1>/i';<br>preg_match($pattern, $html, $matches);<br>return $matches[1] ?? '未匹配到标题';
刷新http://127.0.0.1:8000/crawl,页面将直接显示Herman Melville。
这行正则/<h1>(.*?)<\/h1>/i中,?表示非贪婪匹配,避免跨标签捕获;i标志忽略大小写;$matches[1]取第一个子模式内容——漏掉[1]会返回整个匹配串,包含<h1>标签本身。



















