1. 链家北京租房抓取的真实场景与核心难点链家网北京租房信息抓取是很多做房产数据分析、租房比价工具、区域租金行情看板的朋友绕不开的一关。它页面结构规整、字段丰富看起来很适合练手但真正跑起来你会发现三个现实问题一是列表页和详情页的字段分布在不同层级正则一改版就崩二是请求频率稍高就会触发验证或返回空数据三是抓下来的字段经常出现空值、错位落库时才发现对不上。这篇内容面向的是已经会写基础 requests 请求、想把这套流程做稳的读者。我会从请求头构造、分页策略、详情页字段抽取、频率控制一直讲到数据落盘和字段校验。同时把 TaoToken 的统一 Key 接入配置一起交付因为很多人在做多模型辅助解析房源文本、或者用模型做字段纠错时Key 管理混乱、环境变量到处散落反而拖慢了调试节奏。TaoToken 在这里的角色是统一管理模型调用凭证让爬虫项目里的辅助解析环节有一个稳定的配置入口而不是每次换模型就改一遍代码。需要先说明的是抓取行为要遵守目标站点的 robots 协议和相关规定控制频率、只取公开信息、不用于商业转售这是前提。下面的配置和代码都是围绕“稳定、可校验、可复现”来设计的。2. TaoToken 前置准备统一 Key 与 config.toml 骨架在爬虫项目里引入模型能力最常见的痛点是 Key 散落在各个脚本、测试环境和正式环境混用。TaoToken 提供统一的 API 入口把模型调用凭证集中管理。你可以在官网了解整体能力实际接入时用 API 地址https://taotoken.net/api。先注册并拿到 Key入口在控制台的 API Keys 页面。拿到之后不要硬编码进脚本而是写进config.toml用环境变量兜底。下面是我实测下来比较稳的骨架# config.toml [app] name lianjia_bj_zufang timeout 15 retry 3 [request] # 列表页与详情页共用请求头 user_agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 referer https://bj.lianjia.com/zufang/ accept_language zh-CN,zh;q0.9 # 请求间隔秒控制频率的核心参数 min_delay 2.5 max_delay 5.0 page_start 1 page_end 20 [storage] # 落盘方式csv 或 mysql mode csv csv_path ./data/lianjia_bj.csv [taotoken] base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} model claude-3-5-sonnet # 用于房源文本字段纠错与补全 enable_field_fix true这里api_key用${TAOTOKEN_API_KEY}占位运行时从环境变量读取避免把凭证提交到仓库。模型对话相关的调试可以直接在模型对话页面验证返回是否符合预期确认没问题再写进爬虫的辅助流程。读取配置的代码import os import toml def load_config(pathconfig.toml): cfg toml.load(path) # 环境变量覆盖优先级最高 env_key os.getenv(TAOTOKEN_API_KEY) if env_key: cfg[taotoken][api_key] env_key return cfg CFG load_config()这样本地开发用环境变量CI 或服务器上注入密钥代码本身不含敏感信息。3. 可复制配置请求头、分页与详情页字段抽取链家列表页的 URL 结构是https://bj.lianjia.com/zufang/{区域}/pg{页码}/比如朝阳区就是chaoyang。分页从 1 开始超过实际页数会返回空列表所以要在解析时判断是否还有房源及时停止而不是死循环到 100 页。请求头里最关键的是User-Agent和Referer缺了 Referer 有时会拿到不完整页面。下面是一个带重试和随机间隔的请求封装import time import random import requests def build_headers(cfg): return { User-Agent: cfg[request][user_agent], Referer: cfg[request][referer], Accept-Language: cfg[request][accept_language], } def fetch(url, cfg, sessionNone): headers build_headers(cfg) sess session or requests.Session() for attempt in range(cfg[app][retry]): try: resp sess.get(url, headersheaders, timeoutcfg[app][timeout]) if resp.status_code 200 and zufang in resp.text: return resp.text # 状态码异常或页面异常等待后重试 time.sleep(random.uniform(cfg[request][min_delay], cfg[request][max_delay])) except requests.RequestException as e: print(f请求异常 {url}: {e}) time.sleep(random.uniform(cfg[request][min_delay], cfg[request][max_delay])) return None分页循环要带终止判断def crawl_list(area, cfg): session requests.Session() results [] for page in range(cfg[request][page_start], cfg[request][page_end] 1): url fhttps://bj.lianjia.com/zufang/{area}/pg{page}/ html fetch(url, cfg, session) if not html: print(f第 {page} 页无数据停止) break items parse_list(html) if not items: print(f第 {page} 页解析为空停止) break results.extend(items) print(f第 {page} 页抓到 {len(items)} 条) time.sleep(random.uniform(cfg[request][min_delay], cfg[request][max_delay])) return results列表页解析建议用 lxml 或 BeautifulSoup比正则稳。详情页字段多用 CSS 选择器逐项取取不到就留空不要因为一个字段缺失整条丢弃from bs4 import BeautifulSoup def parse_list(html): soup BeautifulSoup(html, lxml) items [] for node in soup.select(div.content__list--item): title_node node.select_one(p.content__list--item--title a) if not title_node: continue items.append({ title: title_node.get_text(stripTrue), url: https://bj.lianjia.com title_node.get(href, ), }) return items def parse_detail(html): soup BeautifulSoup(html, lxml) def pick(selector): el soup.select_one(selector) return el.get_text(stripTrue) if el else return { price: pick(span.content__aside--title span), method: pick(ul.content__aside--info li:nth-child(1)), square: pick(ul.content__aside--info li:nth-child(2)), orientation: pick(ul.content__aside--info li:nth-child(3)), }字段抽取完落盘前做一次校验价格必须是数字、面积必须带“㎡”、标题非空不满足的记录单独存到reject.csv方便回头排查是页面改版还是解析规则失效。4. 验证请求与成功结果频率控制与字段校验动作配置写完先做小规模验证不要一上来就跑全量。把page_end设成 2跑一遍看输出if __name__ __main__: cfg load_config() data crawl_list(chaoyang, cfg) print(f共抓取 {len(data)} 条) for row in data[:3]: print(row)成功时你会看到类似输出第 1 页抓到 30 条 第 2 页抓到 30 条 共抓取 60 条 {title: 整租·朝阳门外·..., url: https://bj.lianjia.com/zufang/BJ...}如果第 1 页就返回 0 条先检查请求头里的 Referer 和 User-Agent 是否被识别再确认区域拼音是否正确。频率控制上min_delay和max_delay不要低于 2 秒实测低于 1.5 秒连续请求几页之后就会拿到空页面。字段校验用一个独立函数落盘前统一过一遍import re def validate(row): errors [] if not row.get(title): errors.append(title_empty) price row.get(price, ) if price and not re.match(r^\d, price): errors.append(price_invalid) return errors校验不通过的记录写入reject.csv并记录原因通过的写入正式数据文件。这样即使页面改版你也能从 reject 文件里快速定位是哪一类字段先失效。5. 本篇常见错排查空数据、字段错位与 Key 失效跑链家抓取时下面几个错误出现频率最高我按现象、原因、处理方式列出来方便对照。现象可能原因处理方式列表页返回空频率过高被限流调大 min_delay加随机抖动详情页字段全空选择器随改版失效用浏览器检查元素更新 CSS 选择器价格字段混入文字正则匹配范围过宽改用选择器取节点文本再清洗落库字段错位列表与详情顺序不一致用 url 作为主键关联不靠下标TaoToken 调用 401Key 未注入或过期检查环境变量重新生成 Key模型返回超时单次文本过长截断输入或分批调用关于 TaoToken 的 Key 失效最常见的坑是把 Key 写死在脚本里换环境后忘了改。用config.toml加环境变量的方式能规避大部分问题。如果调用报错先去 API Keys 页面确认 Key 状态再对照接入文档检查请求格式。模型返回异常时可以单独在模型对话里复现同样的输入确认是模型侧还是爬虫侧的问题。还有一个容易忽略的点详情页请求也要带 Referer且 Referer 最好指向列表页而不是详情页自身否则部分页面会返回精简版。字段错位问题根源往往是用列表下标去对应详情结果一旦某条详情抓取失败后面全部错位。正确做法是以 url 为键做字典映射落盘时再按 url 组装。6. 语义一致 CTA把配置和 Key 管理固定下来整套流程跑通之后真正影响长期稳定的是配置管理和 Key 管理这两件事。把config.toml作为唯一配置入口请求参数、频率、落盘方式、模型接入全部集中换区域、换页数、换模型都只改一个文件。TaoToken 的 Key 通过环境变量注入配合统一 API 入口多脚本共用一套凭证不用在每个爬虫里重复维护。如果你后续要做长期编码或 Agent 化的数据流水线可以了解 Coding Plan把模型调用纳入统一的开发计划里。需要验证模型返回是否符合字段纠错预期时直接在模型对话里试。接入细节和请求格式以接入文档为准Key 的生成和管理在 API Keys 页面完成。把这些固定下来链家北京租房信息的抓取和后续分析就能稳定复现而不是每次跑都靠运气。
企业数字化 ERP 产品动态
相关推荐
小白也能轻松玩转OpenClaw:虾壳云一键部署轻量化安装包(附最新安装包) /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 19:39:26
Python直链解析实战:突破网盘限速的下载方案 1. 直链解析到底在解决什么问题很多人第一次接触"直链解析"这个词,是因为被网盘的下载速度折磨得没脾气。明明家里是千兆宽带,下载一个几百兆的文件,进度条却像蜗牛爬树,几十KB每秒的速度能磨掉一整个下午。这时候就会有… · 2026/9/26 19:39:01
Claude Code集成SKILL:EDA工程师的本地AI工作流实战 1. 项目概述:这不是“装个插件”那么简单,而是打通EDA工程师的本地智能工作流你搜“Claude Code 安装 SKILL”,大概率正卡在某个IC设计流程里——比如想快速从版图里提取器件参数、批量重命名cell、自动检查DRC违例区域,或者把一段… · 2026/9/26 20:22:44
SecureCRT连接虚拟机超时?从IP到防火墙的完整排查指南 又见connection timed out。今天这位朋友的截图很典型:secureCRT会话框里红字提示"Connection timed out",他反复强调"IP我都改成一样的了",虚拟机就在VMware里运行着,可怎么都连不上。这种案例我经手过太多次… · 2026/9/26 20:22:38
Git pull报错详解:本地修改冲突的原理与安全应对 1. 这个报错到底在说什么?——不是Git坏了,是它在认真保护你的代码你刚敲下git pull或git merge,终端突然跳出一行红色文字:error: Your local changes to the following files would be overwritten by merge紧接着还列了一堆文件… · 2026/9/26 20:22:32
UEditor Word导入乱码图片红叉?从docx到HTML完整解析与解决方案 有段时间我天天被客户的一句话搞得头大:你们这个编辑器,把Word里的东西粘进来,怎么图片全变红叉?表格也歪了,标题级别也不对。项目用的是百度出品的开源富文本编辑器UEditor,说实话它本身是个老牌编辑器&am… · 2026/9/26 20:22:25
Harbor v2.5.0离线安装实战:CentOS 7内网镜像仓库部署指南 简介:Harbor v2.5.0-rc1 离线安装包面向需要在内网、离线或安全隔离环境中搭建容器镜像仓库的运维工程师与平台管理员,解决因无法访问公网镜像源而导致的 Harbor 部署困难问题。安装包内含6个文件,以 Shell 脚本、配置文件模板、License 许可… · 2026/9/26 20:22:25
AI绘画工作流实战:提示词设计、流程图与出图参数全解析 1. 从一句话脑洞到成品图:AI作图工作流的真实痛点 先把话撂在这:现在做AI作图,最大的瓶颈早就不再是模型能力,而是“你到底会不会把脑子里的想法变成模型听得懂的语言”。我见过太多人打开工具,输入一句“帮我画一个赛… · 2026/9/26 20:22:19
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46