当前位置: 当前位置:首页 > 探索 > py爬虫代码正文

py爬虫代码

作者:时尚 来源:百科 浏览: 【大 中 小】 发布时间:2026-10-17 06:23:36 评论数:

写爬虫这件事,爬虫很多人以为门槛在代码。代码其实不是爬虫。真正卡住你的代码是目标网站的反爬策略,以及你对自己要抓什么数据到底有没有想清楚。爬虫我见过太多人上来就抄一段requests加BeautifulSoup的代码模板,跑通一个静态页面就觉得自己会了,爬虫结果遇到JavaScript渲染的代码站点直接傻眼。

先看一段最朴素的爬虫代码:

import requests from bs4 import BeautifulSoup url = "https://example.com/list" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} resp = requests.get(url, headers=headers) soup = BeautifulSoup(resp.text, "html.parser") for item in soup.select(".item-title"): print(item.get_text(strip=True)) 

这段代码能跑,但它脆得像纸。代码网站改一次class名,爬虫你就得重写。代码更别说很多站点根本不给你静态HTML——打开DevTools看Network,爬虫数据全在XHR请求里,代码页面骨架是爬虫空的。这时候你得去翻API接口,找到那个返回JSON的URL,直接用requests打过去。比解析HTML舒服十倍。

我去年帮朋友抓一个招聘网站的数据。表面上看是分页列表,实际翻到第三页就弹出验证码。换了IP也不行,它检测的是浏览器指纹。后来用playwright起了一个带完整浏览器环境的实例,模拟鼠标滚动和点击,才绕过检测。代价是速度慢了很多,每页要等两秒。但数据质量高,字段齐全,省去了大量清洗工作。

说到清洗,这是另一个容易被低估的环节。网页上的文本经常带一堆空白字符、换行、HTML实体。比如 、\u200b这种零宽空格。不处理的话,存进数据库全是脏数据。我习惯在解析阶段就统一做strip和replace,别留到后面。

关于并发,新手容易犯两个极端。要么纯单线程,一万条数据跑到天荒地老;要么一上来就开五百个线程,直接把目标站打挂,IP秒封。比较稳妥的做法是用concurrent.futures的ThreadPoolExecutor,控制在10到20个worker,每个请求之间加time.sleep(random.uniform(0.5, 1.5))。别嫌慢,稳定比快重要。

还有一点,robots.txt不是摆设。我一般会看一眼,如果明确禁止抓取,就换目标。这不光是法律风险的问题,而是没必要跟一个不欢迎你的站点较劲。数据源多的是,找那些开放的、或者提供API的,省心得多。

存储环节看数据量。几千条用CSV足够,几万条上SQLite,再大就考虑MongoDB或者PostgreSQL。别一上来就搞分布式,大部分人的需求根本到不了那个量级。我见过有人为了抓五万条商品评论,硬是搭了一套Scrapy-Redis集群,维护成本比数据本身还高。

最后说个细节:日志。很多人写爬虫不打日志,跑完不知道哪些URL失败了,哪些解析出错了。加两行logging的事,能省你很多排查时间。我通常会把失败的URL单独写到一个文件里,方便重试。

爬虫代码本身不复杂,复杂的是应对变化。网站改版、反爬升级、IP被封,这些都是常态。写的时候多留几个后路,比如把选择器写成配置项,把请求头做成可替换的,把解析逻辑和抓取逻辑分开。这样下次改起来,不至于从头再来。