尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Python爬虫实战:Selenium+BeautifulSoup自动化抓取腾讯文档在线表格

Python爬虫实战:Selenium+BeautifulSoup自动化抓取腾讯文档在线表格 1. 项目概述从网页到表格的自动化抓取做数据分析或者信息整理的朋友经常会遇到一个头疼的问题需要的数据明明就在一个网页上以表格的形式展示得清清楚楚但网站偏偏不提供直接的下载按钮。手动复制粘贴如果数据量少、结构简单还能勉强应付。一旦遇到多页、动态加载或者需要定期更新的情况手动操作就成了效率的噩梦不仅耗时耗力还容易出错。最近我就遇到了一个典型的场景需要从腾讯文档的一个在线表格里定期获取最新的项目数据。这个表格是团队协作使用的数据实时更新但导出功能要么受限要么操作繁琐。作为一个Python开发者我的第一反应就是写个爬虫把它自动化。这不仅仅是“下载一个Excel文件”那么简单因为很多时候网页上展示的并非一个静态的.xlsx或.csv文件链接而是一个由前端动态渲染的复杂表格。因此这个项目的核心是如何精准地定位、解析并提取网页中的表格数据并将其高效、结构化地保存为本地Excel文件。这个任务看似基础实则涉及网络请求、HTML解析、反爬策略应对、数据清洗以及Excel文件操作等多个环节。它非常适合有一定Python基础希望提升自动化办公能力或数据获取技能的开发者。接下来我将详细拆解整个实现过程从环境准备、核心思路到代码实现、问题排查分享我踩过的坑和总结的经验让你不仅能完成“下载”更能理解背后的原理举一反三。2. 核心思路与技术选型解析面对“下载腾讯文档在线表格”这个需求我们不能想当然地认为页面上一定有一个.xlsx的下载链接等着我们去抓。腾讯文档这类现代在线协作文档其数据交互逻辑远比静态页面复杂。我们需要先分析其数据加载方式再决定技术路线。2.1 网页数据加载方式分析首先通过浏览器的开发者工具按F12我们通常会发现两种主要的数据呈现方式服务端渲染SSR静态表格表格的HTML结构直接存在于初始的页面源代码中。这种情况下数据是“看得见摸得着”的我们只需要解析HTML就能拿到数据。这是最简单、最理想的情况但现在大型网站为了性能和交互越来越少采用这种方式呈现核心数据。客户端动态渲染这是目前的主流方式。页面初始加载时HTML骨架是空的或者只有加载动画表格数据是通过后续的JavaScript发起的Ajax或Fetch请求从服务器获取到JSON格式的原始数据再由前端框架如React, Vue动态渲染到页面上。腾讯文档的在线表格几乎100%属于这种模式。这意味着你直接使用requests库获取网页源码很可能看不到表格数据只能看到一个空的div容器。因此我们的技术路线必须能够应对动态渲染。主要有两种主流方案方案A模拟Ajax请求直接获取JSON数据。这是最高效、最优雅的方式。通过分析浏览器网络请求找到那个返回表格数据的API接口然后直接用Python模拟这个请求拿到结构化的JSON数据。这省去了解析HTML的步骤数据最纯净。但难点在于需要破解接口的认证、参数加密或签名机制技术门槛相对较高。方案B使用无头浏览器渲染页面再解析渲染后的HTML。这是更通用、更“暴力”但更稳定的方式。我们使用像Selenium或Playwright这样的工具控制一个真正的浏览器如Chrome去访问页面等待JavaScript执行完毕、数据加载完成然后再从完全渲染好的页面DOM树中提取数据。这种方式能应对绝大多数复杂的动态页面包括需要登录、有复杂交互的场景。为什么我选择方案BSelenium作为本次讲解的核心对于腾讯文档这类可能涉及登录态查看权限、且接口逻辑可能随时变更的复杂应用直接逆向API的成本和维护风险较高。而Selenium方案更贴近真实用户操作通用性强更适合作为教学和快速解决问题的首选。它能确保我们“看到即所得”降低了初期分析的难度。当然在后续的优化部分我也会探讨如何向方案A演进。2.2 工具库选型与理由确定了使用浏览器自动化方案后我们来选择具体的工具Selenium老牌、稳定、社区资源丰富的浏览器自动化工具。它支持多种浏览器通过WebDriver进行通信。对于Python爬虫初学者来说其API直观调试方便可以实时看到浏览器操作。Playwright由微软开发的后起之秀相比Selenium它在速度、稳定性以及API设计上更有优势内置了自动等待等智能机制能更好地处理现代单页应用SPA。但学习曲线稍陡且较新。BeautifulSoup / lxmlHTML解析库。在Selenium获取到渲染后的页面源码后我们需要用它来定位和提取表格元素。pandas数据处理和分析的核心库。它不仅能轻松地将提取到的列表数据转换为DataFrame更关键的是它内置了强大的to_excel方法可以一键将数据写入Excel文件并支持设置工作表名称、索引等。openpyxl / xlsxwriterpandas写入Excel的引擎。通常我们无需直接调用pandas会自动处理。本次项目技术栈确定Selenium BeautifulSoup pandas。这是一个经典、稳健且易于理解和上手的组合。注意腾讯文档对公开链接的访问可能有简单的反爬机制如验证码或请求频率限制。我们的Selenium脚本模拟的是真人浏览行为在一定程度上能规避这类基础防护但对于需要登录才能访问的私有文档你需要先处理登录环节。本文假设你拥有文档的公开查看链接或已处理登录。3. 环境准备与核心工具详解工欲善其事必先利其器。在开始写代码之前我们需要把环境和工具准备好。这个过程虽然有些繁琐但一次配置长期受益。3.1 安装必要的Python库打开你的终端或命令提示符使用pip进行安装。建议在虚拟环境中进行以避免包版本冲突。pip install selenium beautifulsoup4 pandas lxmlselenium用于驱动浏览器。beautifulsoup4用于解析HTML。pandas用于数据处理和写入Excel。lxml是一个高效的HTML/XML解析器BeautifulSoup推荐使用它作为解析引擎速度比Python内置的html.parser快很多。3.2 配置浏览器驱动WebDriverSelenium本身不能直接控制浏览器它需要通过一个名为“WebDriver”的中间件来发送指令。你需要下载与你电脑上Chrome浏览器版本匹配的ChromeDriver。查看Chrome版本打开Chrome浏览器点击右上角三个点 - 帮助 - 关于Google Chrome记下版本号例如128.0.6613.138。下载ChromeDriver访问 ChromeDriver官方下载站 或国内镜像站。下载与你的Chrome主版本号如128完全一致的驱动。放置驱动下载后是一个可执行文件如chromedriver.exeon Windows,chromedriveron Mac/Linux。你有两个选择推荐将其所在目录添加到系统的PATH环境变量中。这样Selenium就能自动找到它。或者在代码中指定驱动的绝对路径。一个关键的避坑点浏览器会自动更新但WebDriver不会。如果某天你的脚本突然报错“This version of ChromeDriver only supports Chrome version X”就是因为两者版本不匹配了。你需要重新下载对应版本的驱动。为了解决这个问题可以考虑使用webdriver-manager这个第三方库它能自动下载和管理匹配的驱动。pip install webdriver-manager然后在代码中这样使用from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice)这样就能省去手动管理驱动的麻烦非常推荐。3.3 编写第一个探测脚本确认数据加载方式在全面开发之前我们先写一个简单的脚本来验证我们的思路并窥探页面的结构。from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager import time # 1. 设置浏览器选项可选用于调试 options webdriver.ChromeOptions() # options.add_argument(--headless) # 无头模式不显示浏览器窗口。调试时建议先注释掉。 options.add_argument(--disable-gpu) options.add_argument(--no-sandbox) # 防止被检测为自动化工具可添加以下参数非绝对有效 options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) # 2. 自动管理并启动驱动 service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice, optionsoptions) # 3. 目标URL请替换为你的腾讯文档在线表格地址 # 示例地址格式通常为https://docs.qq.com/sheet/DRVpTclduY3hQZ0pX?tabBB08J2 target_url 你的腾讯文档表格链接 driver.get(target_url) # 4. 显式等待等待表格内容加载出来 # 这是爬虫稳定性的关键不能直接用time.sleep固定等待。 try: # 假设表格加载后某个具有特定class或id的元素会出现 # 你需要用浏览器开发者工具查看表格区域的元素特征 # 例如等待一个包含表格的div出现 wait WebDriverWait(driver, 20) # 最多等待20秒 # 这里需要你根据实际页面修改定位器下面是一个示例 table_present wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, div.sheet-container)) ) print(表格区域已加载完成) except Exception as e: print(f等待表格超时或出错: {e}) driver.save_screenshot(timeout_error.png) # 保存截图便于调试 driver.quit() exit() # 5. 获取渲染后的完整页面HTML并保存下来供分析 page_html driver.page_source with open(rendered_page.html, w, encodingutf-8) as f: f.write(page_html) print(页面源码已保存到 rendered_page.html) # 6. 稍微滚动一下确保所有懒加载的数据都触发了针对长表格 driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) time.sleep(2) # 等待滚动后可能触发的加载 # 7. 再次保存看看是否有变化 page_html_after_scroll driver.page_source with open(rendered_page_after_scroll.html, w, encodingutf-8) as f: f.write(page_html_after_scroll) # 8. 关闭浏览器 driver.quit() print(探测完成请查看保存的HTML文件分析结构。)运行这个脚本后你会得到两个HTML文件。用文本编辑器或浏览器打开它们搜索表格里的文字内容比如你知道的某一行数据。如果能找到恭喜数据就在HTML里我们可以用BeautifulSoup解析。如果找不到那说明数据可能通过更复杂的API加载或者被深度隐藏在某个脚本标签里这时我们需要进一步分析网络请求在开发者工具的Network面板查看XHR/Fetch请求。4. 解析HTML与提取表格数据假设我们的探测脚本成功获取到了包含表格数据的HTML。下一步就是像外科手术一样从中精准地提取出表格的行列数据。这里需要你仔细分析保存下来的rendered_page.html文件。4.1 使用开发者工具分析表格结构打开rendered_page.html文件的同时用浏览器打开原腾讯文档页面按下F12打开开发者工具。使用元素选择器箭头图标点击工具左上角的小箭头图标然后用鼠标去点击网页表格中的某个单元格。开发者工具会自动定位到对应的HTML元素。观察结构你会发现腾讯文档的表格通常由多层div嵌套构成而不是传统的table、tr、td标签。这是现代前端框架的常见做法。你需要找到规律整个表格的外层容器是什么可能有class包含sheet-container,grid-container等。每一行Row用什么元素表示可能是div[data-row-index]。每一个单元格Cell用什么元素表示可能是div[data-col-index]并且单元格内容可能在某个子span或div里。记录特征记下这些关键元素的class名称、>from bs4 import BeautifulSoup import pandas as pd # 假设我们已经通过Selenium获得了页面源码存储在变量 page_html 中 # page_html driver.page_source soup BeautifulSoup(page_html, lxml) # 使用lxml解析引擎速度更快 # 首先找到整个表格区域。这里的选择器需要你根据实际情况修改 table_container soup.select_one(div.sheet-container) # 示例选择器 if not table_container: print(未找到表格容器请检查选择器。) # 可以尝试更通用的选择器或者打印soup.prettify()的一部分来查找 exit() data_rows [] # 查找所有行。同样选择器是关键。 # 示例寻找所有具有特定data属性的行 div[data-row-index] rows table_container.select(div[data-row-index]) for row in rows: row_data [] # 在当前行内查找所有单元格 # 示例寻找所有具有特定data属性的单元格 div[data-col-index] cells row.select(div[data-col-index]) # 如果没有按列索引的可以尝试按类名找如 div.cell # cells row.select(div.cell) for cell in cells: # 提取单元格文本。可能需要深入查找内部的span或div cell_text_elem cell.select_one(span, div.rich-text) # 尝试多种内部标签 cell_text cell_text_elem.get_text(stripTrue) if cell_text_elem else row_data.append(cell_text) if row_data: # 避免添加空行 data_rows.append(row_data) print(f共提取到 {len(data_rows)} 行数据。) for i, row in enumerate(data_rows[:3]): # 打印前3行看看 print(f第{i}行: {row})实操心得选择器的灵活运用select_one(‘div.classA’)返回找到的第一个匹配元素。select(‘div.classA’)返回所有匹配元素的列表。属性选择器非常强大例如div[data-row-index”0″]可以精确定位第一行。如果直接选择器找不到可以考虑先定位父级元素再层层深入。有时表格内容可能是通过Canvas绘制的这就不是HTML了那上述方法无效必须考虑其他方案如OCR或直接找数据接口但腾讯文档目前主流还是DOM渲染。4.3 处理分页与滚动加载如果表格很长有分页或滚动加载无限滚动我们的第一次driver.page_source可能只包含了第一屏的数据。我们需要让Selenium模拟滚动触发更多数据加载。# 接续之前的Selenium代码在获取初始HTML后 last_height driver.execute_script(return document.body.scrollHeight) scroll_pause_time 2 # 每次滚动后等待加载的时间 scroll_limit 10 # 最多滚动10次防止无限循环 for i in range(scroll_limit): # 滚动到页面底部 driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) # 等待新内容加载 time.sleep(scroll_pause_time) # 计算新的滚动高度 new_height driver.execute_script(return document.body.scrollHeight) if new_height last_height: # 如果高度不再变化说明已滚动到底部或没有更多内容 print(f滚动 {i1} 次后已加载所有内容。) break last_height new_height print(f第 {i1} 次滚动页面高度更新为: {new_height}) # 滚动完成后再次获取完整的页面源码 final_page_html driver.page_source # 然后用 final_page_html 进行解析5. 使用Pandas清洗数据并写入Excel提取到的数据列表data_rows可能包含空行、表头格式不一致等问题。Pandas的DataFrame是处理这类数据的绝佳工具。5.1 构建DataFrame并清洗# 假设 data_rows 是一个列表的列表每个子列表代表一行 import pandas as pd # 将数据转换为DataFrame # 注意这里默认第一行是表头。如果腾讯文档的表头是独立的元素你可能需要单独提取并作为column_names传入。 df pd.DataFrame(data_rows) # 查看数据概览 print(df.head()) print(df.shape) # 常见数据清洗操作 # 1. 去除完全为空的行和列 df_cleaned df.dropna(howall).dropna(axis1, howall) # 2. 重置索引 df_cleaned df_cleaned.reset_index(dropTrue) # 3. 处理表头如果第一行确实是数据表头 # 方法A将第一行设置为表头 # df_cleaned.columns df_cleaned.iloc[0] # 第一行作为列名 # df_cleaned df_cleaned[1:].reset_index(dropTrue) # 去掉原来的第一行 # 方法B如果你在解析时已经区分了表头和数据这里直接使用即可。 # 假设我们解析时没有单独处理表头且数据第一行就是表头 if not df_cleaned.empty: # 一个简单的启发式判断如果第一行看起来不像数据比如包含“序号”、“姓名”等就设为表头 potential_header df_cleaned.iloc[0] # 这里可以自定义判断逻辑例如检查是否包含特定关键词 header_keywords [序号, 名称, 日期, 备注] if any(keyword in str(cell) for cell in potential_header for keyword in header_keywords): df_cleaned.columns potential_header df_cleaned df_cleaned[1:].reset_index(dropTrue) print(已将第一行设置为表头。) print(清洗后的数据框) print(df_cleaned.head())5.2 将数据写入Excel文件使用Pandas的to_excel方法非常简单但有一些参数对生成美观的Excel文件很重要。# 定义输出文件名 output_filename 腾讯文档表格数据.xlsx # 使用 pandas 的 ExcelWriter 可以更灵活地控制例如写入多个sheet with pd.ExcelWriter(output_filename, engineopenpyxl) as writer: df_cleaned.to_excel(writer, sheet_nameSheet1, indexFalse) # indexFalse 不写入行索引 # 你可以在这里继续写入其他的DataFrame到不同的sheet # df2.to_excel(writer, sheet_nameSheet2, indexFalse) # 高级设置调整列宽需要openpyxl from openpyxl import load_workbook wb load_workbook(output_filename) ws wb.active # 自动调整列宽近似 for column in ws.columns: max_length 0 column_letter column[0].column_letter # 获取列字母 for cell in column: try: cell_value_len len(str(cell.value)) if cell_value_len max_length: max_length cell_value_len except: pass adjusted_width (max_length 2) * 1.2 # 加一点边距 ws.column_dimensions[column_letter].width min(adjusted_width, 50) # 设置最大宽度 wb.save(output_filename) print(f数据已成功写入到 {output_filename})注意openpyxl是处理.xlsx格式的库如果你没有安装pandas会默认使用它如果已安装或xlsxwriter。确保你的环境里至少有一个。通常安装pandas时会推荐安装openpyxl。6. 完整脚本整合与优化现在我们将所有步骤整合成一个完整、健壮的脚本。这个脚本包含了错误处理、等待逻辑、数据提取和保存。import time from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager from bs4 import BeautifulSoup import pandas as pd from openpyxl import load_workbook def fetch_table_from_tencent_docs(url, output_exceltencent_docs_output.xlsx, headlessFalse): 从腾讯文档在线表格抓取数据并保存为Excel。 参数: url (str): 腾讯文档表格的公开链接。 output_excel (str): 输出的Excel文件名。 headless (bool): 是否使用无头模式不显示浏览器窗口。 print(f开始抓取: {url}) # 1. 设置浏览器选项 options webdriver.ChromeOptions() if headless: options.add_argument(--headless) options.add_argument(--disable-gpu) options.add_argument(--no-sandbox) options.add_argument(--disable-dev-shm-usage) # 添加一些参数避免被检测 options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) options.add_argument(--disable-blink-featuresAutomationControlled) # 2. 初始化浏览器驱动 service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice, optionsoptions) driver.implicitly_wait(10) # 隐式等待全局生效 try: # 3. 访问目标页面 driver.get(url) print(页面加载中...) # 4. 显式等待表格核心区域出现 - **这是最关键的一步选择器需要你自定义** # 你需要用开发者工具找到表格加载完成后出现的某个稳定元素的定位方式。 # 示例等待一个包含‘sheet’或‘grid’的类出现 wait WebDriverWait(driver, 30) # 延长等待时间 try: # 尝试多种可能的定位器增加鲁棒性 table_ready wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, div[class*sheet], div[class*grid], div[rolegrid]) )) print(表格主体加载完成。) except Exception as e: print(f等待表格主体超时: {e}) driver.save_screenshot(wait_timeout.png) # 即使没等到特定元素也继续执行可能页面结构不同 pass # 5. 模拟滚动加载所有数据 print(开始滚动加载潜在的分页数据...) last_height driver.execute_script(return document.body.scrollHeight) for _ in range(15): # 最多滚动15次 driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) time.sleep(1.5) # 等待滚动加载 new_height driver.execute_script(return document.body.scrollHeight) if new_height last_height: break last_height new_height print(滚动加载完毕。) time.sleep(2) # 最终等待一下 # 6. 获取最终页面源码并解析 final_html driver.page_source soup BeautifulSoup(final_html, lxml) # **7. 数据提取 - 这部分需要你根据实际页面结构仔细调整** # 这里是一个通用性较强的示例通过查找所有类似行的元素来提取。 all_rows [] # 假设每一行数据在一个具有‘data-row-index’属性的div里 row_elements soup.select(div[data-row-index]) if not row_elements: # 如果上述选择器无效尝试更通用的方法寻找可能是表格行的元素 print(未找到按data-row-index标记的行尝试通用查找...) # 可以尝试查找具有特定样式的行容器 row_elements soup.select(div.sheet-row, .grid-row) for row_elem in row_elements: row_data [] # 在每一行里查找单元格 cell_elements row_elem.select(div[data-col-index], .cell, [class*cell-]) for cell_elem in cell_elements: # 提取文本可能需要深入内部元素 text_elem cell_elem.find([span, div], class_lambda x: x and (text in str(x).lower() or value in str(x).lower())) cell_text text_elem.get_text(stripTrue) if text_elem else cell_elem.get_text(stripTrue) row_data.append(cell_text) if row_data: # 只添加非空行 all_rows.append(row_data) if not all_rows: print(警告未提取到任何数据行。请检查HTML结构和选择器。) # 可以将HTML保存下来供手动分析 with open(debug_page.html, w, encodingutf-8) as f: f.write(final_html) print(已保存页面HTML到 debug_page.html请手动分析。) return False print(f共提取到 {len(all_rows)} 行原始数据。) # 8. 使用Pandas进行数据清洗和保存 df pd.DataFrame(all_rows) # 基础清洗去除全空行/列 df_cleaned df.dropna(howall).dropna(axis1, howall).reset_index(dropTrue) # 智能判断表头如果第一行看起来像中文表头包含常见字段词则设为表头 if not df_cleaned.empty and len(df_cleaned) 1: first_row df_cleaned.iloc[0].astype(str).str.cat(sep ) header_indicators [姓名, 账号, 日期, 时间, 状态, 备注, 数量, 金额, 序号, 编号] if any(indicator in first_row for indicator in header_indicators): df_cleaned.columns df_cleaned.iloc[0] df_cleaned df_cleaned[1:].reset_index(dropTrue) print(已自动识别并设置第一行为表头。) # 写入Excel with pd.ExcelWriter(output_excel, engineopenpyxl) as writer: df_cleaned.to_excel(writer, indexFalse, sheet_name数据) # 可选调整列宽 try: wb load_workbook(output_excel) ws wb.active for col in ws.columns: max_length 0 col_letter col[0].column_letter for cell in col: try: cell_length len(str(cell.value)) if cell_length max_length: max_length cell_length except: pass adjusted_width min((max_length 2), 50) ws.column_dimensions[col_letter].width adjusted_width wb.save(output_excel) except Exception as e: print(f调整列宽时出错不影响数据保存: {e}) print(f数据已成功保存至: {output_excel}) print(f数据形状: {df_cleaned.shape}) return True except Exception as e: print(f抓取过程中发生错误: {e}) import traceback traceback.print_exc() return False finally: # 9. 无论如何最后都要关闭浏览器 driver.quit() print(浏览器已关闭。) # 使用示例 if __name__ __main__: # 替换成你的腾讯文档表格链接 doc_url https://docs.qq.com/sheet/你的表格ID?tab你的标签页 success fetch_table_from_tencent_docs(doc_url, headlessFalse) # 调试时设为False可以看到浏览器操作 if success: print(任务完成) else: print(任务失败请根据提示检查。)7. 常见问题、反爬策略与进阶优化即使有了完整脚本在实际运行中你依然会遇到各种问题。下面是我总结的一些常见坑点和解决方案。7.1 常见错误与排查表问题现象可能原因排查与解决方案TimeoutException等待超时1. 网络慢或页面加载时间长。2. 选择器定位的元素不存在或名称错误。3. 页面需要登录或有弹窗遮挡。1. 增加WebDriverWait的等待时间如30秒。2.使用driver.save_screenshot(‘error.png’)保存截图查看页面实际状态。3. 检查选择器是否正确。尝试更通用或更具体的CSS选择器。4. 手动访问链接看是否需要登录如需登录则先处理登录逻辑见7.2。提取到的数据为空 (all_rows为空)1. 表格数据是Canvas绘制或通过更复杂的JS加载不在DOM中。2. 数据在iframe内。3. 选择器完全错误。1. 检查保存的debug_page.html搜索你知道的表格内容。搜不到可能是Canvas或接口数据。2. 查看页面是否有iframe需要driver.switch_to.frame切换。3.分析网络请求在开发者工具Network面板过滤XHR/Fetch刷新页面看是否有包含表格数据的API请求。这是进阶方向。数据错位或包含大量空白/无关元素1. 单元格选择器过于宽泛抓到了非表格元素。2. 表格结构复杂有合并单元格或浮动元素。1. 精细化你的选择器。使用开发者工具仔细分析目标单元格的唯一特征如特定的class组合、属性。2. 尝试从行元素.find_all子元素而不是全局select。被网站检测到自动化工具网站检测到webdriver属性或某些自动化特征。1. 添加本文代码中的excludeSwitches和useAutomationExtension选项。2. 可以尝试添加--disable-blink-featuresAutomationControlled。3. 使用undetected-chromedriver库更高级的反反爬。只能抓到第一屏数据表格是滚动懒加载但滚动逻辑没触发或等待时间不足。1. 确保滚动代码执行了。检查new_height是否变化。2. 增加滚动后的等待时间time.sleep。3. 尝试滚动到特定元素driver.execute_script(“arguments[0].scrollIntoView();”, element)。7.2 处理登录与权限如果文档是私有的需要登录才能查看你需要在脚本中增加登录环节。核心思路用Selenium打开登录页面如腾讯文档首页或统一的登录页。定位账号、密码输入框输入你的凭据重要切勿将密码硬编码在代码中使用环境变量或配置文件。点击登录按钮。等待登录成功如跳转或出现用户头像。再访问目标文档链接。def login_tencent_docs(driver, username, password): 模拟登录腾讯文档示例实际选择器需根据登录页调整 login_url https://docs.qq.com/login # 示例登录页 driver.get(login_url) time.sleep(3) # 可能需要切换登录方式这里以账号密码为例 # 定位输入框并输入 user_input driver.find_element(By.ID, “username-input-id”) # 替换为实际ID user_input.send_keys(username) pwd_input driver.find_element(By.ID, “password-input-id”) pwd_input.send_keys(password) # 点击登录按钮 login_btn driver.find_element(By.CSS_SELECTOR, “button.login-btn”) login_btn.click() # 等待登录成功 WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CLASS_NAME, “user-avatar”)) # 替换为登录成功后的标志元素 ) print(“登录成功”) # 登录后cookies会保存在driver中后续访问私有链接即可。安全警告绝对不要将真实的账号密码写在脚本里并上传到Git等公共平台。请使用os.environ.get(‘TENCENT_USERNAME’)从环境变量读取或使用input()函数在运行时手动输入。7.3 进阶优化直接请求数据接口方案A如果通过分析网络请求你找到了返回纯JSON数据的API那么效率将大大提升。这需要一些前端知识。在目标页面按F12打开开发者工具切换到Network网络面板。刷新页面在类型筛选里选择XHR或Fetch。观察请求列表寻找名称包含sheet,data,cell,range或看起来像数据接口的请求。点击该请求查看Headers和Preview。Headers复制Request URL接口地址查看Request Method通常是GET或POST以及关键的Headers如Authorization,Cookie,Referer,User-Agent和一些自定义签名头。Preview查看返回的数据结构是否是包含行列信息的JSON。如果接口没有复杂的加密签名你可以尝试用requests库直接模拟import requests import json headers { ‘User-Agent’: ‘Mozilla/5.0 ...‘, ‘Referer’: ‘你的腾讯文档链接‘, ‘Cookie’: ‘从浏览器复制过来的完整Cookie字符串‘, # 注意Cookie会过期 # 可能还需要其他认证头 } api_url “你找到的API地址” response requests.get(api_url, headersheaders) if response.status_code 200: data response.json() # 根据JSON结构解析出表格数据 # 例如数据可能在 data[sheets][0][rows] 里 # 然后将其转换为列表再用pandas处理这种方式更快更省资源但维护成本高。一旦腾讯文档更新接口或加密方式脚本就会失效。而Selenium方案虽然慢但更接近真实用户稳定性更好。对于长期稳定的爬取任务建议先用Selenium方案跑通再尝试逆向接口作为优化。最后记得尊重网站的服务条款和robots.txt合理控制请求频率避免对目标服务器造成压力。将爬虫用于个人学习、自动化办公或获取公开数据是常见的用途但切勿用于大规模商业爬取或侵犯隐私。
返回列表