You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

调用新浪财经盈利分析API分页获取数据时部分页面行数缺失问题排查

问题排查与解决方案

我之前碰到过类似的新浪财经内容爬取异常问题,咱们一步步拆解原因并给出解决思路:

可能的核心原因

1. 反爬机制导致返回内容截断

新浪财经对请求头不完整的请求会返回部分截断的HTML内容。你的代码只设置了User-Agent,缺少CookieReferer等关键请求头字段,服务器可能判定你为非正常访问,从而返回不完整的表格数据——这也是你提到的特定页面(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面板获取),补充CookieReferer字段,并设置正确的编码:

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

火山引擎 最新活动