调用新浪财经盈利分析API分页获取数据时部分页面行数缺失问题排查
问题排查与解决方案
我之前碰到过类似的新浪财经内容爬取异常问题,咱们一步步拆解原因并给出解决思路:
可能的核心原因
1. 反爬机制导致返回内容截断
新浪财经对请求头不完整的请求会返回部分截断的HTML内容。你的代码只设置了User-Agent,缺少Cookie、Referer等关键请求头字段,服务器可能判定你为非正常访问,从而返回不完整的表格数据——这也是你提到的特定页面(3、38、73等)出现行数缺失的主要原因。
2. 编码问题引发解析错误
新浪财经页面采用gb2312编码,你的代码直接读取二进制数据后解析,若编码处理不当,可能导致HTML内容乱码,进而让lxml解析时丢失部分行数据。
3. 动态内容加载(概率较低)
少数页面可能通过JavaScript懒加载表格行,而urllib.request只能获取初始静态HTML,无法加载动态生成的内容,但这种情况在你提到的页面中出现概率不高。
验证步骤
先确认问题出在请求环节还是解析环节:在函数中添加代码,把返回的HTML保存到本地文件,打开查看实际内容:
with open(f"page_{page}.html", "wb") as f: f.write(data_string)
如果本地文件里表格确实只有26行,说明服务器返回内容不完整;如果本地文件有完整的41行,那就是解析环节出了问题。
针对性解决方案
方案1:完善请求头并处理编码
复制浏览器中正常访问该页面的请求头(用F12的Network面板获取),补充Cookie、Referer字段,并设置正确的编码:
def get_rows(page): import urllib.request import lxml.html url = "http://vip.stock.finance.sina.com.cn/q/go.php/vFinanceAnalyze/kind/profit/"\ "index.phtml?s_i=&s_a=&s_c=&reportdate=2021&quarter=4&p={}".format(page) table_xpath = '//*[@id="dataTable"]' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', 'Referer': 'http://vip.stock.finance.sina.com.cn/q/go.php/vFinanceAnalyze/kind/profit/index.phtml', 'Cookie': '这里填入你浏览器中复制的Cookie内容' } req = urllib.request.Request(url=url, headers=headers) data_string=urllib.request.urlopen(req).read() # 处理编码,避免乱码 data_string = data_string.decode('gb2312', errors='ignore').encode('utf-8') root=lxml.html.fromstring(data_string) dtable = root.xpath(table_xpath)[0] rows = dtable.xpath('.//tr') print(len(rows))
注意:Cookie有有效期,需要定期从浏览器中更新。
方案2:改用requests库简化请求管理
requests库更易用,能维持会话状态,减少反爬触发概率:
import requests from lxml import html def get_rows(page): url = "http://vip.stock.finance.sina.com.cn/q/go.php/vFinanceAnalyze/kind/profit/index.phtml?s_i=&s_a=&s_c=&reportdate=2021&quarter=4&p={}".format(page) table_xpath = '//*[@id="dataTable"]' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', 'Referer': 'http://vip.stock.finance.sina.com.cn/q/go.php/vFinanceAnalyze/kind/profit/index.phtml' } # 维持会话,模拟浏览器访问状态 session = requests.Session() response = session.get(url, headers=headers) response.encoding = 'gb2312' # 直接设置正确编码 root = html.fromstring(response.text) dtable = root.xpath(table_xpath)[0] rows = dtable.xpath('.//tr') print(len(rows))
方案3:添加请求间隔避免频繁访问
如果是请求频率过高触发反爬,可在每次请求后添加延迟:
import time # 在函数末尾添加延迟 time.sleep(1)
内容的提问来源于stack exchange,提问作者showkey




