求助,关于vfp爬虫在下载含有中文及特殊字符url时无法识别的问题。

fojiao8745 2017-11-27 10:03:30
女票最近跟我提了需求,想学习英语口语,遂打算写一个爬虫去下载目标为"http://www.ifrog.cc/course/28"的学习资源,但是编程发现不能下载,怀疑是url包含特殊字符及中文导致,自己尝试了很多均无法解决,特来请求各位前辈帮助,不甚感激。
以下贴上源码:
DECLARE LONG URLDownloadToFileA IN Urlmon LONG, STRING@, STRING@, LONG, LONG
DECLARE LONG DeleteUrlCacheEntry IN Wininet STRING@
LOCAL oxhttp AS Microsoft.xmlhttp
oxhttp=CREATEOBJECT("Microsoft.xmlhttp")
oxhttp.OPEN("GET",'http://www.ifrog.cc/course/28',.F.)
oxhttp.SEND()
SourceCode=oxhttp.responseBody
RELEASE oxhttp
&&SourceCode = STRCONV(SourceCode,11)
lclength = LEN(SourceCode)
FOR a=1 TO lclength
lcString=SUBSTR(SourceCode,a,31)
IF lcString == '<i class="icon-course-chapter">'
lnstart = a
a = lclength
ENDIF
ENDFOR

FOR a=lnstart TO lclength
lcString=SUBSTR(SourceCode,a,52)
IF lcString == '<form action="/comment/course/28" id="comment-form">'
lnend = a
a = lclength
ENDIF
ENDFOR

SourceCode = SUBSTR(SourceCode,lnstart,lnend - lnstart)
FOR a=1 TO 49
lcnum = STREXTRACT(SourceCode,'<a href="/section/','" target="_blank">',a)
lcurl = 'http://www.ifrog.cc/section/'+lcnum

LOCAL oxhttp
lndelay = 0
lcstatus = 'ok'
oxhttp=CREATEOBJECT("InternetExplorer.Application")
oxhttp.Navigate(lcurl)
oxhttp.visible = .T.
Do While oxhttp.ReadyState != 4 AND lcstatus == 'ok'
INKEY(1,'H')
lndelay = lndelay + 1
IF lndelay = 5
lcstatus = 'fail'
ENDIF
ENDDO
IF lcstatus = 'ok'
SourceCode1 = oxhttp.Document.body.innerhtml
oxhttp.Quit
RELEASE oxhttp
lctarget = STREXTRACT(SourceCode1,"file:'/uploads/2016/","'",1)
lcdownurl = 'http://www.ifrog.cc/uploads/2016/'+lctarget &&if error?
IF DownloadFile(lcdownurl,'.\'+STRTRAN(STRTRAN(lctarget,':',''),'/','')) = .F.
MESSAGEBOX(lctarget+' failed',48,'Tips',800)
ELSE
MESSAGEBOX(lctarget+' ok',48,'Tips',800)
ENDIF
ELSE
oxhttp.Quit
RELEASE oxhttp
a = a - 1
ENDIF
ENDFOR

***********************Function DownloadFile***********************
FUNCTION DownloadFile(cURL, cLocalFileName)
IF URLDownloadToFileA(0, @cURL, @cLocalFileName, 0, 0) == 0
DeleteUrlCacheEntry(@cURL)
RETURN .T.
ENDIF
RETURN .F.
ENDFUNC
***************************Function End*****************************

*************************Function urlencode*************************
FUNCTION urlencode(lcUrl)
LOCAL r, i
r = ''
FOR i=1 TO LEN(lcUrl)
r = r + '%' + RIGHT(TRANSFORM(ASC(SUBSTR(lcUrl, i, 1)), '@0'), 2)
ENDFOR
RETURN r
ENDFUNC
***************************Function End*****************************
...全文
1373 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
fojiao8745 2017-11-30
  • 打赏
  • 举报
回复
引用 22 楼 dkfdtf 的回复:
参数 开始模式 可取三种值: 0 - 手工,1 - 自动,-1(默认) - 迅雷配置值
版主大大,我就是直接复制你的,默认这个参数是1啊,但是执行的时候弹出了迅雷的任务确认对话框
都市夜猫 2017-11-30
  • 打赏
  • 举报
回复
参数 开始模式 可取三种值: 0 - 手工,1 - 自动,-1(默认) - 迅雷配置值
fojiao8745 2017-11-30
  • 打赏
  • 举报
回复
引用 20 楼 dkfdtf 的回复:
1. 加 Try 是因为我这调用 QUIT 方法会出错 2. vfp 中,字符串用方括号,单引号,双引号标识都可以 3. 调用迅雷应该是可以的,迅雷提供了 COM 控件可直接使用 添加下载任务的参数如下: AddTask("下载地址", "另存文件名", "保存目录","任务注释","引用地址",开始模式, 只从原始地址下载,从原始地址下载线程数) 例如: oo = NewObject('ThunderAgent.Agent') oo.AddTask('http://www.ifrog.cc/uploads/2016/013-双元音【o】的发音.mp4','','','','',1,0,10) oo.CommitTasks()
谢谢版主大大的帮忙,不过好像是他们的服务器有毛病,很多视频下载下来看不了。。。已经放弃了。。。另外上面这三行代码执行完了会弹出迅雷确认下载的对话框,并不会自动下载,请问可以让他静默下载吗?
都市夜猫 2017-11-29
  • 打赏
  • 举报
回复
unicode 是一种字符集,其他常见的字符集是 ASCII,GB2312,GBK,GB18030,....;ANSI,utf-8,utf-16,utf-32 是对字符集的某种编码方式 utf-8 也使用 unicode 字符集,但它的编码方式与 win32api 要求的 Wide 字符(unicode)编码方式还是不同的,俗称的 unicode 是 utf-16 编码 utf-16 编码的好处是任何字符都采用固定两字节来编码,字符串分析处理就可以简单快速,坏处是对 ascii < 127 的字符要浪费一半的字节 utf-8 编码就是为了弥补 utf-16 这一缺陷而制定的标准,因此在网页上得到广泛应用,网页中绝大部分内容都是英文字符,采用 utf-8 可以节省流量;而基于本地运行的 win32api ,多占用内存和流量不是要考虑的重点,能快速解析才是关键,因此 win32api 的 W 函数使用 utf-16(unicode) 编码 +chr(0) 是因为 win32api 绝大部分字符串解析采用 C/C++ 字符串规则(遇到 0x00 作为一个字符串结束标记来判断),vfp 默认只调用 api 的 ANSI版本,在传字符串参数时会自动附加一个chr(0),显式调用 Wide 版本时,由于 unicode 用两字节代表一个字符,因此必须手工再加一个 chr(0),当然多几个 chr(0) 也不会有问题,规矩的写法应该是:STRCONV(s,5) + CHR(0) STRCONV(lcdownurl+CHR(0),5),参数 5,因为 lcdownurl 经过 URLEncode2 编码后返回的是 ANSI 编码,因此要用 5 转成 unicode STRCONV(lctarget+CHR(0),12),参数 12,因为 lctarget 是 utf-8 编码,因此要用 12 转成 unicode sys(3101) 函数 vfp 帮助文档里有描述的,65001 是 utf-8 编码的代码 至于下载的部分文件无法播放,也许是网络或网站加了限制的问题,我检查了下载的 004 也无法播放,我用迅雷试了试,可以播放的长度是 48348K。如果只是为了得到这些媒体文件,建议只提取下载地址,下载交给迅雷等工具去干;若是想用 vfp 实现就另当别说了,正常情况下载的文件没问题,那就去考虑错误处理等方面了
fojiao8745 2017-11-29
  • 打赏
  • 举报
回复
引用 11 楼 dkfdtf 的回复:
你看到乱码是因为 vfp 不支持,所以不能正确显示 utf-8 编码的字符串,这不奇怪,不影响存放在内存中的数据
utf-8 编码对于 ascii < 128 的字符仍只使用一个字节来表示,所以 vfp 能正确会显示它们;对于 > 127 的字符会采用变长字节来存储,这些就无法正确显示,也就是你看到的乱码

你好像少改了一个地方:
URLDownloadToFileA 都要换成 URLDownloadToFileW

版主大大,还有一点不太明白

就是这个地方,为什么要加上chr(0),还有encodeurl2不是已经编码为utf-8了吗,为什么这里的目标连接还要strconv("",5)?以及后面的strconv("",12)是什么作用呢?还有最后一个问题,SYS(3101,65001) 以及SYS(3101,0)这个用法在vfp的官方支持文档里面都找不到使用说明,你有使用说明吗?可否分享一下?
最后非常感谢版主大大的热情解答O(∩_∩)O~
fojiao8745 2017-11-29
  • 打赏
  • 举报
回复
引用 13 楼 ckc 的回复:
vfp的爬虫第一次见
很正常。。。又不是实现不了,我还写了一个爬虫爬去图片,利用多个进程,半小时爬了17GB的图片,100M的宽带达到满速,差不多有12000张图片。。。供我自己观赏。。。
fojiao8745 2017-11-29
  • 打赏
  • 举报
回复
引用 11 楼 dkfdtf 的回复:
你看到乱码是因为 vfp 不支持,所以不能正确显示 utf-8 编码的字符串,这不奇怪,不影响存放在内存中的数据 utf-8 编码对于 ascii < 128 的字符仍只使用一个字节来表示,所以 vfp 能正确会显示它们;对于 > 127 的字符会采用变长字节来存储,这些就无法正确显示,也就是你看到的乱码 你好像少改了一个地方: URLDownloadToFileA 都要换成 URLDownloadToFileW
确实,是我自己没看到你在第二点里面说的要改下载函数,后面躺在床上休息的时候再次看你回复才发现,早上调试了一下,已经可以下载了,可是貌似有点bug?我在下载到004-单元音【I】的发音.m4v的时候,发现文件大小是正常的可是没法播放,前面的m4v都正常播放。。。。。
ckc 2017-11-29
  • 打赏
  • 举报
回复
vfp的爬虫第一次见
都市夜猫 2017-11-29
  • 打赏
  • 举报
回复
1. 加 Try 是因为我这调用 QUIT 方法会出错 2. vfp 中,字符串用方括号,单引号,双引号标识都可以 3. 调用迅雷应该是可以的,迅雷提供了 COM 控件可直接使用 添加下载任务的参数如下: AddTask("下载地址", "另存文件名", "保存目录","任务注释","引用地址",开始模式, 只从原始地址下载,从原始地址下载线程数) 例如: oo = NewObject('ThunderAgent.Agent') oo.AddTask('http://www.ifrog.cc/uploads/2016/013-双元音【o】的发音.mp4','','','','',1,0,10) oo.CommitTasks()
fojiao8745 2017-11-29
  • 打赏
  • 举报
回复
引用 17 楼 dkfdtf 的回复:
unicode 是一种字符集,其他常见的字符集是 ASCII,GB2312,GBK,GB18030,....;ANSI,utf-8,utf-16,utf-32 是对字符集的某种编码方式 utf-8 也使用 unicode 字符集,但它的编码方式与 win32api 要求的 Wide 字符(unicode)编码方式还是不同的,俗称的 unicode 是 utf-16 编码 utf-16 编码的好处是任何字符都采用固定两字节来编码,字符串分析处理就可以简单快速,坏处是对 ascii < 127 的字符要浪费一半的字节 utf-8 编码就是为了弥补 utf-16 这一缺陷而制定的标准,因此在网页上得到广泛应用,网页中绝大部分内容都是英文字符,采用 utf-8 可以节省流量;而基于本地运行的 win32api ,多占用内存和流量不是要考虑的重点,能快速解析才是关键,因此 win32api 的 W 函数使用 utf-16(unicode) 编码 +chr(0) 是因为 win32api 绝大部分字符串解析采用 C/C++ 字符串规则(遇到 0x00 作为一个字符串结束标记来判断),vfp 默认只调用 api 的 ANSI版本,在传字符串参数时会自动附加一个chr(0),显式调用 Wide 版本时,由于 unicode 用两字节代表一个字符,因此必须手工再加一个 chr(0),当然多几个 chr(0) 也不会有问题,规矩的写法应该是:STRCONV(s,5) + CHR(0) STRCONV(lcdownurl+CHR(0),5),参数 5,因为 lcdownurl 经过 URLEncode2 编码后返回的是 ANSI 编码,因此要用 5 转成 unicode STRCONV(lctarget+CHR(0),12),参数 12,因为 lctarget 是 utf-8 编码,因此要用 12 转成 unicode sys(3101) 函数 vfp 帮助文档里有描述的,65001 是 utf-8 编码的代码 至于下载的部分文件无法播放,也许是网络或网站加了限制的问题,我检查了下载的 004 也无法播放,我用迅雷试了试,可以播放的长度是 48348K。如果只是为了得到这些媒体文件,建议只提取下载地址,下载交给迅雷等工具去干;若是想用 vfp 实现就另当别说了,正常情况下载的文件没问题,那就去考虑错误处理等方面了
另外,VFP可以调用迅雷下载吗,能不能就我这个例子演示一下呢,恳请版主大大不吝赐教 对了我用的迅雷是极速版,没有会员
fojiao8745 2017-11-29
  • 打赏
  • 举报
回复
引用 17 楼 dkfdtf 的回复:
unicode 是一种字符集,其他常见的字符集是 ASCII,GB2312,GBK,GB18030,....;ANSI,utf-8,utf-16,utf-32 是对字符集的某种编码方式 utf-8 也使用 unicode 字符集,但它的编码方式与 win32api 要求的 Wide 字符(unicode)编码方式还是不同的,俗称的 unicode 是 utf-16 编码 utf-16 编码的好处是任何字符都采用固定两字节来编码,字符串分析处理就可以简单快速,坏处是对 ascii < 127 的字符要浪费一半的字节 utf-8 编码就是为了弥补 utf-16 这一缺陷而制定的标准,因此在网页上得到广泛应用,网页中绝大部分内容都是英文字符,采用 utf-8 可以节省流量;而基于本地运行的 win32api ,多占用内存和流量不是要考虑的重点,能快速解析才是关键,因此 win32api 的 W 函数使用 utf-16(unicode) 编码 +chr(0) 是因为 win32api 绝大部分字符串解析采用 C/C++ 字符串规则(遇到 0x00 作为一个字符串结束标记来判断),vfp 默认只调用 api 的 ANSI版本,在传字符串参数时会自动附加一个chr(0),显式调用 Wide 版本时,由于 unicode 用两字节代表一个字符,因此必须手工再加一个 chr(0),当然多几个 chr(0) 也不会有问题,规矩的写法应该是:STRCONV(s,5) + CHR(0) STRCONV(lcdownurl+CHR(0),5),参数 5,因为 lcdownurl 经过 URLEncode2 编码后返回的是 ANSI 编码,因此要用 5 转成 unicode STRCONV(lctarget+CHR(0),12),参数 12,因为 lctarget 是 utf-8 编码,因此要用 12 转成 unicode sys(3101) 函数 vfp 帮助文档里有描述的,65001 是 utf-8 编码的代码 至于下载的部分文件无法播放,也许是网络或网站加了限制的问题,我检查了下载的 004 也无法播放,我用迅雷试了试,可以播放的长度是 48348K。如果只是为了得到这些媒体文件,建议只提取下载地址,下载交给迅雷等工具去干;若是想用 vfp 实现就另当别说了,正常情况下载的文件没问题,那就去考虑错误处理等方面了
厉害呀,这个CHR(0)加的很精髓。。。版主大大真乃神人也 另外,这里的tyr catch endtry加上去是什么作用啊,直接oxhttp.QUIT不行么,还有一个疑问,为什么要用这种写法STRCONV([http://www.ifrog.cc/uploads/2016/],9),这里的[]换成双引号不行么?
都市夜猫 2017-11-28
  • 打赏
  • 举报
回复
大概调试了下,试了下10来个文件,问题不大


1. 另写了个专用的 URLEncode2
Function URLEncode2(tcUrl)
Local cRet, cc, c2, ii, jj

tcUrl = Strconv(tcUrl,12)
cRet = ''
For ii = 1 to Len(tcUrl) step 2
cc = Substr(tcUrl, ii, 2)
If Asc(Right(cc,1)) == 0 and Asc(Left(cc,1)) < 128
cRet = cRet + Left(cc, 1)
Else
cc = Strconv(Strconv(cc,10), 15)
c2 = ''
For jj = 1 to Len(cc) step 2
c2 = c2 + '%' + Substr(cc,jj,2)
EndFor
cRet = cRet + c2
EndIf
EndFor
Return cRet
EndFunc

2. 由于要保存带 unicode 字符的文件名,URLDownloadToFile 要调用其 unicode 版本,最开始声明改为
Declare Long URLDownloadToFileW In Urlmon Long, String@, String@, Long, Long
Function DownloadFile 中A 也同步改为 W

3. 获取下载地址和下载文件部分修改如下:
...
SourceCode = Substr(SourceCode,lnstart,lnend - lnstart)
For a = 1 To 49
lcnum = Strextract(SourceCode,'<a href="/section/','" target="_blank">',a)
lcurl = 'http://www.ifrog.cc/section/'+lcnum

Local oxhttp
lndelay = 0
lcstatus = 'ok'
oxhttp=Createobject("InternetExplorer.Application")
oxhttp.Navigate(lcurl)
oxhttp.Visible = .T.
Do While oxhttp.ReadyState != 4 And lcstatus == 'ok'
Inkey(1,'H')
lndelay = lndelay + 1
If lndelay = 5
lcstatus = 'fail'
Endif
Enddo

If lcstatus = 'ok'
Sys(3101,65001) && 重要: 定义 vfp 与 COM 对象间用 utf-8 编码交换数据
SourceCode1 = oxhttp.Document.body.innerhtml && 现在 SourceCode1 是 utf-8 编码
Sys(3101,0)
try
oxhttp.Quit
Catch
EndTry
Release oxhttp

Local c1, c2
c1 = Strconv([file:'/uploads/2016/],9)
c2 = Strconv(['],9)
lctarget = Strextract(SourceCode1,c1,c2,1)
lcdownurl = Strconv([http://www.ifrog.cc/uploads/2016/],9)+lctarget
lcdownurl = URLEncode2(lcdownurl)
If DownloadFile(Strconv(lcdownurl+Chr(0),5),Strconv(lctarget+Chr(0),12)) = .F.
Messagebox(Strconv(lctarget,11)+' failed',48+4096,'Tips',800)
Else
Messagebox(Strconv(lctarget,11)+' ok',64+4096,'Tips',800)
Endif
Else
try
oxhttp.Quit
Catch
EndTry
Release oxhttp
a = a - 1
Endif
Endfor
都市夜猫 2017-11-28
  • 打赏
  • 举报
回复
其实你确已找到了问题所在,再解决两个问题就好 1. 你的 urlencode 函数要改下,只要编码中文就好了,地址编码正确后,下载没问题 例如: http://www.ifrog.cc/uploads/2016/001-字母的发音(2).mp4 编码为: http://www.ifrog.cc/uploads/2016/001-%E5%AD%97%E6%AF%8D%E7%9A%84%E5%8F%91%E9%9F%B3(2).mp4 2. 第二个问题倒是有些麻烦 类似 006-单元音【æ】的发音.m4v 中字母æ,这种字母 ascii > 127,在不支持 unicode 的 vfp 中就不太容易处理 当打开浏览器获取下载地址时,vfp 得到的 innerHTML 已经转成了 ANSI 编码,也就丢失了下载地址中的 æ 字符(变成了 ?),地址错误导致下载失败
都市夜猫 2017-11-28
  • 打赏
  • 举报
回复
ok,既然楼主账号都给了,那咱就试试
都市夜猫 2017-11-28
  • 打赏
  • 举报
回复
不支持 unicode 是 vfp 的死穴,对微软来说应该是挺简单的一件事情,商业利益导致而已 如果你分析获取到的 innerHTML 真实内容,可将它输出到一个 txt 文本文件,记事本就可以正确解释其中的内容 ... SYS(3101,65001) && 重要: 定义 vfp 与 COM 对象间用 utf-8 编码交换数据 SourceCode1 = oxhttp.DOCUMENT.body.innerhtml && 现在 SourceCode1 是 utf-8 编码 *----------------------- StrToFile(SourceCode1, 'innerhtml.txt', 4) && 然后用支持 unicode 的编辑器打开查看它,例如记事本 notepad.exe set step on *----------------------- SYS(3101,0) ...
都市夜猫 2017-11-28
  • 打赏
  • 举报
回复
你看到乱码是因为 vfp 不支持,所以不能正确显示 utf-8 编码的字符串,这不奇怪,不影响存放在内存中的数据
utf-8 编码对于 ascii < 128 的字符仍只使用一个字节来表示,所以 vfp 能正确会显示它们;对于 > 127 的字符会采用变长字节来存储,这些就无法正确显示,也就是你看到的乱码

你好像少改了一个地方:
URLDownloadToFileA 都要换成 URLDownloadToFileW
fojiao8745 2017-11-28
  • 打赏
  • 举报
回复
引用 7 楼 dkfdtf 的回复:
其实你确已找到了问题所在,再解决两个问题就好

1. 你的 urlencode 函数要改下,只要编码中文就好了,地址编码正确后,下载没问题
例如:
http://www.ifrog.cc/uploads/2016/001-字母的发音(2).mp4
编码为:
http://www.ifrog.cc/uploads/2016/001-%E5%AD%97%E6%AF%8D%E7%9A%84%E5%8F%91%E9%9F%B3(2).mp4

2. 第二个问题倒是有些麻烦
类似 006-单元音【æ】的发音.m4v 中字母æ,这种字母 ascii > 127,在不支持 unicode 的 vfp 中就不太容易处理
当打开浏览器获取下载地址时,vfp 得到的 innerHTML 已经转成了 ANSI 编码,也就丢失了下载地址中的 æ 字符(变成了 ?),地址错误导致下载失败

版主大大,在我这边运行不行啊,转成UTF-8之后全是乱码,然后下载每个都是failed,下面是调试的截图和现在的代码,烦请再帮我看看呗。



代码如下:
DECLARE LONG URLDownloadToFileA IN Urlmon LONG, STRING@, STRING@, LONG, LONG
DECLARE LONG DeleteUrlCacheEntry IN Wininet STRING@
LOCAL oxhttp AS Microsoft.xmlhttp
oxhttp=CREATEOBJECT("Microsoft.xmlhttp")
oxhttp.OPEN("GET",'http://www.ifrog.cc/course/28',.F.)
oxhttp.SEND()
SourceCode=oxhttp.responseBody
RELEASE oxhttp
SourceCode = STRCONV(SourceCode,11)
lclength = LEN(SourceCode)
FOR a=1 TO lclength
lcString=SUBSTR(SourceCode,a,31)
IF lcString == '<i class="icon-course-chapter">'
lnstart = a
a = lclength
ENDIF
ENDFOR

FOR a=lnstart TO lclength
lcString=SUBSTR(SourceCode,a,52)
IF lcString == '<form action="/comment/course/28" id="comment-form">'
lnend = a
a = lclength
ENDIF
ENDFOR

SourceCode = SUBSTR(SourceCode,lnstart,lnend - lnstart)
FOR a = 1 TO 49
lcnum = STREXTRACT(SourceCode,'<a href="/section/','" target="_blank">',a)
lcurl = 'http://www.ifrog.cc/section/'+lcnum

LOCAL oxhttp
lndelay = 0
lcstatus = 'ok'
oxhttp=CREATEOBJECT("InternetExplorer.Application")
oxhttp.NAVIGATE(lcurl)
oxhttp.VISIBLE = .T.
DO WHILE oxhttp.ReadyState != 4 AND lcstatus == 'ok'
INKEY(1,'H')
lndelay = lndelay + 1
IF lndelay = 5
lcstatus = 'fail'
ENDIF
ENDDO

IF lcstatus = 'ok'
SYS(3101,65001) && 重要: 定义 vfp 与 COM 对象间用 utf-8 编码交换数据
SourceCode1 = oxhttp.DOCUMENT.body.innerhtml && 现在 SourceCode1 是 utf-8 编码
SYS(3101,0)
TRY
oxhttp.QUIT
CATCH
ENDTRY
RELEASE oxhttp

LOCAL c1, c2
c1 = STRCONV([file:'/uploads/2016/],9)
c2 = STRCONV(['],9)
lctarget = STREXTRACT(SourceCode1,c1,c2,1)
lcdownurl = STRCONV([http://www.ifrog.cc/uploads/2016/],9)+lctarget
lcdownurl = URLEncode2(lcdownurl)
IF DownloadFile(STRCONV(lcdownurl+CHR(0),5),STRCONV(lctarget+CHR(0),12)) = .F.
MESSAGEBOX(STRCONV(lctarget,11)+' failed',48+4096,'Tips',800)
ELSE
MESSAGEBOX(STRCONV(lctarget,11)+' ok',64+4096,'Tips',800)
ENDIF
ELSE
TRY
oxhttp.QUIT
CATCH
ENDTRY
RELEASE oxhttp
a = a - 1
ENDIF
ENDFOR

***********************Function DownloadFile***********************
FUNCTION DownloadFile(cURL, cLocalFileName)
IF URLDownloadToFileA(0, @cURL, @cLocalFileName, 0, 0) == 0
DeleteUrlCacheEntry(@cURL)
RETURN .T.
ENDIF
RETURN .F.
ENDFUNC
***************************Function End*****************************

*************************Function urlencode*************************
FUNCTION URLEncode2(lcurl)
LOCAL ReadyState, ii
ReadyState = ''
FOR ii=1 TO LEN(lcurl)
ReadyState = ReadyState + '%' + RIGHT(TRANSFORM(ASC(SUBSTR(lcurl, ii, 1)), '@0'), 2)
ENDFOR
RETURN ReadyState
ENDFUNC
***************************Function End*****************************

*************************Function urlencode2*************************
FUNCTION URLEncode2(tcUrl)
LOCAL cRet, cc, c2, ii, jj

tcUrl = STRCONV(tcUrl,12)
cRet = ''
FOR ii = 1 TO LEN(tcUrl) STEP 2
cc = SUBSTR(tcUrl, ii, 2)
IF ASC(RIGHT(cc,1)) == 0 AND ASC(LEFT(cc,1)) < 128
cRet = cRet + LEFT(cc, 1)
ELSE
cc = STRCONV(STRCONV(cc,10), 15)
c2 = ''
FOR jj = 1 TO LEN(cc) STEP 2
c2 = c2 + '%' + SUBSTR(cc,jj,2)
ENDFOR
cRet = cRet + c2
ENDIF
ENDFOR
RETURN cRet
ENDFUNC
***************************Function End******************************
fojiao8745 2017-11-28
  • 打赏
  • 举报
回复
引用 8 楼 dkfdtf 的回复:
大概调试了下,试了下10来个文件,问题不大 1. 另写了个专用的 URLEncode2
Function URLEncode2(tcUrl)
    Local cRet, cc, c2, ii, jj

    tcUrl = Strconv(tcUrl,12)
    cRet = ''
    For ii = 1 to Len(tcUrl) step 2
        cc = Substr(tcUrl, ii, 2)
        If Asc(Right(cc,1)) == 0 and Asc(Left(cc,1)) < 128
            cRet = cRet + Left(cc, 1)
        Else
            cc = Strconv(Strconv(cc,10), 15)
            c2 = ''
            For jj = 1 to Len(cc) step 2
                c2 = c2 + '%' + Substr(cc,jj,2)
            EndFor
            cRet = cRet + c2
        EndIf
    EndFor
    Return cRet
EndFunc
2. 由于要保存带 unicode 字符的文件名,URLDownloadToFile 要调用其 unicode 版本,最开始声明改为 Declare Long URLDownloadToFileW In Urlmon Long, String@, String@, Long, Long Function DownloadFile 中A 也同步改为 W 3. 获取下载地址和下载文件部分修改如下:
...
SourceCode = Substr(SourceCode,lnstart,lnend - lnstart)
For a = 1 To 49
    lcnum = Strextract(SourceCode,'<a href="/section/','" target="_blank">',a)
    lcurl = 'http://www.ifrog.cc/section/'+lcnum

    Local oxhttp
    lndelay = 0
    lcstatus = 'ok'
    oxhttp=Createobject("InternetExplorer.Application")
    oxhttp.Navigate(lcurl)
    oxhttp.Visible =  .T.
    Do While oxhttp.ReadyState != 4 And lcstatus == 'ok'
        Inkey(1,'H')
        lndelay = lndelay + 1
        If lndelay = 5
            lcstatus = 'fail'
        Endif
    Enddo

    If lcstatus = 'ok'
        Sys(3101,65001)     && 重要: 定义 vfp 与 COM 对象间用 utf-8 编码交换数据
        SourceCode1 = oxhttp.Document.body.innerhtml    && 现在 SourceCode1 是 utf-8 编码
        Sys(3101,0)
try
    oxhttp.Quit
Catch
EndTry
        Release oxhttp

        Local c1, c2
        c1 = Strconv([file:'/uploads/2016/],9)
        c2 = Strconv(['],9)
        lctarget = Strextract(SourceCode1,c1,c2,1)
        lcdownurl = Strconv([http://www.ifrog.cc/uploads/2016/],9)+lctarget
        lcdownurl = URLEncode2(lcdownurl)
        If DownloadFile(Strconv(lcdownurl+Chr(0),5),Strconv(lctarget+Chr(0),12)) = .F.
            Messagebox(Strconv(lctarget,11)+' failed',48+4096,'Tips',800)
        Else
            Messagebox(Strconv(lctarget,11)+' ok',64+4096,'Tips',800)
        Endif
    Else
try
    oxhttp.Quit
Catch
EndTry
        Release oxhttp
        a = a - 1
    Endif
Endfor
谢谢版主大大的指点,我现在去调试一下,非常感谢
fojiao8745 2017-11-27
  • 打赏
  • 举报
回复
引用 2 楼 dkfdtf 的回复:
注册还要填手机号 那我还是算了吧
代码不可以用vb的模板吗?怎么没有格式了。。。。
fojiao8745 2017-11-27
  • 打赏
  • 举报
回复
引用 2 楼 dkfdtf 的回复:
注册还要填手机号 那我还是算了吧
版主大人。。。别啊。。。帮我看下呗。。。我账号17751295643 密码123456
加载更多回复(3)

2,718

社区成员

发帖
与我相关
我的任务
社区描述
VFP,是Microsoft公司推出的数据库开发软件,用它来开发数据库,既简单又方便。
社区管理员
  • VFP社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧