标题:老师好,又来请教了,这个网页的采集入口如何找,谢谢
只看楼主
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
回复 39楼 sdta
所谓的windows深入编程基本就是使用不同层次的 Windows API
顺便说说VFP使用 API strstr() 函数时要注意:
一般可声明为:DECLARE LONG strstr IN msvcrt STRING@,STRING@
这样调用时最好观察一下返回的字符串地址是否正确,尤其是同时对不同的字符串操作时返回的地址可能有冲突。
最好自己分配堆内存来处理,如使用 API HeapAlloc() 分配内存,尤其是处理较大的字符串。
可声明为:DECLARE LONG strstr IN msvcrt LONG,LONG
参数就是存放字符串的地址,返回的地址肯定也是在这地址存放数据的范围。



2021-06-04 15:43
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:323
帖 子:9621
专家分:26174
注 册:2012-2-5
得分:0 
回复 33楼 吹水佬
如果
如果 lotteryDrawNum 后面的数据长度固定,33楼的代码应该是速度最快的代码,如果长度不固定,就受到了限制。
如:
"lotteryDrawNum":"21062"
"lotteryDrawResult":"04 06 23 32 34 05 07"
"lotteryDrawTime":"2021-06-02"
"lotteryEquipmentCount":2

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

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


坚守VFP最后的阵地
2021-06-04 15:45
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用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)就是所求数据长度。
2021-06-04 16:01
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:323
帖 子:9621
专家分:26174
注 册:2012-2-5
得分:0 
在吹版代码的基础上做了改进,适应不定长数据的提取。大家可以测试下(时间比吹版的时间稍长些)
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编辑过]


坚守VFP最后的阵地
2021-06-04 17:07
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
回复 44楼 sdta
hMem = StrDup(@lcText) 分配内存(hMem地址空间),并将lcText复制到hMem的地址空间   
sys(2600, hMem, len(lcText)) 这句不要(重复载入)
2021-06-05 08:42
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:323
帖 子:9621
专家分:26174
注 册:2012-2-5
得分:0 
以下是引用吹水佬在2021-6-5 08:42:19的发言:

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

谢谢吹版,sys(2600, hMem, len(lcText)) 这句代码确实可以省略,同时代码运行时间也减少了。上面的代码只是照葫芦画瓢。

坚守VFP最后的阵地
2021-06-05 09:06
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
写个类似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编辑过]

2021-06-05 10:04
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
换个花样玩玩
程序代码:
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编辑过]

2021-06-05 10:32
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:323
帖 子:9621
专家分:26174
注 册:2012-2-5
得分:0 
如果当属性的顺序不一致时,程序会发生错误
{"ab":"12","cd","34","ef:","56"}
{"ef":"21","cd","43","ab:","65"}

坚守VFP最后的阵地
2021-06-05 11:30
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:323
帖 子:9621
专家分:26174
注 册:2012-2-5
得分:0 
谢谢吹版无私的指导,令我大开眼界,慢慢消化吸收。

坚守VFP最后的阵地
2021-06-05 11:31



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-505901-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.187321 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved