鱼C论坛

 找回密码
 立即注册
12
返回列表 发新帖
楼主: shadowmage

[已解决]@FishC,想要编一个抓取基金净值,并进行计算的程序

[复制链接]
 楼主| 发表于 2024-10-11 08:47:33 | 显示全部楼层
FishC 发表于 2024-10-11 08:45
将 VBA 代码转换为 Python,可以使用 `requests` 库来发送 HTTP 请求,`re` 模块进行正则表达式匹配,` ...

我是说,请把下面这些VBA代码,转成Python。
Sub GetUrlData()
    Dim sURL As String, sCode As String, oRegExp As Object, nPage As Long, nPages As Long, nRecords As Long, sResponseText As String
    Dim vData As Variant, nI As Long, nJ As Long, oReg As Object, vFill As Variant, nRow As Double, nCol As Long, ws As Worksheet
    
    ' 关闭屏幕更新和警告,提高代码执行效率
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    ' 设置引用到【基金净值】工作表
    Set ws = ThisWorkbook.Worksheets("基金净值")
    ' 获取A1单元格的值,并转换为字符串
    sCode = CStr(ws.Range("A1").Value)
    ' 使用字符串函数Left和String来确保sCode是6位数字
    ' 如果不足6位,则在前面补0
    sCode = String(6 - Len(sCode), "0") & sCode
    ' 创建正则表达式对象,用于字符串匹配
    Set oRegExp = CreateObject("VBSCRIPT.REGEXP")
    ' 设置正则表达式为全局匹配模式
    oRegExp.Global = True
    ' 清空工作表中的所有单元格内容
    Cells.Clear
    ' 初始化页面计数器
    nPage = 1
    ' 构建基金数据API的URL,其中[Page]是页码占位符
    sURL = "http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=" & sCode & "&page=[Page]&per=2000"
    ' 创建XMLHTTP对象,用于发送网络请求
    With CreateObject("msXML2.ServerXMLHttp")
        ' 循环直到所有页面都被请求和处理
        Do While nPage = 1 Or nPage <= nPages
            ' 发送GET请求,替换URL中的[Page]为当前页码
            .Open "GET", Replace(sURL, "[Page]", nPage), True
            ' 发送请求
            .Send
            ' 等待请求完成
            While .ReadyState <> 4
                DoEvents
            Wend
                
            ' 获取响应文本
            sResponseText = .ResponseText
            ' 使用正则表达式解析响应文本
            With oRegExp
                ' 如果还未获取总记录数和总页数,则先进行匹配
                If nPages = 0 Then
                    ' 设置正则表达式模式,匹配记录数和页数
                    .Pattern = "records[^\d]+(\d+)[^\d]+pages[^\d]+(\d+)"
                    ' 执行匹配
                    Set oReg = .Execute(sResponseText)
                    ' 如果匹配到结果,则提取记录数和页数
                    If oReg.Count > 0 Then
                        nRecords = Val(oReg(0).SubMatches(0))
                        nPages = Val(oReg(0).SubMatches(1))
                    End If
                    ' 设置正则表达式模式,匹配表头
                    .Pattern = "<th([^>]+)?>([^<]+)<"
                    ' 执行匹配
                    Set oReg = .Execute(sResponseText)
                    ' 如果匹配到结果,则初始化数据数组
                    If oReg.Count > 0 Then
                        ReDim vFill(1 To nRecords + 1, 1 To oReg.Count + 1)
                        ' 在数据数组的第1行第1列存储基金代码
                        vFill(1, 1) = sCode
                        ' 遍历匹配到的表头,存储在数据数组的第1行
                        For nCol = 1 To oReg.Count
                            vFill(1, nCol + 1) = oReg(nCol - 1).SubMatches(1)
                        Next
                    End If
                    ' 初始化列和行计数器
                    nCol = 8
                    nRow = 1
                    ' 设置正则表达式模式,匹配表格数据
                    .Pattern = "<td([^>]+)?>([^<]+)?<"
                End If
                ' 使用正则表达式匹配响应文本中的数据
                Set oReg = .Execute(sResponseText)
                ' 如果匹配到数据
                If oReg.Count > 0 Then
                    ' 初始化循环计数器
                    nI = 0
                    ' 循环遍历匹配到的数据
                    Do While nI + 1 < oReg.Count
                        ' 获取当前匹配的数据
                        sCode = oReg(nI).SubMatches(1)
                        ' 检查数据是否是日期格式(假设日期格式为"年-月-日")
                        If sCode Like "*-*-*" Then
                            ' 如果是日期,则列计数器重置为2,表示日期列
                            nCol = 2
                            ' 行计数器加1,准备写入下一行的数据
                            nRow = nRow + 1
                            ' 在数据数组的第1列存储行号(假设第1列用于存储序号)
                            vFill(nRow, 1) = nRow - 1
                        Else
                            ' 如果不是日期,则列计数器加1,准备写入下一列的数据
                            nCol = nCol + 1
                        End If
                        ' 在数据数组中存储当前匹配的数据
                        vFill(nRow, nCol) = oReg(nI).SubMatches(1)
                        ' 循环计数器加1
                        nI = nI + 1
                    Loop
                End If
            End With
            ' 页码计数器加1,准备请求下一页数据
            nPage = nPage + 1
        Loop
    End With
    
    ' 将数据数组写入工作表的指定区域
    With [A1].Resize(UBound(vFill), UBound(vFill, 2))
        ' 设置日期列的格式为"年-月-日"
        .Offset(, 1).Resize(, 1).NumberFormatLocal = "yyyy-m-d"
        ' 设置数值列的格式为千分位分隔,保留4位小数
        .Offset(, 2).Resize(, 2).NumberFormatLocal = "_ * #,##0.0000_ ;_ * -#,##0.0000_ ;_ * ""-""????_ ;_ @_ "
        ' 设置百分比列的格式为百分比,保留2位小数
        .Offset(, 4).Resize(, 1).NumberFormatLocal = "0.00%"
        ' 将数据数组的内容写入工作表
        .Formula = vFill
        ' 自动调整列宽以适应内容
        .EntireColumn.AutoFit
        ' 设置水平对齐方式为居中
        .HorizontalAlignment = xlCenter
        ' 设置垂直对齐方式为底部对齐
        .VerticalAlignment = xlBottom
    End With
    ' 重新开启屏幕更新和警告
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-11 08:47:39 | 显示全部楼层
shadowmage 发表于 2024-10-11 08:47
我是说,请把下面这些VBA代码,转成Python。
Sub Get ...


要将 VBA 代码转换为 Python,你可以使用 `requests` 库进行 HTTP 请求,用 `re` 模块进行正则表达式匹配,并使用 `openpyxl` 或 `pandas` 进行 Excel 数据的处理。以下是对应的 Python 示例代码:

```python
import requests
import re
from openpyxl import Workbook, load_workbook

def get_url_data():
    # 加载 Excel 文件并获取工作表
    wb = load_workbook('your_file.xlsx')
    ws = wb['基金净值']
   
    # 获取A1单元格的值作为基金代码,并确保是6位数字
    sCode = str(ws

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-11 09:17:11 | 显示全部楼层
FishC 发表于 2024-10-11 08:45
将 VBA 代码转换为 Python,可以使用 `requests` 库来发送 HTTP 请求,`re` 模块进行正则表达式匹配,` ...

这一段Python代码,缺少原VBA代码的以下功能:
1,获取某个sheet的A1单元格的值。我需要这个功能,假设是要获取Py程序同目录下的【工具.xlsm】的sheet【期初数据】,从A列【基金代码】中依次选取;
2,清空工作表中所有单元格内容。我需要清空【工具.xlsm】的sheet【基金净值】。
3,构建基金数据API的Url,这个需要重新加进去。
4,页码计数器+1,准备下一页数据,这个也是需要加进去的。
5,将获取到的数据写入工作表指定区域,即前面提到的sheet【基金净值】。

我再发一下代码,请你逐行比对着改写一下。
Sub GetUrlData()
    Dim sURL As String, sCode As String, oRegExp As Object, nPage As Long, nPages As Long, nRecords As Long, sResponseText As String
    Dim vData As Variant, nI As Long, nJ As Long, oReg As Object, vFill As Variant, nRow As Double, nCol As Long, ws As Worksheet
    
    ' 关闭屏幕更新和警告,提高代码执行效率
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    ' 设置引用到【基金净值】工作表
    Set ws = ThisWorkbook.Worksheets("基金净值")
    ' 获取A1单元格的值,并转换为字符串
    sCode = CStr(ws.Range("A1").Value)
    ' 使用字符串函数Left和String来确保sCode是6位数字
    ' 如果不足6位,则在前面补0
    sCode = String(6 - Len(sCode), "0") & sCode
    ' 创建正则表达式对象,用于字符串匹配
    Set oRegExp = CreateObject("VBSCRIPT.REGEXP")
    ' 设置正则表达式为全局匹配模式
    oRegExp.Global = True
    ' 清空工作表中的所有单元格内容
    Cells.Clear
    ' 初始化页面计数器
    nPage = 1
    ' 构建基金数据API的URL,其中[Page]是页码占位符
    sURL = "http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=" & sCode & "&page=[Page]&per=2000"
    ' 创建XMLHTTP对象,用于发送网络请求
    With CreateObject("msXML2.ServerXMLHttp")
        ' 循环直到所有页面都被请求和处理
        Do While nPage = 1 Or nPage <= nPages
            ' 发送GET请求,替换URL中的[Page]为当前页码
            .Open "GET", Replace(sURL, "[Page]", nPage), True
            ' 发送请求
            .Send
            ' 等待请求完成
            While .ReadyState <> 4
                DoEvents
            Wend
                
            ' 获取响应文本
            sResponseText = .ResponseText
            ' 使用正则表达式解析响应文本
            With oRegExp
                ' 如果还未获取总记录数和总页数,则先进行匹配
                If nPages = 0 Then
                    ' 设置正则表达式模式,匹配记录数和页数
                    .Pattern = "records[^\d]+(\d+)[^\d]+pages[^\d]+(\d+)"
                    ' 执行匹配
                    Set oReg = .Execute(sResponseText)
                    ' 如果匹配到结果,则提取记录数和页数
                    If oReg.Count > 0 Then
                        nRecords = Val(oReg(0).SubMatches(0))
                        nPages = Val(oReg(0).SubMatches(1))
                    End If
                    ' 设置正则表达式模式,匹配表头
                    .Pattern = "<th([^>]+)?>([^<]+)<"
                    ' 执行匹配
                    Set oReg = .Execute(sResponseText)
                    ' 如果匹配到结果,则初始化数据数组
                    If oReg.Count > 0 Then
                        ReDim vFill(1 To nRecords + 1, 1 To oReg.Count + 1)
                        ' 在数据数组的第1行第1列存储基金代码
                        vFill(1, 1) = sCode
                        ' 遍历匹配到的表头,存储在数据数组的第1行
                        For nCol = 1 To oReg.Count
                            vFill(1, nCol + 1) = oReg(nCol - 1).SubMatches(1)
                        Next
                    End If
                    ' 初始化列和行计数器
                    nCol = 8
                    nRow = 1
                    ' 设置正则表达式模式,匹配表格数据
                    .Pattern = "<td([^>]+)?>([^<]+)?<"
                End If
                ' 使用正则表达式匹配响应文本中的数据
                Set oReg = .Execute(sResponseText)
                ' 如果匹配到数据
                If oReg.Count > 0 Then
                    ' 初始化循环计数器
                    nI = 0
                    ' 循环遍历匹配到的数据
                    Do While nI + 1 < oReg.Count
                        ' 获取当前匹配的数据
                        sCode = oReg(nI).SubMatches(1)
                        ' 检查数据是否是日期格式(假设日期格式为"年-月-日")
                        If sCode Like "*-*-*" Then
                            ' 如果是日期,则列计数器重置为2,表示日期列
                            nCol = 2
                            ' 行计数器加1,准备写入下一行的数据
                            nRow = nRow + 1
                            ' 在数据数组的第1列存储行号(假设第1列用于存储序号)
                            vFill(nRow, 1) = nRow - 1
                        Else
                            ' 如果不是日期,则列计数器加1,准备写入下一列的数据
                            nCol = nCol + 1
                        End If
                        ' 在数据数组中存储当前匹配的数据
                        vFill(nRow, nCol) = oReg(nI).SubMatches(1)
                        ' 循环计数器加1
                        nI = nI + 1
                    Loop
                End If
            End With
            ' 页码计数器加1,准备请求下一页数据
            nPage = nPage + 1
        Loop
    End With
    
    ' 将数据数组写入工作表的指定区域
    With [A1].Resize(UBound(vFill), UBound(vFill, 2))
        ' 设置日期列的格式为"年-月-日"
        .Offset(, 1).Resize(, 1).NumberFormatLocal = "yyyy-m-d"
        ' 设置数值列的格式为千分位分隔,保留4位小数
        .Offset(, 2).Resize(, 2).NumberFormatLocal = "_ * #,##0.0000_ ;_ * -#,##0.0000_ ;_ * ""-""????_ ;_ @_ "
        ' 设置百分比列的格式为百分比,保留2位小数
        .Offset(, 4).Resize(, 1).NumberFormatLocal = "0.00%"
        ' 将数据数组的内容写入工作表
        .Formula = vFill
        ' 自动调整列宽以适应内容
        .EntireColumn.AutoFit
        ' 设置水平对齐方式为居中
        .HorizontalAlignment = xlCenter
        ' 设置垂直对齐方式为底部对齐
        .VerticalAlignment = xlBottom
    End With
    ' 重新开启屏幕更新和警告
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-11 09:17:15 | 显示全部楼层
shadowmage 发表于 2024-10-11 09:17
这一段Python代码,缺少原VBA代码的以下功能:
1,获 ...


下面是您请求的将VBA代码转换为Python的实现,包括所需的功能:

```python
import requests
import re
import openpyxl
import os

def get_url_data():
    # 定义文件路径和读取Excel文件
    file_path = '工具.xlsm'
    workbook = openpyxl.load_workbook(file_path, keep_vba=True)

    # 引用【期初数据】工作表
    initial_data_sheet = workbook['期初数据']
    # 引用【基金净值】工作表

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 17:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表