游客发表
我用phpspider抓过招聘网站,一天跑了三千个页面,没被封IP。这工具最狠的地方在于,它把PHP的简单粗暴发挥到了极致——你写个回调函数,它就把网页内容嚼碎了喂给你,连正则都不用自己写。
先看个最基础的例子。你要抓某个新闻站,只需要定义规则:
require 'vendor/autoload.php'; use phpspider\core\phpspider; $configs = array( 'name' => '新闻抓取', 'log_show' => true, 'domains' => array('news.example.com'), 'scan_urls' => array('http://news.example.com/list/1.html'), 'list_url_regex' => array('http://news.example.com/list/\d+\.html'), 'content_url_regex' => array('http://news.example.com/detail/\d+\.html'), 'fields' => array( array('name' => 'title', 'selector' => '//h1', 'required' => true), array('name' => 'content', 'selector' => '//div[@class="article"]', 'required' => true), ), ); phpspider::run($configs); 这段代码干了三件事:先锁定列表页,再通过正则找到所有详情页链接,最后用XPath抽取标题和正文。你注意到没?required 参数很关键——如果某条数据缺了标题,它直接跳过,不会让你后续清洗时崩掉。
但光会跑通demo没用。我踩过最大的坑是编码问题。默认情况下它按UTF-8处理,可国内很多老站点还是GBK。你抓下来全是乱码,正则匹配直接失效。解决办法是在配置里加一句:
'input_encoding' => 'GBK', 'output_encoding' => 'UTF-8',
这玩意儿我折腾了整整一个下午才搞明白。官方文档写得含糊,只说“支持编码转换”,实际你得自己试。后来我干脆写了个小函数,先检测页面meta标签里的charset,再动态设置。
再说说并发。phpspider默认单进程跑,速度其实不慢,但遇到那种几千页的站就难受了。它内置了request_interval参数,控制每次请求间隔毫秒数。我建议设成500到1000,太慢了浪费时间,太快了容易被封。有一次我图快设了200毫秒,结果抓了不到两百页,对方服务器直接把我IP断了一小时。
还有个容易被忽略的功能——断点续抓。它把已抓取的URL存在SQLite里,你中途挂了,重新跑会跳过那些已经抓过的。这个设计很实在,不像某些框架要自己维护状态。
不过说实话,phpspider的文档写得真不咋地。很多方法你得翻源码才能看懂。比如selector支持XPath和CSS两种写法,但没告诉你CSS选择器需要额外装个库。我当初用div.article这种写法,死活匹配不上,查了半天才发现要改成//div[@class="article"]。
如果你要抓的是SPA页面(Vue、React那种),phpspider就抓瞎了。它本质上是模拟HTTP请求,拿不到JS渲染后的DOM。这时候建议换Puppeteer或者Playwright,或者用phpspider抓接口,直接请求后端API反而更干净。
最后说个实战技巧。抓取时尽量把user_agent伪装成真实浏览器,最好随机切换。它默认的UA是“phpspider/1.0”,一眼就被识别出来了。我写了个UA池,每次请求随机选一个Chrome或Firefox的UA,封禁率明显下降。
这工具适合什么场景?中小规模采集、规则清晰的静态站、快速原型验证。真要搞分布式海量抓取,它撑不住。但你要是用PHP写业务,又不想额外维护一套Python爬虫服务,phpspider是性价比最高的选择——装个Composer包就能跑,和现有代码无缝集成。至少对我来说,它帮我省掉了写curl循环的麻烦,还自带日志和去重,省心。
友情链接