注册 登录
编程论坛 VFP论坛

老师好,又来请教了,这个网页的采集入口如何找,谢谢

jinanshui 发布于 2021-05-31 10:36, 7804 次点击
老师好,又来请教了,这个网页的数据采集入口如何找,谢谢,我用开发者工具找了很长时间,没找到
https://www.lottery.
只有本站会员才能查看附件,请 登录

56 回复
#2
sdta2021-05-31 11:01
只有本站会员才能查看附件,请 登录

{"dataFrom":"","emptyFlag":false,"errorCode":"0","errorMessage":"处理成功","success":true,"value":{"dlt":{"drawPdfUrl":"https://pdf.,"isGetKjpdf":1,"lotteryDrawNum":"21060","lotteryDrawResult":"09 13 25 31 33 03 07","lotteryDrawTime":"2021-05-29 20:24:38","lotteryEquipmentCount":1,"lotteryGameName":"大乐透","lotteryGameNum":"85","lotterySaleBeginTime":"2021-05-26 20:10:00","lotterySaleEndtime":"2021-05-29 20:00:00","lotteryUnsortDrawresult":"09 33 31 25 13 07 03","poolBalanceAfterdraw":"509,405,220.73","ruleType":0,"termList":["21060","21059","21058","21057","21056","21055","21054","21053","21052","21051","21050","21049","21048","21047","21046","21045","21044","21043","21042","21041","21040","21039","21038","21037","21036","21035","21034","21033","21032","21031","21030","21029","21028","21027","21026","21025","21024","21023","21022","21021","21020","21019","21018","21017","21016","21015","21014","21013","21012","21011"]},"fj225":{},"fj317":{},"fj317fj":{},"fj367":{},"hlj61":{},"hn41":{},"js7":{},"pls":{},"plw":{},"qxc":{},"zj205":{},"zj61":{}}}
#3
jinanshui2021-05-31 15:31
回复 2楼 sdta
谢谢老师,学习了,正在探索如何采集各期的数据,请老师不吝赐教..
#4
sdta2021-05-31 16:02
先学基础,解析JSON数据
#5
吹水佬2021-05-31 16:44
回复 3楼 jinanshui
是“历史开奖”
https://webapi.

[此贴子已经被作者于2021-5-31 16:51编辑过]

#6
吹水佬2021-05-31 16:49
通常这类数据相对较大,刷新一下 Network,再点击 Size 排一下就找到
#7
jinanshui2021-05-31 21:37
以下是引用吹水佬在2021-5-31 16:49:15的发言:

通常这类数据相对较大,刷新一下 Network,再点击 Size 排一下就找到



老师,球号可以找到,但是这个期数这表达式怎么有错误?谢谢,不呈现
CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2))
lcUrl = "https://webapi.
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", lcUrl, .F.)
oHTTP.SETREQUESTHEADER("Content-Type", "text/html;charset=UTF-8")
oHTTP.Send()
lcText = STRCONV(oHTTP.ResponseBody, 11)
lcText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList')
lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"')
?? lcText ,lyText
#8
sdta2021-05-31 22:45
21061期
只有本站会员才能查看附件,请 登录
#9
sdta2021-05-31 23:04
21061期开奖详细数据
drawFlowFund
"0"
drawFlowFundRj
""
estimateDrawTime
""
isGetKjpdf
1
isGetXlpdf
2
lotteryDrawNum
"21061"
lotteryDrawResult
"15 19 20 26 32 04 07"
lotteryDrawStatus
20
lotteryDrawTime
"2021-05-31"
lotteryEquipmentCount
2
lotteryGameName
"超级大乐透"
lotteryGameNum
"85"
lotteryGamePronum
0
lotteryPromotionFlag
0
lotterySaleBeginTime
"2021-05-29 20:10:00"
lotterySaleEndTimeUnix
0
lotterySaleEndtime
"2021-05-31 20:00:00"
lotterySuspendedFlag
0
lotteryUnsortDrawresult
"15+32+26+19+20 07+04"
matchList
[]
pdfType
1
poolBalanceAfterdraw
"502,877,803.60"
poolBalanceAfterdrawRj
""
prizeLevelList

awardType
0
group
"101"
lotteryCondition
""
prizeLevel
"一等奖"
sort
101
stakeAmount
"6484687"
stakeCount
"7"
totalPrizeamount
"45392809"
awardType
0
group
"201"
lotteryCondition
""
prizeLevel
"一等奖(追加)"
sort
201
stakeAmount
"5187749"
stakeCount
"3"
totalPrizeamount
"15563247"
awardType
0
group
"301"
lotteryCondition
""
prizeLevel
"二等奖"
sort
301
stakeAmount
"115599"
stakeCount
"100"
totalPrizeamount
"11559900"
awardType
0
group
"401"
lotteryCondition
""
prizeLevel
"二等奖(追加)"
sort
401
stakeAmount
"92479"
stakeCount
"41"
totalPrizeamount
"3791639"
awardType
0
group
"501"
lotteryCondition
""
prizeLevel
"三等奖"
sort
501
stakeAmount
"10000"
stakeCount
"230"
totalPrizeamount
"2300000"
awardType
0
group
"601"
lotteryCondition
""
prizeLevel
"四等奖"
sort
601
stakeAmount
"3000"
stakeCount
"1,032"
totalPrizeamount
"3096000"
awardType
0
group
"701"
lotteryCondition
""
prizeLevel
"五等奖"
sort
701
stakeAmount
"300"
stakeCount
"18,516"
totalPrizeamount
"5554800"
awardType
0
group
"801"
lotteryCondition
""
prizeLevel
"六等奖"
sort
801
stakeAmount
"200"
stakeCount
"32,712"
totalPrizeamount
"6542400"
awardType
0
group
"901"
lotteryCondition
""
prizeLevel
"七等奖"
sort
901
stakeAmount
"100"
stakeCount
"33,028"
totalPrizeamount
"3302800"
awardType
0
group
"1001"
lotteryCondition
""
prizeLevel
"八等奖"
sort
1001
stakeAmount
"15"
stakeCount
"909,788"
totalPrizeamount
"13646820"
awardType
0
group
"1101"
lotteryCondition
""
prizeLevel
"九等奖"
sort
1101
stakeAmount
"5"
stakeCount
"8,985,884"
totalPrizeamount
"44929420"

prizeLevelListRj
[]
ruleType
0
termList
[]
totalSaleAmount
"304,392,970"
totalSaleAmountRj
""
verify
1
vtoolsConfig
#10
sdta2021-05-31 23:26
以下是引用jinanshui在2021-5-31 21:37:48的发言:




老师,球号可以找到,但是这个期数这表达式怎么有错误?谢谢,不呈现
CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2))
lcUrl = "https://webapi.
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", lcUrl, .F.)
oHTTP.SETREQUESTHEADER("Content-Type", "text/html;charset=UTF-8")
oHTTP.Send()
lcText = STRCONV(oHTTP.ResponseBody, 11)
lcText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList')
lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"')
?? lcText ,lyText


顺序调整下即可
lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"')
lcText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList')
?? lcText ,lyText
#11
jinanshui2021-06-01 06:59
以下是引用sdta在2021-5-31 23:26:12的发言:

顺序调整下即可
lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"')
lcText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList')
?? lcText ,lyText



谢谢老师,最难的遍历来了,怎样一期一组,全部找出来呢?尝试了一晚上,也没找到,学不会,再次请教老师.

[此贴子已经被作者于2021-6-1 07:02编辑过]

#12
sdta2021-06-01 07:19
下载数据用时比较长(8秒左右),解析数据应该能控制在1秒内
#13
jinanshui2021-06-01 07:43
以下是引用sdta在2021-6-1 07:19:55的发言:

下载数据用时比较长(8秒左右),解析数据应该能控制在1秒内

老师,您是大神级高手,我是一个小菜鸟
#14
sdta2021-06-01 08:06
以下是引用jinanshui在2021-6-1 06:59:50的发言:




谢谢老师,最难的遍历来了,怎样一期一组,全部找出来呢?尝试了一晚上,也没找到,学不会,再次请教老师.

试试
FOR lnj = 1 TO OCCURS("lotteryDrawNum", lcText)
    lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"', lnj)
    lcText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList', lnj)
    ? lcText ,lyText
ENDFOR
#15
sdta2021-06-01 09:49
FOR lnj = 1 TO OCCURS("lotteryDrawNum", lcText)
    lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"', lnj)
    lcText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList', lnj)
    ? lcText ,lyText
ENDFOR

改为

FOR lnj = 1 TO OCCURS("lotteryDrawNum", lcText)
    lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"', lnj)
    lxText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList', lnj) && lcText 为下载的数据
    ? lxText ,lyText
ENDFOR
#16
sdta2021-06-01 10:00
从11006期开始才有出球顺序的数据,也就是lxText提取的数据
#17
吹水佬2021-06-01 14:29
以下是引用sdta在2021-6-1 07:19:55的发言:

下载数据用时比较长(8秒左右),解析数据应该能控制在1秒内

下载的数据有5M多,记录也2000多条,用STREXTRACT()要秒杀有难度。
试试用JavaScript应该能秒杀
只有本站会员才能查看附件,请 登录

程序代码:
CREATE CURSOR tt (DrawNum C(5), DrawResult C(20))
cUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0"
oHttp = CREATEOBJECT("MSXML2.XMLHTTP")
oHttp.Open("GET", cUrl, .F.)
oHttp.Send()
jsCode = 'var data='+oHttp.responseText+';var list=data["value"]["list"];'
oSC = CREATEOBJECT("ScriptControl")
oSC.Language = "JavaScript"
oSC.AddCode(jsCode)
FOR i=0 TO oSC.eval('list.length')-1
    INSERT INTO tt VALUES (oSC.eval('list['+TRANSFORM(i)+']["lotteryDrawNum"]'),;
                           oSC.eval('list['+TRANSFORM(i)+']["lotteryUnsortDrawresult"]'))
ENDFOR
SELECT * FROM tt
RETURN
#18
吹水佬2021-06-01 15:30
JS部分这样写好读一点
程序代码:
jsCode = 'var data=' + oHttp.responseText + ';' +;
         'var list=data["value"]["list"];' +;
         'function getList(n,name){return list[n][name];}'
oSC = CREATEOBJECT("ScriptControl")
oSC.Language = "JavaScript"
oSC.AddCode(jsCode)
FOR i=0 TO oSC.eval('list.length')-1
    INSERT INTO tt VALUES (oSC.run("getList",i,"lotteryDrawNum"),;
                           oSC.run("getList",i,"lotteryUnsortDrawresult"))
ENDFOR
#19
sdta2021-06-01 16:13
以下是引用吹水佬在2021-6-1 15:30:05的发言:

JS部分这样写好读一点
jsCode = 'var data=' + oHttp.responseText + ';' +;
         'var list=data["value"]["list"];' +;
         'function getList(n,name){return list[n][name];}'
oSC = CREATEOBJECT("ScriptControl")
oSC.Language = "JavaScript"
oSC.AddCode(jsCode)
FOR i=0 TO oSC.eval('list.length')-1
    INSERT INTO tt VALUES (oSC.run("getList",i,"lotteryDrawNum"),;
                           oSC.run("getList",i,"lotteryUnsortDrawresult"))
ENDFOR

看惯VFP的代码,再看别的代码很不习惯!
#20
吹水佬2021-06-01 17:23
以下是引用sdta在2021-6-1 16:13:03的发言:


看惯VFP的代码,再看别的代码很不习惯!

windows环境避免不了,很多时要通过COM服务应用
面对WEB方面的编程,JS、HTML、CSS才是主体
就好象VFP面对EXCEL,不用VBA怕好难成事
#21
schtg2021-06-01 18:13
向各位学习,谢谢!
#22
jinanshui2021-06-01 20:41
在各位老师的帮助下终于,成功了,谢谢,虽然很慢,但是毕竟成功了
CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5))
lcUrl = "https://webapi.
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", lcUrl, .F.)
oHTTP.SETREQUESTHEADER("Content-Type", "text/html;charset=UTF-8")
oHTTP.Send()
lcText = STRCONV(oHTTP.ResponseBody, 11)
lmText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList')
lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"')
lstext = OCCURS("lotteryDrawNum", lcText)
? lmText ,lyText ,lstext
FOR lnj = 1 TO OCCURS("lotteryDrawNum", lcText)
    lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"', lnj)
    lmText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList', lnj)
   h1 = Substr(lmText ,1,2)
   h2 = Substr(lmText ,4,2)
   h3 = Substr(lmText ,7,2)
   h4 = Substr(lmText ,10,2)
   h5 = Substr(lmText ,13,2)
   l1 = Substr(lmText ,16,2)
   l2 = Substr(lmText ,19,2)
   q1 = Substr(lyText ,1,5)
   INSERT INTO 大乐透 VALUES (h1,h2,h3,h4,h5,l1,l2,q1)
  ENDFOR

[此贴子已经被作者于2021-6-1 20:47编辑过]

#23
jinanshui2021-06-01 21:02
另外,各位老师,没有找到使用第几套球的采集入口,麻烦各位老师再看看,谢谢.
#24
sdta2021-06-01 21:18
以下是引用jinanshui在2021-6-1 21:02:45的发言:

另外,各位老师,没有找到使用第几套球的采集入口,麻烦各位老师再看看,谢谢.

应该是这个字段:lotteryEquipmentCount
#25
sdta2021-06-01 21:19
以下是引用jinanshui在2021-6-1 20:41:30的发言:

在各位老师的帮助下终于,成功了,谢谢,虽然很慢,但是毕竟成功了
CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5))
lcUrl = "https://webapi.
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", lcUrl, .F.)
oHTTP.SETREQUESTHEADER("Content-Type", "text/html;charset=UTF-8")
oHTTP.Send()
lcText = STRCONV(oHTTP.ResponseBody, 11)
lmText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList')
lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"')
lstext = OCCURS("lotteryDrawNum", lcText)
? lmText ,lyText ,lstext
FOR lnj = 1 TO OCCURS("lotteryDrawNum", lcText)
    lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','","lotteryDrawResult":"', lnj)
    lmText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','","matchList', lnj)
   h1 = Substr(lmText ,1,2)
   h2 = Substr(lmText ,4,2)
   h3 = Substr(lmText ,7,2)
   h4 = Substr(lmText ,10,2)
   h5 = Substr(lmText ,13,2)
   l1 = Substr(lmText ,16,2)
   l2 = Substr(lmText ,19,2)
   q1 = Substr(lyText ,1,5)
   INSERT INTO 大乐透 VALUES (h1,h2,h3,h4,h5,l1,l2,q1)
  ENDFOR

看下ALINES()的用法
#26
sdta2021-06-01 21:23
只有本站会员才能查看附件,请 登录
#27
吹水佬2021-06-01 22:18
回复 22楼 jinanshui
测试结果的确有点慢,比对了一下:
耗时:254秒
程序代码:
CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5))
lcUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0"
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", lcUrl, .F.)
oHTTP.SETREQUESTHEADER("Content-Type", "text/html;charset=UTF-8")
oHTTP.Send()
lcText = oHTTP.ResponseText

t1 = SECONDS()
FOR lnj = 1 TO OCCURS("lotteryDrawNum", lcText)
    lyText = STREXTRACT(lcText,',"lotteryDrawNum":"','"', lnj)
    lmText = STREXTRACT(lcText,'lotteryUnsortDrawresult":"','"', lnj)
    h1 = Substr(lmText ,1,2)
    h2 = Substr(lmText ,4,2)
    h3 = Substr(lmText ,7,2)
    h4 = Substr(lmText ,10,2)
    h5 = Substr(lmText ,13,2)
    l1 = Substr(lmText ,16,2)
    l2 = Substr(lmText ,19,2)
    INSERT INTO 大乐透 VALUES (h1,h2,h3,h4,h5,l1,l2,lyText)
ENDFOR
? SECONDS() - t1 && 254秒


用JS代码相对也只要1秒多点,真有点意外,大家测试一下:
程序代码:
CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5))
cUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0"
oHttp = CREATEOBJECT("MSXML2.XMLHTTP")
oHttp.Open("GET", cUrl, .F.)
oHttp.Send()

t1 = SECONDS()

jsCode = 'var data=' + oHttp.responseText + ';' +;
         'var list=data["value"]["list"];' +;
         'function getList(n,name){return list[n][name];}'
oSC = CREATEOBJECT("ScriptControl")
oSC.Language = "JavaScript"
oSC.AddCode(jsCode)
FOR i=0 TO oSC.eval('list.length')-1
    lyText = oSC.run("getList",i,"lotteryDrawNum")
    lmText = oSC.run("getList",i,"lotteryUnsortDrawresult")
    h1 = Substr(lmText ,1,2)
    h2 = Substr(lmText ,4,2)
    h3 = Substr(lmText ,7,2)
    h4 = Substr(lmText ,10,2)
    h5 = Substr(lmText ,13,2)
    l1 = Substr(lmText ,16,2)
    l2 = Substr(lmText ,19,2)
    INSERT INTO 大乐透 VALUES (h1,h2,h3,h4,h5,l1,l2,lyText)
ENDFOR
? SECONDS() - t1 && 1.6秒




#28
sdta2021-06-01 22:49
回复 27楼 吹水佬
楼主:300秒
吹版:0.9秒
#29
sdta2021-06-01 23:02
程序代码:
CLEAR
CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5), 球具 N(1))
cUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0&" + SUBSTR(SYS(2015), 2)
t1 = SECONDS()
oHttp = CREATEOBJECT("MSXML2.XMLHTTP")
oHttp.Open("GET", cUrl, .F.)
oHttp.Send()
lcText = oHttp.ResponseText
? "下载数据:", SECONDS() - t1
t1 = SECONDS()
lcText = STREXTRACT(lcText, '{"list":[{"', '')
ALINES(laText, lcText, '{}},{"')
FOR ln1 = 1 TO ALEN(laText, 1)
    ALINES(laStr, laText[ln1], '},{"', '":', ',"', '[{"', '}]')
    ALINES(laHm, &laStr[14], SPACE(1))
    INSERT INTO 大乐透 VALUES (laHm[1], laHm[2], laHm[3], laHm[4], laHm[5], laHm[6], laHm[7], &laStr[12], &laStr[20])
ENDFOR
? "解析数据:", SECONDS() - t1 && 0.6秒
BROWSE


[此贴子已经被作者于2021-6-1 23:19编辑过]

#30
sdta2021-06-01 23:11
STREXTRACT()在解析这种大块头JSON数据中速度确实慢,ALINES()速度则飞快,建议大家以后解析类似这种大块头的文本,使用ALINES()函数。ALINES()是解析文本字符的利器。
#31
jinanshui2021-06-02 03:59
真心佩服
#32
schtg2021-06-02 05:26
受益,谢谢!
#33
吹水佬2021-06-02 10:46
以下是引用sdta在2021-6-1 23:11:24的发言:

STREXTRACT()在解析这种大块头JSON数据中速度确实慢,ALINES()速度则飞快,建议大家以后解析类似这种大块头的文本,使用ALINES()函数。ALINES()是解析文本字符的利器。

这个循环有2000多次,STREXTRACT()在循环体每次从头起搜索大块头肯定快不了。
ALINES()在分配内存和读入数据时有点耗时,以后寻址取数就快了。
循环体内如果能用其他字符串函数代替ALINES()应该会快点,用ALINES()来处理较规范的数据确是便捷些。

有点不明白,VFP既然有SYS(2600)使用到指针,为何不提供处理指针的方法?

试用指针来处理这个问题,好象可以做到 0.1 秒杀,大家试试看:
程序代码:
DECLARE LONG GetProcessHeap IN Kernel32
DECLARE LONG HeapAlloc IN kernel32 LONG, LONG, LONG
DECLARE LONG HeapFree IN Kernel32 LONG, LONG, LONG
DECLARE LONG strstr IN msvcrt LONG,STRING@

CREATE CURSOR 大乐透 (红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5),球具 N(1))
cUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0&" + SUBSTR(SYS(2015), 2)
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", cUrl, .F.)
oHTTP.SETREQUESTHEADER("Content-Type", "text/html;charset=UTF-8")
oHTTP.Send()
lcText = oHTTP.ResponseText

t1 = SECONDS()
nSize = LEN(lcText)+1
pText = HeapAlloc(GetProcessHeap(), 8, nSize)
SYS(2600, pText, nSize, lcText+0h00)

p = strstr(pText, "lotteryDrawNum")
DO WHILE p > 0
    DrawNum =  SYS(2600, p+17, 5)
    p2 = strstr(p, "lotteryDrawResult") + 20
    p = strstr(p2, "lotteryEquipmentCount") + 23
    EquipmentCount = VAL(SYS(2600, p, 1))
    INSERT INTO 大乐透 VALUES (SYS(2600, p2, 2),;
                               SYS(2600, p2+3, 2),;
                               SYS(2600, p2+6, 2),;
                               SYS(2600, p2+9, 2),;
                               SYS(2600, p2+12, 2),;
                               SYS(2600, p2+15, 2),;
                               SYS(2600, p2+18, 2),;
                               DrawNum, EquipmentCount)
    p = strstr(p, "lotteryDrawNum")
ENDDO
? SECONDS() - t1  && 0.094
HeapFree(GetProcessHeap(), 1, pText)
SELECT * FROM 大乐透
RETURN


#34
sdta2021-06-02 11:01
回复 33楼 吹水佬
这个方法不错,学习了!
0.084秒
#35
jinanshui2021-06-02 16:59
真厉害,0.040秒
#36
sdta2021-06-02 17:12
以下是引用jinanshui在2021-6-2 16:59:29的发言:

真厉害,0.040秒

楼主的电脑高配
#37
sdta2021-06-02 21:35
吹版请教几个问题:
1 msvcrt.dll 是API 动态链接库吗
2 strstr()函数的功能是什么,其中只有两个参数吗,网上没找到用法,能详细介绍下用法吗
#38
吹水佬2021-06-03 08:30
以下是引用sdta在2021-6-2 21:35:00的发言:

吹版请教几个问题:
1 msvcrt.dll 是API 动态链接库吗
2 strstr()函数的功能是什么,其中只有两个参数吗,网上没找到用法,能详细介绍下用法吗

msvcrt.dll是windows自带的C语言运行库,VFP9运行库也自带v7.1版本的msvcr71.dll
strstr(s1,s2)是在s1搜寻s2,成功返回s2地址,失败返回0
strstr()是用基本算法按顺序逐个字符比对搜索,效率不算高
#39
sdta2021-06-04 12:02
以下是引用吹水佬在2021-6-3 08:30:49的发言:


msvcrt.dll是windows自带的C语言运行库,VFP9运行库也自带v7.1版本的msvcr71.dll
strstr(s1,s2)是在s1搜寻s2,成功返回s2地址,失败返回0
strstr()是用基本算法按顺序逐个字符比对搜索,效率不算高

谢谢吹版回复
以前从没用过API函数,看样子要从头学习API函数
#40
nbwww2021-06-04 15:05
收藏收藏
#41
吹水佬2021-06-04 15:43
回复 39楼 sdta
所谓的windows深入编程基本就是使用不同层次的 Windows API
顺便说说VFP使用 API strstr() 函数时要注意:
一般可声明为:DECLARE LONG strstr IN msvcrt STRING@,STRING@
这样调用时最好观察一下返回的字符串地址是否正确,尤其是同时对不同的字符串操作时返回的地址可能有冲突。
最好自己分配堆内存来处理,如使用 API HeapAlloc() 分配内存,尤其是处理较大的字符串。
可声明为:DECLARE LONG strstr IN msvcrt LONG,LONG
参数就是存放字符串的地址,返回的地址肯定也是在这地址存放数据的范围。



#42
sdta2021-06-04 15:45
回复 33楼 吹水佬
如果
如果 lotteryDrawNum 后面的数据长度固定,33楼的代码应该是速度最快的代码,如果长度不固定,就受到了限制。
如:
"lotteryDrawNum":"21062"
"lotteryDrawResult":"04 06 23 32 34 05 07"
"lotteryDrawTime":"2021-06-02"
"lotteryEquipmentCount":2

如果 ":"后面的数据长度不一的话,如何处理!

[此贴子已经被作者于2021-6-4 16:00编辑过]

#43
吹水佬2021-06-04 16:01
以下是引用sdta在2021-6-4 15:45:00的发言:

如果 lotteryDrawNum 后面的数据长度不固定,就受到限制

其实可以调用strstr()写模拟VFP的STREXTRACT()
lotteryDrawNum","="21006"
就是搜寻到[lotteryDrawNum]后(返回地址p1)
p1 = p1 + 19  将p1指向到"21006"的2
跟着又从p1起搜寻["](返回地址p2),(p2 - p1)就是所求数据长度。
#44
sdta2021-06-04 17:07
在吹版代码的基础上做了改进,适应不定长数据的提取。大家可以测试下(时间比吹版的时间稍长些)
API代码部分来源于大师(行者孙)及本论坛的大师吹水佬。
程序代码:
DECLARE LONG StrDup IN shlwapi STRING @lpsz
DECLARE LONG LocalFree IN kernel32 LONG
DECLARE LONG strstr IN msvcrt LONG,STRING @

CREATE CURSOR dlt (开奖日期 C(10), 红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5),球具 N(1))
cUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0&" + SUBSTR(SYS(2015), 2)
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", cUrl, .F.)
oHTTP.Send()
lcText = oHTTP.ResponseText
t1 = SECONDS()
hMem = StrDup(@lcText)
sys(2600, hMem, len(lcText))
nSize = 100 && 根据JSON块数据的长度做适当调整
p0 = strstr(hMem, "lotteryDrawNum")
DO WHILE p0 > 0
    DrawNum =  STREXTRACT(SYS(2600, p0, nSize), ':', ',"')
    p1 = strstr(p0, "lotteryDrawResult")
    p2 = strstr(p1, "lotteryDrawTime")
    p0 = strstr(p2, "lotteryEquipmentCount")
    lcqh = DrawNum
    lckjrq = STREXTRACT(SYS(2600, p2, nSize), ':', ',"')
    lcjh = STREXTRACT(SYS(2600, p1, nSize), ':', ',"')
    lcqj = STREXTRACT(SYS(2600, p0, nSize), ':', ',"')
    INSERT INTO dlt VALUES (&lckjrq, SUBSTR(lcjh, 2, 2), SUBSTR(lcjh, 5, 2), SUBSTR(lcjh, 8, 2), SUBSTR(lcjh, 11, 2), SUBSTR(lcjh, 14, 2), SUBSTR(lcjh, 17, 2), SUBSTR(lcjh, 20, 2), &DrawNum, &lcqj)
    p0 = strstr(p0, "lotteryDrawNum")
ENDDO
LocalFree(hMem)
CLEAR DLLS
? SECONDS() - t1 && 0.2秒内
BROWSE


[此贴子已经被作者于2021-6-4 17:20编辑过]

#45
吹水佬2021-06-05 08:42
回复 44楼 sdta
hMem = StrDup(@lcText) 分配内存(hMem地址空间),并将lcText复制到hMem的地址空间   
sys(2600, hMem, len(lcText)) 这句不要(重复载入)
#46
sdta2021-06-05 09:06
以下是引用吹水佬在2021-6-5 08:42:19的发言:

hMem = StrDup(@lcText) 分配内存(hMem地址空间),并将lcText复制到hMem的地址空间   
sys(2600, hMem, len(lcText)) 这句不要(重复载入)

谢谢吹版,sys(2600, hMem, len(lcText)) 这句代码确实可以省略,同时代码运行时间也减少了。上面的代码只是照葫芦画瓢。
#47
吹水佬2021-06-05 10:04
写个类似STREXTRACT(),从VFP的视觉看起来顺眼一点
程序代码:
DECLARE LONG _strdup IN msvcrt as api_strdup STRING@
DECLARE LONG free    IN msvcrt as api_free   LONG
DECLARE LONG strstr  IN msvcrt as api_strstr LONG,STRING@

CREATE CURSOR dlt (开奖日期 C(10), 红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5),球具 N(1))
cUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0&" + SUBSTR(SYS(2015), 2)
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", cUrl, .F.)
oHTTP.Send()
lcText = oHTTP.ResponseText

t1 = SECONDS()
pText = api_strdup(@lcText)
ptr = pText
DrawNum = _STREXTRACT(@ptr, [lotteryDrawNum":"], ["])
DO WHILE ptr > 0
    DrawResult = _STREXTRACT(@ptr, [lotteryDrawResult":"], ["])
    INSERT INTO dlt VALUES (;
        _STREXTRACT(@ptr, [lotteryDrawTime":"], ["]),;
        SUBSTR(DrawResult,1,2),;
        SUBSTR(DrawResult,4,2),;
        SUBSTR(DrawResult,7,2),;
        SUBSTR(DrawResult,10,2),;
        SUBSTR(DrawResult,13,2),;
        SUBSTR(DrawResult,16,2),;
        SUBSTR(DrawResult,19,2),;
        DrawNum,;
        VAL(_STREXTRACT(@ptr, [lotteryEquipmentCount":], [,])))
    DrawNum = _STREXTRACT(@ptr, [lotteryDrawNum":"], ["])
ENDDO
? SECONDS() - t1
api_free(pText)

CLEAR DLLS
SELECT * FROM dlt
RETURN

FUNCTION _STREXTRACT(pStr, cStr1, cStr2)
    pStr = api_strstr(pStr, cStr1)
    IF pStr > 0
        pBegin = pStr + LEN(cStr1)
        pEnd = api_strstr(pBegin, cStr2)
        IF pEnd > 0
            pStr = pEnd + LEN(cStr2)
            RETURN SYS(2600, pBegin, pEnd-pBegin)
        ENDIF
    ENDIF
    pStr = 0
    RETURN ""
ENDFOR


[此贴子已经被作者于2021-6-5 11:09编辑过]

#48
吹水佬2021-06-05 10:32
换个花样玩玩
程序代码:
DECLARE LONG _strdup IN msvcrt as api_strdup STRING@
DECLARE LONG free    IN msvcrt as api_free   LONG
DECLARE LONG strstr  IN msvcrt as api_strstr LONG,STRING@
DECLARE LONG sscanf  IN msvcrt as api_sscanf STRING@,STRING@,STRING@,STRING@,STRING@,STRING@,STRING@,STRING@,STRING@

CREATE CURSOR dlt (开奖日期 C(10), 红1 C(2), 红2 C(2), 红3 C(2),红4 C(2),红5 C(2),兰1 C(2),兰2 C(2),期号 C(5),球具 N(1))
cUrl = "https://webapi./gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=0&" + SUBSTR(SYS(2015), 2)
oHTTP=NEWOBJECT("MSXML2.XMLHTTP")
oHTTP.Open("GET", cUrl, .F.)
oHTTP.Send()
lcText = oHTTP.ResponseText

t1 = SECONDS()
STORE "  " TO s1,s2,s3,s4,s5,s6,s7
pText = api_strdup(@lcText)
ptr = pText
DrawNum = _STREXTRACT(@ptr, [lotteryDrawNum":"], ["])
DO WHILE ptr > 0
    api_sscanf(_STREXTRACT(@ptr,[lotteryDrawResult":"],["]), "%s %s %s %s %s %s %s", @s1,@s2,@s3,@s4,@s5,@s6,@s7)
    INSERT INTO dlt VALUES (_STREXTRACT(@ptr, [lotteryDrawTime":"], ["]),;
                            s1,s2,s3,s4,s5,s6,s7, DrawNum,;
                            VAL(_STREXTRACT(@ptr, [lotteryEquipmentCount":], [,])))
    DrawNum = _STREXTRACT(@ptr, [lotteryDrawNum":"], ["])
ENDDO
? SECONDS() - t1
api_free(pText)

CLEAR DLLS
SELECT * FROM dlt
RETURN

FUNCTION _STREXTRACT(pStr, cStr1, cStr2)
    pStr = api_strstr(pStr, cStr1)
    IF pStr > 0
        pBegin = pStr + LEN(cStr1)
        pEnd = api_strstr(pBegin, cStr2)
        IF pEnd > 0
            pStr = pEnd + LEN(cStr2)
            RETURN SYS(2600, pBegin, pEnd-pBegin)
        ENDIF
    ENDIF
    pStr = 0
    RETURN ""
ENDFOR


[此贴子已经被作者于2021-6-5 11:10编辑过]

#49
sdta2021-06-05 11:30
如果当属性的顺序不一致时,程序会发生错误
{"ab":"12","cd","34","ef:","56"}
{"ef":"21","cd","43","ab:","65"}
#50
sdta2021-06-05 11:31
谢谢吹版无私的指导,令我大开眼界,慢慢消化吸收。
#51
吹水佬2021-06-05 11:47
以下是引用sdta在2021-6-5 11:30:15的发言:

如果当属性的顺序不一致时,程序会发生错误
{"ab":"12","cd","34","ef:","56"}
{"ef":"21","cd","43","ab:","65"}

是的,搜寻是不回头的:pStr = pEnd + LEN(cStr2)
如果要回头,每个记录要保存一个记录头指针,每次要从这个头指针开始搜寻
对于每个记录各字段数据顺序不确定,数据存放格式不规范,这样会影响搜寻效率
12