打造专属面试题库:知识抽取与数据清洗の奇妙之旅!✨

16 min

前言呀前言

想当年我还是个研一小萌新,超爱逛牛客网、脉脉、小红书,扒拉各种面试经验贴。看到那些热门面试题和“八股文”,就忍不住把自己代入进去,琢磨着怎么回答才完美。

但是,问题也随之而来:题目多如牛毛,新题层出不穷,记性又不太好使,简直让人头大!🤯

于是,一个大胆的想法在我脑海中萌芽——“为啥不自己动手,丰衣足食,搞一个专属面试题库呢?”

不过嘛,人生就是这么充满戏剧性。刚把数据集吭哧吭哧搜集完毕,实习的橄榄枝就砸了过来,然后…然后这个伟大的项目就被我暂时“鸽”了 ( ̄▽ ̄)/。

虽然项目没完全落地,但从扒拉数据到清洗数据的整个过程,我感觉自己像是打通了任督二脉,学到了不少好东西。所以,独乐乐不如众乐乐,今天就把它写成博客,跟小伙伴们分享一下这段奇妙的旅程吧!

1. 数据从哪儿来:网页数据的获取

万事开头难,获取数据是搭建任何数据集的“万里长征第一步”。想拿到网页上的宝贝数据,咱们通常有两大招式:

  1. 模拟网络请求(API大法好!): 这招就像是给网站API发个“暗号”,用 Chrome开发者工具 或是 Charles 这种抓包神器,找到那些藏在深闺的API接口。然后,再模仿用户的Cookie或Session,就能直接拿到相对干净、原始的数据啦。 写代码的时候也超简单,JavaScript里有 axiosfetch,Python里有 requests 库,几行代码就搞定,主打一个直接高效!

  2. 无头浏览器(“隐身”访问大法): 有时候网站的“保安系统”(反爬虫机制)太强,API大法不好使了。这时候,就轮到无头浏览器出马了!它就像一个没有界面的浏览器,能模拟用户的真实操作,直接“看”到啥就抓啥。 常用的“隐身衣”有 PlaywrightSelenium。当然啦,就算披了隐身衣,也别太浪,不然还是会被网站识破是爬虫哦!所以,写代码时得耍点小聪明,比如随机User-Agent、随机请求头、随机访问间隔,让你的爬虫看起来更像个“真人”。

2. 给数据“洗白白”:数据预处理

辛辛苦苦爬下来的原始数据,打开一看,哇塞!经常是这样的(随便抓了个脱敏数据瞅瞅):

<section data-v-5ea596c4="" data-v-405cdcf2=""><!----> <div data-v-5ea596c4="" class="tw-flex"><h1 data-v-5ea596c4="" class="tw-mb-5 tw-font-medium tw-text-size-title-lg-pure tw-text-gray-800">宇宙厂一面</h1> <!----></div> <!----> <!----> <div data-v-5ea596c4="" class="feed-content-text tw-text-gray-800 tw-mb-4 tw-break-all">base北京&nbsp;&nbsp;2024年4月1日<br>上来三道算法题<br>1.最大公共前缀<br>2.最大子序列<br>3.重复字符串<br><br>开始聊项目细节,看到我的项目涉及数据存储相关,问我存储的内容;看到有智能代理相关项目,询问具体工作内容...<br>后面开始从项目延伸出考察知识点:<br>流式输出;<br>大文件上传<br>场景题:如果每次向智能程序询问的问题都是一样,你会怎么减少性能开销。<br>询问对前端框架的熟悉情况,我说对vue框架了解更多,面试官询问了该框架的相关内容,我阐述了一些基础响应式原理相关内容后,未被要求继续展开。<br>询问学习前端的时长和学习方式。<br>反问环节<br><br>全程1个小时9分钟,前面算法题用时接近40分钟(理论预计30分钟完成)。整体感觉还行,面试官没有深入追问更多细节。<br><br><a href="/creation/subject/3871fa77df8f40faa40474d054dbe5e3" target="_blank" class="subject font-green" nc-subject-type="0" nc-subject-tag-id="0">#面试问题记录#</a> <a href="/creation/subject/e7e06396e28b43b2928970fed37fc9ea" target="_blank" class="subject font-green" nc-subject-type="0" nc-subject-tag-id="0">#面试被问“你的缺点是什么?”怎么答#</a> </div> <!----> <!----> <!----> <!----> <!----> <!----> <!----> <div data-v-5ea596c4="" class="tw-my-3"><!----> <!----></div></section>

是不是感觉眼睛要瞎了?🤯 这么多HTML标签,简直没法直接用!

这时候,就需要给数据“洗个澡”,做个预处理。但注意哦,不能粗暴地把所有标签都删掉,那样会破坏文本原有的段落结构和语义。聪明的做法是,把HTML标签替换成空格或者空行,这样既能去掉“杂质”,又能保留原汁原味的语义结构。

一番操作下来,当当当当~ 数据就变得清爽多啦:

宇宙厂一面
base北京  2024年4月1日
上来三道算法题
1.最大公共前缀
2.最大子序列
3.重复字符串

开始聊项目细节,看到我的项目涉及数据存储相关,问我存储的内容;看到有智能代理相关项目,询问具体工作内容...

后面开始从项目延伸出考察知识点:
流式输出;
大文件上传;
场景题:如果每次向智能程序询问的问题都是一样,你会怎么减少性能开销。

询问对前端框架的熟悉情况,我说对vue框架了解更多,面试官询问了该框架的相关内容,我阐述了一些基础响应式原理相关内容后,未被要求继续展开。

询问学习前端的时长和学习方式。

反问环节
全程1个小时9分钟,前面算法题用时接近40分钟(理论预计30分钟完成)。整体感觉还行,面试官没有深入追问更多细节。

#面试问题记录#

#面试被问“你的缺点是什么?”怎么答#

3. 让机器读懂“人话”:知识抽取与标签化

经过一番“洗礼”,我们拿到了一堆纯文本。但这些文本就像一锅大杂烩,各种信息(公司、时间、问题、难度…)都混在一起,还是非结构化的,机器宝宝表示看不懂,没法直接处理。咋办呢?

这时候就要祭出“知识抽取”大法,把这些乱糟糟的文本变成整整齐齐的结构化JSON数据啦!

咱们可以召唤强大的大语言模型(LLM),再配合点“提示工程”(Prompt Engineering)的小技巧。比如,用经典的 COSTAR 框架来组织我们的“咒语”(提示词),并告诉LLM输出格式的必须是JSON格式。看我的“咒语”示例:

# CONTEXT(上下文)
你将处理一段来自面试经验分享的非结构化文本。这些文本通常包含面试公司信息、面试时间、面试内容、技术问题、面试难度等多种元素。文本已经过初步清洗,但仍需进一步结构化处理。

# OBJECTIVE(目标)
将非结构化的面试文本转换为结构化的JSON数据,提取关键信息。

# STYLE(风格)
- 精确:确保提取的信息准确无误
- 完整:尽可能提取所有相关信息
- 结构化:遵循严格的JSON结构
- 简明:去除冗余信息,保留核心内容

# TONE(语调)
专业、中立、客观,不添加个人评价或判断。

# AUDIENCE(受众)
数据处理者和开发人员,他们将使用这些结构化数据构建面试题库。

# RESPONSE(响应)
请返回一个JSON数组,包含以下字段(如果信息不存在则使用null):
[{
  "company": "面试公司名称",
  "level": "面试轮次(如一面、二面等)",
  "tag": "问题类别(如数据结构与算法、数据库、计算机网络等)",
  "difficulty": "难度等级(1-5的整数)",
  "question": "具体的面试问题内容(每条数据仅包含一个问题)",
  "time": "面试日期(YYYY-MM-DD格式)"
},...]

不过有个小tips:咱们通常要处理海量数据,一条一条请求LLM太慢,并发请求又怕钱包顶不住。好消息是,现在很多LLM服务都提供了批量API(Batch API)的选项!你可以把所有请求打包成一个 .jsonl 文件(每行一个JSON请求),一次性丢给模型。等模型慢慢处理完(它们可能会挑个非高峰期,还能用上提示词缓存之类的省钱大法),再把结果一口气还给你。这种方式不仅方便快捷,还超级省钱,简直是我等“贫民窟”开发者的福音啊!

经过LLM的“点化”,我们就能得到像下面这样漂亮的JSON数据啦(这里只展示一条原始文本提取出的多条面试题数据):

[
  {
    "company": "宇宙厂",
    "level": "一面",
    "tag": "数据结构与算法",
    "difficulty": 3,
    "question": "最大公共前缀",
    "time": "2024-04-01"
  },
  {
    "company": "宇宙厂",
    "level": "一面",
    "tag": "项目经历",
    "difficulty": 2,
    "question": "聊项目细节",
    "time": "2024-04-01"
  },
  {
    "company": "宇宙厂",
    "level": "一面",
    "tag": "数据库",
    "difficulty": 2,
    "question": "项目涉及数据存储相关,存储的内容是什么?",
    "time": "2024-04-01"
  },
  {
    "company": "宇宙厂",
    "level": "一面",
    "tag": "计算机网络",
    "difficulty": 3,
    "question": "流式输出的实现或原理",
    "time": "2024-04-01"
  },
  {
    "company": "宇宙厂",
    "level": "一面",
    "tag": "技术知识",
    "difficulty": 4,
    "question": "大文件上传的实现或方案",
    "time": "2024-04-01"
  },
  {
    "company": "宇宙厂",
    "level": "一面",
    "tag": "性能优化",
    "difficulty": 4,
    "question": "如果每次向智能程序询问的问题都是一样,你会怎么减少性能开销?",
    "time": "2024-04-01"
  },
  ...
]

4. “强迫症”的自我修养:数据清洗

拿到LLM处理过的数据,是不是以为可以高枕无忧了?Too young, too simple! 😉

仔细瞅瞅,可能会发现标签、公司名、面试轮次还是五花八门,有点“逼死强迫症”的意思。比如,“宇宙厂”、“抖Y”、“字J”、“bytedance”其实说的都是一家公司。

这时候,就需要我们拿出“火眼金睛”,手动或者用脚本(Excel大法、Python/JS小脚本都行)再精炼一下。

比如,把“宇宙厂”、“抖音”、“字节”、“bytedance”这些都统一成“字节跳动”;面试轮次也规范成“一面”、“二面”、“三面”这种标准格式。

清洗完毕,数据就更规整啦:

  {
    "id": "3w5s8a",
    "company": "字节跳动",
    "level": "一面",
    "tag": "计算机网络",
    "difficulty": 3,
    "question": "流式输出的实现或原理",
    "time": "2024-04-01"
  }

5. 流量焦虑者的福音:数据压缩

当我们的数据要在网络上传输时,体积大小可是个敏感问题,毕竟流量也是钱啊!仔细观察一下JSON数据,你会发现好多key(像"company", "question"这些)都是重复的,占了不少空间。

这时,机智的我们就可以给key“瘦瘦身”:

比如,把完整的key缩写成单个字母:

{
    "i": "3w5s8a",
    "c": "字节跳动",
    "l": "一面",
    "t": "计算机网络",
    "d": 3,
    "q": "流式输出的实现或原理",
    "m": "2024-04-01"
}

更狠一点,直接省略key,用数组形式(当然,这需要前后端约定好顺序):

["3w5s8a","字节跳动","一面","计算机网络",3,"流式输出的实现或原理","2024-04-01"]

这么一顿操作,能轻松减少近30%的数据体积,是不是很香?💰

尾声:开源分享,与你同行!🚀

基于上面折腾出来的这套数据集,我顺手搭了个前端面试刷题小站:FE Rusher (没错,就是为了督促自己刷题,哈哈!)。

代码也光荣地躺在GitHub上了:ni00/FERusher,数据集在仓库的 ./data/fe.json 路径下,欢迎围观和Star⭐!

这个小破站有啥好玩的呢?

  • 🌐 海量题库:汇集了各大厂(对,就是你想的那些!)的前端面试真题。
  • 🔍 精准筛选:可以按公司、难度、技术栈等N多维度自由筛选,定位你的薄弱环节。
  • 🎲 随缘刷题:选择困难症?试试随机来一道,刺激!
  • 我的收藏:好题不容错过,一键收藏,反复盘它!
  • 🤖 AI智能分析:遇到难题?召唤AI导师帮你分析解答(钱包在燃烧🔥)。
  • 📱 全端适配:无论你是PC党还是手机党,体验都棒棒哒。
  • 🌙 深色模式:夜猫子友好,保护你的卡姿兰大眼睛。

🛠️ 技术栈揭秘

  • 框架Next.js 15
  • UI:基于 Radix UI 的手搓组件
  • 状态管理:React Hooks (简单粗暴)
  • CSSTailwind CSS (真香!)
  • AI加持OpenAI API
  • 部署:轻松静态部署 (Vercel, Netlify, GitHub Pages… 任君选择)

所以呀,如果你也想搞一个后端版、算法版,甚至产品经理版的刷题网站,简直不要太简单!直接在 data 文件夹下塞入你的JSON数据,稍微改改代码就能跑起来啦。期待看到更多小伙伴的创意作品!🥳