从爬虫到面试题:一个小程序开发者的探索与优化之路
上周五晚上十点半,我还在公司调一个诡异的白屏问题。VSCode里插件装得比头发还多,但就是搞不定用户反馈的“页面偶尔打不开”。刚入职这家新公司两个月,业务压力不小,团队氛围倒是挺好——虽然产品经理又在群里@我说“这个需求很简单,明天上线吧”。
说来惭愧,我在腾讯做了三年微信小程序客户端开发,天天和 wx.request、本地缓存、分包加载打交道,自以为对前端性能优化已经炉火纯青。结果一跳槽,发现外面的世界早就卷到AI+数据驱动了。为了不被淘汰,我最近开始疯狂补课,啃书、刷LeetCode、甚至翻墙看国外技术博客。
而这一切的起点,竟然是一个看起来平平无奇的需求:我们需要从第三方网站抓取一些公开的图书信息,用于推荐系统冷启动。
没错,就是——爬虫。
起因:不是我想写爬虫,是业务逼的
事情是这样的。我们新做的一个阅读类小程序,需要初期有一些书籍数据填充首页。但合作方的API还没对接完,PM急得像热锅上的蚂蚁:“能不能先搞点数据?随便什么书都行!”
我一开始想:这不有现成的豆瓣API吗?结果一查,人家早就不开放免费接口了。GitHub上搜了一圈,发现不少开源项目用的是“模拟请求 + 正则匹配”那一套。行吧,既然躲不过,那就上。
但作为一个曾经在微信生态里被各种安全策略、域名白名单、HTTPS强制要求“调教”过的老客户端,我深知直接在小程序端做网络抓取是不可能的——不仅会被拦截,还可能被封号。所以方案很明确:后端写爬虫,前端只负责展示。
可问题是,我们后端人手紧张,排期排到下个月。领导看了我一眼:“你不是会Node.js吗?要不你先搭个临时服务?”
于是,我的“技术探索与实践优化”之旅,就这么开始了。
第一阶段:糙快猛的脚本式爬虫
我翻出大学时看的《Python网络数据采集》(Web Scraping with Python),虽然现在主力语言是JavaScript,但Python写爬虫确实香。装了个requests + BeautifulSoup,二十行代码就跑通了:
import requests
from bs4 import BeautifulSoup
url = "https://book.douban.com/tag/小说"
res = requests.get(url, headers={'User-Agent': 'Mozilla/5.0...'})
soup = BeautifulSoup(res.text, 'html.parser')
books = soup.select('.subject-item h2 a')
for book in books:
print(book.get('title'), book.get('href'))
跑起来没问题,数据也拿到了。但当我试着并发抓100本书详情页时,IP直接被豆瓣封了。而且速度慢得像蜗牛——一页3秒,100页就是5分钟。
更麻烦的是,有些字段(比如评分、评论数)藏在动态加载的JS里,静态HTML根本拿不到。这时候我意识到:现代网站反爬机制早已不是十年前那样简单了。
转向Puppeteer:用浏览器模拟人类
既然静态解析不行,那就上无头浏览器!我切换到Node.js环境,用上了Puppeteer——这玩意儿我在微信小程序自动化测试时就玩过,熟悉得很。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https https://book.douban.com/subject/123456/', {
waitUntil: 'networkidle2'
});
const title = await page.$eval('#wrapper h1 span', el => el.textContent);
console.log(title);
await browser.close();
})();
效果立竿见影!动态内容全都能拿到,还能自动处理Cookie、登录态(虽然这次用不上)。但代价也很明显:资源消耗巨大。每次启动Chrome实例都要吃掉几百MB内存,CPU飙到80%。在我那台MacBook Air上跑三个并发就卡成幻灯片。
这时我想起以前在腾讯做压测时的经验:不要在生产环境直接跑重型爬虫。于是赶紧加了队列和限流:
- 使用
bull做任务队列 - 每个任务间隔1.5秒
- 同一域名最多2个并发
- 自动轮换User-Agent和代理IP(用了免费的proxy池)
虽然还是慢,但至少不会被封,也不会把服务器干趴。
性能瓶颈:如何让爬虫快而不死?
随着数据量增大(目标是10万+书籍),效率成了最大问题。我开始思考优化路径:
能不能复用浏览器实例?
答案是可以!Puppeteer支持page复用,避免频繁启停Chromium。我把核心逻辑改成了“一个浏览器,多个页面轮流使用”,内存占用降了40%。能不能缓存已抓取页面?
当然。我用Redis存了URL哈希值,重复请求直接返回缓存。顺便加了个TTL=7天,避免数据过期。能不能分布式?
想了想,暂时没必要。10万条数据,按每秒2条算,也就14小时。我们又不是做商业爬虫,够用就行。
最终,我整理了一份性能对比表:
| 方案 | 单页耗时 | 并发上限 | 内存占用 | 反爬绕过能力 |
|---|---|---|---|---|
| requests + BS4 | 0.8s | 10+ | 低 | 弱 |
| Puppeteer(单实例) | 3.2s | 1-2 | 高 | 强 |
| Puppeteer(复用+队列) | 2.1s | 5 | 中 | 强 |
| Playwright(尝鲜版) | 1.9s | 6 | 中高 | 极强 |
注:Playwright是微软出的,比Puppeteer更新,支持多浏览器,但我怕稳定性不够,没敢上生产。
顺手整理:那些年踩过的“爬虫面试题”坑
有意思的是,在折腾爬虫的过程中,我突然意识到:很多大厂面试题,其实就藏在这些实战细节里。
比如前几天刷LeetCode,看到一道题:“如何设计一个高可用的分布式爬虫系统?” 我以前觉得这是纸上谈兵,现在才明白,这题考的就是你对调度、去重、容错、反爬、存储的理解。
我还特意翻了《剑指Offer》和《程序员面试金典》,发现至少有5道题和爬虫相关:
- 如何检测网页是否更新?(ETag / Last-Modified)
- 如何避免重复抓取?(Bloom Filter vs 哈希表)
- 如何处理动态渲染内容?(SSR vs CSR识别)
- 如何应对验证码?(打码平台 or 放弃)
- 如何保证数据一致性?(事务 or 幂等)
甚至有一次小组分享,实习生问我:“哥,爬虫合法吗?” 我愣了一下,认真回答:“技术无罪,但使用有界。公开数据、遵守robots.txt、控制频率、不用于商业牟利——这是底线。”
回归前端:爬虫数据如何赋能小程序?
别忘了,我的本职工作还是小程序客户端开发。爬来的数据最终要展示给用户看。
于是我又开始折腾前端优化:
- 用
<scroll-view>实现虚拟滚动,10万条数据也不卡 - 图片懒加载 + WebP格式,首屏快了40%
- 本地缓存热门书籍,减少网络请求
- 分包加载详情页,主包体积压到1.8MB以内
最骚的操作是:我把爬虫日志接入了小程序埋点系统。当用户点击某本书时,我会记录“该书是否来自爬虫源”,后续用来评估数据质量。产品经理看到报表后惊了:“你们还能追踪数据血缘?”
心得:技术探索的本质是解决问题
说实话,这次经历让我重新理解了“技术探索”的意义。
我不是为了炫技去写爬虫,而是因为业务卡住了,必须有人往前推一步。
在腾讯那三年,我们总说“一切以用户价值为依归”。现在我才懂,工程师的价值,就是在约束条件下找到最优解——无论是性能、成本、合规,还是时间。
我也终于明白为什么那么多面试官爱问爬虫题。它不只是考你会不会写代码,而是看你:
- 能不能权衡利弊(用简单方案 vs 复杂方案)
- 有没有工程思维(日志、监控、回滚)
- 是否尊重规则(法律、道德、技术边界)
最后:推荐几本对我帮助很大的书
如果你也想系统学习这类“跨界”技能,这几本书值得一看:
| 书名 | 适合场景 | 我的评价 |
|---|---|---|
| 《Web Scraping with Python》 | 入门爬虫 | 老但经典,讲透原理 |
| 《高性能MySQL》 | 数据存储优化 | 爬虫数据怎么存?看这本 |
| 《你不知道的JavaScript》 | JS底层 | 写Puppeteer脚本必备 |
| 《算法导论》 | 面试题攻坚 | Bloom Filter在哪章?第11章! |
| 《微信小程序开发实战》 | 本职工作 | 别笑,真有人没看过官方文档 |
现在,那个临时爬虫服务已经稳定运行三周,每天凌晨自动增量抓取,数据准确率98%以上。上周产品会上,PM居然说:“要不把这个做成后台通用能力?” —— 我表面微笑,心里OS:又要加需求了?
但转念一想,这也说明技术真的创造了价值。
从一行爬虫脚本,到支撑业务增长的数据管道,再到面试时能侃侃而谈的实战案例——这就是我们普通程序员的“小确幸”吧。
对了,如果你也在学AI,不妨试试用LLM分析爬取的书籍评论情感倾向。我刚跑通了一个demo,准确率还挺高…… 这又是另一个故事了。
(完)
作者:前腾讯小程序客户端开发,现某创业公司全栈打杂选手。日常用VSCode写代码,插件列表比购物车还长。最近在研究如何用AI自动修复线上Bug——虽然目前只会让它帮我写周报。

评论 0