Python3+Selenium实战:Facebook好友列表抓取与CSV导出
简介这是一份面向Python爬虫初学者与自动化测试爱好者的Facebook好友列表抓取脚本基于Python3编写借助Selenium驱动Firefox完成自动登录与数据提取用户只需填入邮箱和密码即可运行适合想了解浏览器自动化、登录流程模拟与页面解析的入门者练手。压缩包共6个文件约4.03MB包含1个核心py脚本、2个md说明文档、1个gif演示动图以及license和gitignore等辅助文件脚本主体清晰文档与动图便于快速理解运行效果。资源已积累2889人学习下载热度较高。通过阅读脚本与说明可掌握Selenium与Firefox的配合方式、argparse命令行参数设计、登录超时与登录文件等选项的用法并参考BeautifulSoup4相关解析思路为后续扩展抓取字段、处理登录态与调试排错提供可复用的代码骨架。1. 朋友列表抓取一个被低估的自动化入口做海外社媒数据的朋友多半有过这种经历运营需要一批种子用户做冷启动市场部想分析某个垂直圈层的关系网络或者你自己想搞清楚一个公开主页到底连接了哪些人。手动点开、滚动、复制、粘贴一百个好友能耗掉整个下午而且极易触发平台的风控。selenium_facebook_scraper这个标题指向的正是这类需求的最小可行方案——用 Python3 加 Selenium 驱动真实浏览器把朋友列表这种半结构化页面里的昵称、主页链接、头像地址批量落成 CSV。它不碰私有接口不逆向加密参数靠的是模拟真人操作所以对新手友好对熟手也留足了调参空间。适合谁适合需要快速验证关系网络假设、又不想一上来就啃复杂爬虫框架的从业者。下面我把这套方案的选型逻辑、代码骨架、参数边界和血泪坑位一次讲透。2. 为什么用 Selenium 而不是直接怼接口选型与前置准备2.1 朋友列表页面的加载特性决定了工具选择朋友列表不是一张静态 HTML 表。打开一个公开主页的好友标签你会看到首屏只渲染十几个卡片往下滚动才触发异步加载而且滚动到底部时会出现一个短暂的加载指示器。用requests直接请求拿到的往往是空壳或者只有第一页数据。Selenium 的价值在于它驱动的是真实浏览器内核JavaScript 执行、懒加载触发、动态 DOM 插入都和真人操作一致。常见做法是配合WebDriverWait做显式等待等某个卡片元素出现再继续而不是死等固定秒数。另一个选型理由是登录态朋友列表通常要求账号已登录Selenium 可以复用本地浏览器配置或手动扫码后的会话省去处理复杂 Token 的麻烦。2.2 环境搭建与依赖安装的最小命令集先确认本机有 Python3.8 以上和对应版本的浏览器驱动。我一般用虚拟环境隔离避免污染全局包。下面这套命令在 macOS 和主流 Linux 发行版上都能跑通Windows 把激活命令换成venv\Scripts\activate即可。# 创建并激活虚拟环境 python3 -m venv venv source venv/bin/activate # 安装核心依赖 pip install selenium webdriver-manager pandas # 验证 selenium 版本建议 4.x 以上 python -c import selenium; print(selenium.__version__)webdriver-manager的作用是自动下载并匹配浏览器驱动省去手动对照版本号的痛苦。pandas只用于最后导出 CSV如果你习惯用csv标准库也可以不装。安装完成后新建一个scraper.py后续所有代码都写在这里。2.3 初始化 WebDriver 的关键参数与反检测基线直接webdriver.Chrome()启动的浏览器会带一堆自动化特征平台的风控系统很容易识别。我一般会加几个启动参数并把navigator.webdriver这个属性抹掉。注意这里不涉及任何绕过登录或破解加密的操作只是让浏览器行为更接近普通用户。from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.options import Options options Options() # 禁用“正受到自动化测试软件控制”的提示条 options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) # 设置一个常见的桌面窗口尺寸避免移动端布局干扰 options.add_argument(--window-size1400,900) # 可选指定用户数据目录复用已登录的会话 # options.add_argument(--user-data-dir/path/to/your/chrome/profile) driver webdriver.Chrome(serviceService(ChromeDriverManager().install()), optionsoptions) # 抹掉 webdriver 标记 driver.execute_cdp_cmd(Page.addScriptToEvaluateOnNewDocument, { source: Object.defineProperty(navigator, webdriver, {get: () undefined}) })参数说明excludeSwitches去掉顶部提示条减少视觉干扰window-size固定为桌面尺寸因为朋友列表在移动端布局下 DOM 结构不同选择器会失效user-data-dir是可选的重头戏如果你已经在该浏览器配置里登录过目标账号加上这个参数就能直接带着登录态启动省去每次扫码。注意用户数据目录不要和日常使用的浏览器实例同时打开否则会锁冲突。3. 从滚动加载到 CSV 落盘核心抓取逻辑拆解3.1 定位朋友卡片选择器的稳定性与降级策略朋友列表的 DOM 结构会随平台改版变化所以选择器不能写死。我的习惯是先用浏览器开发者工具找到卡片容器的共同特征比如div[rolemain]下带有特定>from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def find_friend_cards(driver, timeout15): # 候选选择器列表按优先级排列 candidates [ div[rolemain] div[data-visualcompletionignore-dynamic] a[href*/friends], div[rolemain] a[href*friend], div[rolemain] div[rolearticle] a, ] for sel in candidates: try: WebDriverWait(driver, timeout).until( EC.presence_of_element_located((By.CSS_SELECTOR, sel)) ) cards driver.find_elements(By.CSS_SELECTOR, sel) if cards: print(f命中选择器: {sel}, 卡片数: {len(cards)}) return cards except Exception: continue raise RuntimeError(所有候选选择器均未命中请检查页面是否加载或登录态是否失效)逻辑说明WebDriverWait最多等 15 秒让异步内容有机会渲染presence_of_element_located只要求元素出现在 DOM 里不要求可见因为部分卡片可能在视口外。候选选择器从具体到宽泛避免因一次改版就全盘失效。如果全部落空直接抛异常而不是返回空列表方便上层决定是否重试。3.2 滚动加载的节奏控制次数、间隔与终止条件滚动是这套脚本最容易被风控盯上的动作。我的经验是不要用window.scrollTo(0, document.body.scrollHeight)一步到底那样滚动事件触发太密集。改成小步长、随机间隔并且每滚几次就检查一次卡片数量是否还在增长。import time import random def scroll_and_collect(driver, max_scrolls50, pause_range(1.5, 3.5)): last_count 0 stable_rounds 0 for i in range(max_scrolls): # 小步滚动每次滚一屏的 80% 左右 driver.execute_script(window.scrollBy(0, window.innerHeight * 0.8);) # 随机停顿模拟真人阅读节奏 time.sleep(random.uniform(*pause_range)) cards driver.find_elements(By.CSS_SELECTOR, div[rolemain] a[href*friend]) current_count len(cards) print(f第 {i1} 次滚动当前卡片数: {current_count}) if current_count last_count: stable_rounds 1 # 连续 3 次数量不变认为已到底 if stable_rounds 3: print(卡片数连续稳定停止滚动) break else: stable_rounds 0 last_count current_count return cards参数说明max_scrolls是硬上限防止页面无限加载导致脚本卡死pause_range给随机间隔1.5 到 3.5 秒之间比较接近真人浏览速度stable_rounds设为 3 是经验值太少容易误判太多浪费时间。注意每次滚动后重新查询卡片因为 DOM 会动态插入新节点之前拿到的列表引用可能已经过期。3.3 提取字段并导出 CSV去重、编码与列顺序拿到卡片元素后逐个提取昵称、主页链接和头像地址。昵称通常在a标签的文本或aria-label里链接是href属性头像在img的src。这里有个细节部分卡片是推荐好友而非真实好友链接里会带?ref参数需要过滤掉。import csv import re def extract_friends(cards): seen set() rows [] for card in cards: try: href card.get_attribute(href) or # 过滤推荐位和空链接 if friend not in href or refbookmarks in href: continue # 用主页 ID 去重 match re.search(rprofile\.php\?id(\d), href) uid match.group(1) if match else href.split(?)[0] if uid in seen: continue seen.add(uid) name card.text.strip() or card.get_attribute(aria-label) or 未知 # 头像通常在卡片内的 img 标签 try: img card.find_element(By.TAG_NAME, img) avatar img.get_attribute(src) or except Exception: avatar rows.append({昵称: name, 主页: href, 头像: avatar}) except Exception as e: print(f跳过一条异常卡片: {e}) return rows def save_csv(rows, pathfriends.csv): if not rows: print(没有可写入的数据) return with open(path, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[昵称, 主页, 头像]) writer.writeheader() writer.writerows(rows) print(f已写入 {len(rows)} 条到 {path})逻辑说明seen集合按用户 ID 去重避免滚动过程中同一张卡片被重复采集utf-8-sig编码让 Excel 打开 CSV 时不乱码字段顺序固定为昵称、主页、头像方便后续用 pandas 读取。如果某条卡片解析失败打印异常并继续不让单条错误中断整个任务。4. 避坑与排查那些让我重跑三次的细节4.1 登录态失效导致页面直接跳转现象脚本启动后浏览器打开的是登录页所有选择器都找不到元素报超时。原因Selenium 每次启动的是全新会话不带任何 Cookie。解决要么在启动参数里加--user-data-dir指向已登录的浏览器配置目录要么在脚本开头留出 30 秒手动扫码时间用input(扫码后按回车继续)阻塞。我一般用前者但注意配置目录不能被日常浏览器占用。4.2 滚动到底部后卡片数不再增长但实际还有数据现象连续三次滚动卡片数不变脚本停止但手动打开页面发现下面还有内容。原因平台的懒加载有节流快速滚动时新内容还没请求回来导致计数稳定假象。解决把stable_rounds提高到 5或者在每次滚动后额外等一个网络空闲信号比如driver.execute_script(return document.readyState)返回complete再计数。更稳妥的是在停顿区间里加一个 5 秒的长停顿每 10 次滚动触发一次。4.3 选择器命中大量非好友元素现象抓下来的 CSV 里混进了“推荐好友”“你可能认识的人”甚至广告卡片。原因候选选择器写得太宽泛a[href*friend]会把所有带 friend 字样的链接都捞进来。解决在提取阶段加过滤条件检查链接是否包含profile.php?id或/friends/路径同时排除带refbookmarks、refsearch的推荐位。更彻底的办法是先用开发者工具确认真实好友卡片的父容器有唯一属性再缩小选择器范围。4.4 头像地址是缩略图或空字符串现象CSV 里头像列大量为空或者全是 50x50 的小图。原因列表页为了性能只加载缩略图部分卡片甚至用懒加载占位符src是 base64 或空。解决如果只需要头像链接接受缩略图即可如果需要原图得再进每个主页抓一次但那会大幅增加请求量和风控风险。我的建议是列表页只存缩略图地址后续按需异步补全不要在主流程里做。4.5 运行中途被要求验证身份或限制访问现象脚本跑了几十次滚动后页面突然弹出验证码或提示“操作过于频繁”。原因滚动节奏太机械或者单次会话抓取量过大。解决把pause_range下限提高到 2.5 秒单次会话最多抓 200 条就主动退出换时段再跑。另外不要在同一个账号上高频运行准备一个专门用于数据采集的账号降低主账号风险。5. 进阶技巧把一次性脚本变成可复用的采集管道5.1 用配置文件管理选择器和滚动参数硬编码选择器的脚本活不过两次改版。我习惯把选择器、滚动次数、停顿区间写进一个config.yaml脚本启动时读取。这样改版时只需要改配置不用动代码。import yaml def load_config(pathconfig.yaml): with open(path, r, encodingutf-8) as f: return yaml.safe_load(f) # config.yaml 示例内容 # selectors: # card: div[rolemain] a[href*friend] # name: span # avatar: img # scroll: # max_scrolls: 60 # pause_min: 2.0 # pause_max: 4.0 # stable_rounds: 5参数说明card是卡片选择器name和avatar是卡片内子元素选择器max_scrolls控制上限pause_min和pause_max给随机停顿范围stable_rounds决定何时停止。把配置和代码分离后同一套逻辑可以快速适配不同页面结构。5.2 断点续抓记录已采集 ID 避免重复劳动如果一次没抓完下次重跑时不应该从头再来。我的做法是在 CSV 旁边维护一个seen_ids.txt每采集一条就追加写入用户 ID。启动时先加载这个文件到集合里提取阶段直接跳过已存在的 ID。def load_seen_ids(pathseen_ids.txt): try: with open(path, r, encodingutf-8) as f: return set(line.strip() for line in f if line.strip()) except FileNotFoundError: return set() def append_seen_id(uid, pathseen_ids.txt): with open(path, a, encodingutf-8) as f: f.write(uid \n)逻辑说明load_seen_ids在脚本启动时调用一次把历史 ID 读进内存append_seen_id在每提取一条新记录后调用实时落盘。这样即使脚本中途崩溃下次也能接着跑。注意文件写入用追加模式不要每次重写整个文件否则数据量大时会很慢。5.3 用 pandas 做后处理去重、排序与导出 ExcelCSV 只是中间产物最终交付往往需要 Excel 或数据库。用 pandas 读进来做一次全局去重和排序再导出成.xlsx比在采集阶段做更高效。import pandas as pd def postprocess(csv_pathfriends.csv, xlsx_pathfriends.xlsx): df pd.read_csv(csv_path, encodingutf-8-sig) # 按主页链接去重保留第一条 df df.drop_duplicates(subset[主页], keepfirst) # 按昵称排序方便查阅 df df.sort_values(by昵称, ascendingTrue) # 重置索引 df df.reset_index(dropTrue) df.to_excel(xlsx_path, indexFalse) print(f后处理完成共 {len(df)} 条已导出到 {xlsx_path}) return df参数说明drop_duplicates的subset指定按主页链接判重keepfirst保留首次出现的记录sort_values按昵称排序如果昵称包含多语言字符排序结果可能不符合预期可以改用主页 ID 排序to_excel需要额外安装openpyxl用pip install openpyxl即可。这一步放在采集之后不占用浏览器会话时间适合批量处理多个 CSV 文件。5.4 一个我常犯的错误忽略浏览器版本与驱动匹配最后说个血泪教训。有次在另一台机器上跑脚本webdriver-manager下载的驱动版本和本机浏览器差了一个大版本启动直接报SessionNotCreatedException。排查了半天才发现是浏览器自动更新了而驱动缓存没刷新。后来我养成的习惯是每次换机器先手动跑一次python -c from webdriver_manager.chrome import ChromeDriverManager; print(ChromeDriverManager().install())确认驱动路径和版本再启动主脚本。另外如果公司网络对驱动下载有限制提前把驱动放到本地路径用Service(executable_path...)指定别等到运行时才发现下不动。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

PyTorch YOLOv3训练实战:数据增强与迭代器设计避坑指南

PyTorch YOLOv3训练实战:数据增强与迭代器设计避坑指南

1. 为什么数据增强和迭代器是YOLOv3训练中最容易被低估的环节搞过目标检测的人都有一个共识:模型结构本身其实没太多秘密,Darknet-53加FPN那一套,论文里写得清清楚楚,网上复现的代码一抓一大把。但真正拉开训练效果差距的&#xf…

2026/10/13 14:03:58 阅读更多 →
LVS DR模式原理与生产级高可用集群搭建

LVS DR模式原理与生产级高可用集群搭建

1. 项目概述:这不是“搭个集群”那么简单,而是吃透LVS底层逻辑的实战切口“Linux操作文档——构建LVS负载均衡群集”,光看标题,很多人第一反应是:哦,又一个教你怎么敲几条命令配IPVS、起keepalived的教程。…

2026/10/13 14:03:58 阅读更多 →
智能体生产化落地:从Demo到稳定服务的七步法

智能体生产化落地:从Demo到稳定服务的七步法

1. 项目概述:为什么智能体落地总在“临门一脚”卡住你有没有遇到过这样的场景:团队花三个月搭出一个看起来很炫的智能体Demo,能自动读合同、能写周报、能调API查库存,演示时领导频频点头;可一到上线评审环节&#xff0…

2026/10/13 14:03:58 阅读更多 →

最新新闻

CT金属伪影成因与实战抑制指南:从物理原理到工作站实操

CT金属伪影成因与实战抑制指南:从物理原理到工作站实操

1. 项目概述:为什么CT图像里总会出现那些刺眼的“亮条纹”和“黑窟窿” 你有没有在医院拍完CT后,拿到报告单上写着“金属伪影明显,局部组织显示不清”?或者在做牙科CBCT时,看到自己种植牙周围一片雪白发亮、完全看不出…

2026/10/13 14:48:07 阅读更多 →
一维Unet实现ECG波形语义分割:从小波去噪到重叠滑窗推理

一维Unet实现ECG波形语义分割:从小波去噪到重叠滑窗推理

简介:这套基于Unet的ECG分段方案面向心电图信号处理与深度学习初学者,用于自动识别P波、QRS波群和T波分量。作者采用PyTorch实现,结合小波变换将来自QTDB数据集的ECG转换到小波域,并借助WFDB标注完成P段、QRS段、T段的类别划分&am…

2026/10/13 14:48:07 阅读更多 →
数据库补丁管理实战:SQL Server/MySQL升级避坑与基线检查

数据库补丁管理实战:SQL Server/MySQL升级避坑与基线检查

简介:SQL2KSP4(SQL Server 2000 Service Pack 4)是微软针对SQL Server 2000发布的最终主要服务包,适合仍需维护旧版数据库系统的管理员、DBA及历史系统迁移人员。该补丁集成了自SP3以来的全部累积更新,重点修复已公开的…

2026/10/13 14:48:07 阅读更多 →
WPF侧边导航框架:基于MVVM的状态机式UI设计

WPF侧边导航框架:基于MVVM的状态机式UI设计

简介:本资源是一个开箱即用的WPF侧边导航UI框架实现,面向C#桌面应用开发者,尤其适合初学WPF MVVM模式或需快速集成导航功能的中初级工程师。它系统性地解决了WPF项目中常见的多视图切换、菜单驱动内容更新、响应式布局适配等核心问题&#xf…

2026/10/13 14:48:07 阅读更多 →
CASTEP-19.11编译实战:从tar.gz解压到性能调优全指南

CASTEP-19.11编译实战:从tar.gz解压到性能调优全指南

简介:CASTEP-19.11.tar.gz是Materials Studio等软件中CASTEP模块的19.11版源码与文档压缩包,面向从事固体材料电子结构计算的研究人员、材料科学/物理专业高年级学生。该版本基于密度泛函理论,支持几何优化、能带结构、频率分析、电荷密度、反…

2026/10/13 14:48:07 阅读更多 →
达曼光栅Matlab仿真:从相位设计到傅里叶点阵生成

达曼光栅Matlab仿真:从相位设计到傅里叶点阵生成

简介:基于达曼光栅原理生成点阵图像的MATLAB程序,面向光学工程、激光物理等方向的学生和研究人员,也适合希望通过代码理解衍射光学与傅里叶变换的MATLAB用户。压缩包内含1个.m源码文件,整体仅约719B,代码精简&#xff…

2026/10/13 14:47:06 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →