![Board logo](images/default/logo.gif)
标题: 强劲的多线程下载器 purl.exe [打印本页]
作者: happy886rr 时间: 2017-8-25 22:10 标题: 强劲的多线程下载器 purl.exe
本帖最后由 happy886rr 于 2017-8-26 08:54 编辑
控制台下强劲的多线程下载器,快如闪电。支持purl.ini配置文件。批量下载各类url资源链。
用法:
purl -i[配置文件.ini] -l[输出日志] -n[线程数] -r[根目录]\n\
配置文件书写格式
#############################################################################
http://www.a.com/[:0].[:1]
#############################################################################
[:0]=01-99
#############################################################################
[:1]=jpg,gif,png,bmp
[:2]=
[:3]=
...
其中[:0]到[:9]为URL通配符,启用[:0]后具有多线程效益,启用[:9]具有尾加速功能。这10个通配符可以是数字范围如:[:0]=1-9;也可以是字符范围,如[:1]=a-z;还可以是字符串枚举,如:[:2]=jpg,mp3,txt,doc
为节省论坛空间,不提供任何附件下载,源码发行。- /*
- THE THREAD DOWNLOAD TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0
- PURL.EXE
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <windows.h>
- #include <process.h>
- #include <direct.h>
- #include <time.h>
- #include <math.h>
- #include <io.h>
-
- #pragma comment(lib, "Ws2_32.lib")
- #pragma comment (lib,"urlmon.lib")
-
- /*************宏量定义*************/
- #define SAFE_SIZE 512
- #define FILE_EXIST 0
-
- //定义配置文件
- #define PURL_INI "\
- #################################################################\n\
- http://\n\
- #################################################################\n\
- [:0]=\n\
- #################################################################\n\
- [:1]=\n\
- [:2]=\n\
- [:3]=\n\
- [:4]=\n\
- [:5]=\n\
- [:6]=\n\
- [:7]=\n\
- [:8]=\n\
- #################################################################\n\
- [:9]=\n\
- #################################################################\n"
-
- //定义帮助说明
- #define HELP_INFORMATION "\
- -----------------------------------------------------------------\n\
- purl -i[inifile] -l[outlog] -n[threadnum] -r[rootdir]\n\
- -----------------------------------------------------------------\n\
- -h Show help information\n\
- -i Set the purl inifile\n\
- -l Set the log output directory\n\
- -n Set the number of concurrent threads to download\n\
- -r Set the download root directory\n\
- -----------------------------------------------------------------\n\
- version 1.0"
-
- /*************全局变量*************/
- static int M[10], N[10], Z[10];
- static int prointThread=0, nowsThread=0, trueDownload=0, totalCYC=1;
-
- static char murl[SAFE_SIZE], outlog[SAFE_SIZE], inifile[SAFE_SIZE]=".\\purl.ini", mpath[SAFE_SIZE]=".\\", settingini[10][SAFE_SIZE*2], *S[10][SAFE_SIZE];
-
- static BOOL renMARK[10];
- static BOOL urlMARK=FALSE;
-
- FILE* logfp;
-
- //进度条容器
- static const char* proGRESS="[ ]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
-
- /*************事件变量*************/
- //创建事件对象
- HANDLE ghDataEvent;
-
- /*************功能函数*************/
- //切分字串
- int ArgsSpliy(char* Str, int SN)
- {
- int i=0;
- char* pstr=strtok(Str, " \t\n,");
-
- while(pstr !=NULL){
- S[SN][i]=(char*)calloc(strlen(pstr)+1, sizeof(char));
- strcpy(S[SN][i++], pstr);
- pstr=strtok(NULL, " \t\n,");
- }
- return i;
- }
- //判断字母
- BOOL isLetter(char* p)
- {
- return (p && (('A'<=*p&&*p<='Z')||('a'<=*p&&*p<='z'))&&(*(p+1)=='\0'))?TRUE:FALSE;
- }
- //彩显函数
- int ColorString(HANDLE handle_out, char* pstrA, char* pstrB, int colorA, int colorB, int num)
- {
- SetConsoleTextAttribute(handle_out, colorA); //项目色
- fprintf(stdout, pstrA);
- SetConsoleTextAttribute(handle_out, colorB); //数据色
- (num<0)?fprintf(stdout, pstrB):fprintf(stdout, "%d\n", num);
- return 0;
- }
- //光标函数
- BOOL DispyCursor(int size,bool mode)
- {
- CONSOLE_CURSOR_INFO cinfo ={(DWORD)size, mode};
- return SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cinfo);
- }
- //域名IP解析
- int DownloadURLtoIP(HANDLE handle_out, const char* downloadURL)
- {
- WSADATA wsaData;
- WSAStartup(MAKEWORD(2,2), &wsaData);
-
- char *pstr=(char*)downloadURL, *urlweb=(char*)calloc(SAFE_SIZE, sizeof(char)), *tstr=urlweb;
-
- while(*pstr!=':'){pstr++;}
- pstr+=3;
- while(*pstr!='/'&& *pstr!='\n' && *pstr!='\0'){
- *tstr++=*pstr++;
- }
-
- const char* pszUrl=(const char*)urlweb;
-
- if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
- {
- //fprintf(stdout, "Init socket faile\n");
- return 1;
- }
- struct hostent *pHost = gethostbyname(pszUrl);
-
- //释放空间
- free(urlweb);
-
- if (pHost == NULL)
- {
- WSACleanup();
- //fprintf(stdout, "pHost == NULL \n");
- return 1;
- }
-
- //主机正式名称
- ColorString(handle_out, "[URL-HOST] ", (pHost)?pHost->h_name:"NULL", 4|8, 1|2|8, -1);
- fprintf(stdout, "\n");
-
- //主机别名,可以有多个
- int iIndex = 0;
- while(pHost->h_aliases[iIndex])
- {
- ColorString(handle_out, "[URLALIAS] ", pHost->h_aliases[iIndex], 4|8, 1|2|8, -1);
- fprintf(stdout, "\n");
- iIndex++;
- }
-
- //地址字节数,IPV4是4,IPV6是6
- if(pHost->h_length==4)
- {
- ColorString(handle_out, "[IPV-TYPE] ", "IPV4\n", 4|8, 4|8, -1);
- }
- else if(pHost->h_length==6)
- {
- ColorString(handle_out, "[IPV-TYPE] ", "IPV6\n", 4|8, 4|8, -1);
- }
-
- iIndex = 0;
- while(pHost->h_addr_list[iIndex])
- {
- ColorString(handle_out, "[IP-ADDRE] ", inet_ntoa(*(struct in_addr*)pHost->h_addr_list[iIndex]), 4|8, 4|2|8, -1);
- fprintf(stdout, "\n");
- iIndex++;
- }
- WSACleanup();
- return 0;
- }
- //开关解析
- int OPTIND=1, OPTOPT;
- char *OPTARG;
- int GetOpt(int nargc, char *nargv[], char *ostr)
- {
- static char* place="";
- static char* lastostr=(char *) 0;
- register char* oli;
- char* index();
- if(ostr!=lastostr){
- lastostr=ostr;
- place="";
- }
- if(!*place)
- {
- if(
- (OPTIND>=nargc) ||
- (*(place=nargv[OPTIND])!='-')||
- (!*(++place))
- ){
- place="";
- return(EOF);
- }
- if (*place == '-' && place[1] == 0){
- ++OPTIND;
- return(EOF);
- }
- }
- if ((OPTOPT=(int)*place++)==(int)':' || !(oli=strchr(ostr, OPTOPT))){
- if(!*place){++OPTIND;}
- }
-
- if (oli != NULL && *(++oli) != ':'){
- OPTARG=NULL;
- if(!*place){++OPTIND;}
- }
- else{
- if(*place){
- OPTARG=place;
- }else if(nargc<=++OPTIND){
- place="";
- }else{
- OPTARG=nargv[OPTIND];
- }
- place="";
- ++OPTIND;
- }
- return(OPTOPT);
- }
-
- /*************获取配置*************/
- int ReadSetting(char* pfile)
- {
- //读取脚本文件
- FILE* fp;
- if( (fp=fopen(pfile, "r"))==NULL ){
- fprintf(stdout, "Reading settings failed!\n");
- exit(1);
- }
-
- int SN;
-
- //分配行容器
- char* LCache=(char*)calloc(1025, sizeof(char));
- //辅助行指针
- char* Line=NULL;
-
- while(!feof(fp)){
-
- memset(LCache, 0, 1024*sizeof(char));
- fgets(LCache, 1024, fp);
-
- //指针置换
- Line=LCache;
-
- //将尾部换行符注掉
- while(*Line!='\n'&& *Line!='\0'){Line++;}
- *Line='\0';
- Line=LCache;
-
- //过滤行TAB缩进或前空格
- while(*Line=='\t'|| *Line==' '){Line++;}
-
- //过滤注释符
- if(Line[0]=='#'||strlen(Line)<=5){
- continue;
- }
-
- //提取URL
- if(
- (!urlMARK) &&
- (Line[0]=='h' ||Line[0]=='H') &&
- (Line[1]=='t' ||Line[1]=='T') &&
- (Line[2]=='t' ||Line[2]=='T') &&
- (Line[3]=='p' ||Line[3]=='P') &&
- (
- Line[4]==':' ||
- (
- (Line[4]=='s'||Line[4]=='S') &&
- (Line[5]==':')
- )
- )
- ){
- if(strlen(Line)<10){
- fprintf(stdout, "Please fill the url!\n");
- exit(1);
- }
-
- strcpy(murl, Line);
- while(*Line !='\0'){
- if(*Line=='[' && *(Line+1)==':' && ('0'<=*(Line+2) && *(Line+2)<='9') && *(Line+3)==']'){
- renMARK[*(Line+2)-48]=TRUE;
- Line+=4;
- }else{
- Line++;
- }
- }
- urlMARK=TRUE;
- continue;
-
- }else if(
- (urlMARK) &&
- (Line[0]=='[' &&Line[1]==':') &&
- ('0'<=Line[2] &&Line[2]<='9') &&
- (Line[3]==']' &&Line[4]=='=')
-
- ){
- SN=Line[2]-48;
- if(!renMARK[SN]){continue;}
-
- strcpy(settingini[SN], Line);
-
- if(strchr(Line+5, ',')){
- M[SN]=0;
- N[SN]=ArgsSpliy(Line+5, SN)-1;
-
- }else if(renMARK[SN]){
-
- char *snumsrc=strtok(Line+5, " \t-"), *tmps=(snumsrc!=NULL)?strtok(NULL, " \t-"):NULL, *zp=snumsrc;
-
- if(isLetter(snumsrc) && isLetter(tmps)){
- int exnum1=*snumsrc, exnum2=*tmps;
- Z[SN]=-1;
- M[SN]=(exnum1 <= exnum2)?(N[SN]=exnum2, exnum1):(N[SN]=exnum1, exnum2);
-
- }else if(tmps!=NULL){
- if(*zp=='0'){
- while('0'<= *zp && *zp <='9'){
- Z[SN]++;
- zp++;
- }
- }
- M[SN]=atoi(snumsrc), N[SN]=atoi(tmps);
- if(M[SN]>N[SN]){
- int exnum=M[SN];
- M[SN]=N[SN], N[SN]=exnum;
- }
- }
- }
- }
- }
- fclose(fp);
-
- //统计总循环次数
- for(int i=0; i<10; i++){totalCYC *=N[i]-M[i]+1;}
- return 0;
- }
-
- /*************下载函数*************/
- UINT WINAPI FastDownload(void* ptr)
- {
- //分配URL字串
- char* ptftr=(char*)calloc(16, sizeof(char));
- char* aurl =(char*)calloc(SAFE_SIZE, sizeof(char));
- char* dest =(char*)calloc(SAFE_SIZE, sizeof(char));
- char* durl =(char*)calloc(SAFE_SIZE, sizeof(char));
- char* titl =(char*)calloc(SAFE_SIZE, sizeof(char));
- durl[0]='.', durl[1]='\\';
-
- //接受线程传参
- int nThreadID = *((int*)ptr);
- int snum = *((int*)ptr+1);
- int lnum = *((int*)ptr+2);
-
- SetEvent(ghDataEvent);
- nowsThread++;
- if(*outlog != 0){
- //fprintf(logfp, "\nThe %dth thread start.\n", nThreadID+1);
- }
-
- //创建循环变量数组
- int i[10]={0}, SN;
-
- //创建下载状态变量
- BOOL preMARK=FALSE, nowMARK=FALSE;
-
- //定义URL指针
- char *purl=NULL, *surl=NULL, *pdit=NULL;
-
- //启动十层循环
- for(i[0]=snum; i[0]<=lnum; i[0]++)
- for(i[1]=M[1]; i[1]<=N[1]; i[1]++)
- for(i[2]=M[2]; i[2]<=N[2]; i[2]++)
- for(i[3]=M[3]; i[3]<=N[3]; i[3]++)
- for(i[4]=M[4]; i[4]<=N[4]; i[4]++)
- for(i[5]=M[5]; i[5]<=N[5]; i[5]++)
- for(i[6]=M[6]; i[6]<=N[6]; i[6]++)
- for(i[7]=M[7]; i[7]<=N[7]; i[7]++)
- for(i[8]=M[8]; i[8]<=N[8]; i[8]++)
- for(i[9]=M[9]; i[9]<=N[9]; i[9]++){
-
- surl=murl, purl=aurl;
-
- while(*surl !='\0'){
-
- //替换正则标签
- if(*surl=='[' && *(surl+1)==':' && '0'<=*(surl+2) && *(surl+2)<='9' && *(surl+3)==']' && renMARK[*(surl+2)-48]){
-
- SN=*(surl+2)-48;
-
- if(S[SN][0] !=NULL){
- pdit=S[SN][i[SN]];
- }else{
- if(Z[SN] >0){
- sprintf(ptftr, "%%0%dd", Z[SN]);
- sprintf(dest, ptftr, i[SN]);
-
- }else if(Z[SN]==-1){
- sprintf(dest, "%c", (char)i[SN]);
-
- }else{
- sprintf(dest, "%d", i[SN]);
- }
- pdit=dest;
- }
-
- while(*pdit !='\0'){
- *(purl++)=*(pdit++);
- }
- surl+=4;
-
- }else{
- *(purl++)=*(surl++);
- }
- }
- //置结束符
- *purl='\0';
-
- //显示当前下载的URL
- prointThread++;
-
- sprintf(titl, "[%03dT]-[%03dF] %s", nowsThread, trueDownload, aurl);
- SetConsoleTitleA(titl);
-
- //处理下载路径
- char* turl=strstr(aurl, "://")+3;
- char* sp=durl+2;
-
- //根据网址创建目录
- while(*turl != '\0'){
- switch(*turl)
- {
- case '/':
- *sp='\0';
- if(_access(durl, FILE_EXIST) != 0){
- _mkdir(durl);
- }
- *sp='\\';
- break;
-
- case ':':
- case '*':
- case '?':
- case '"':
- case '>':
- case '<':
- case '|':
- *sp='@';
- break;
-
- default:
- *sp=*turl;
- break;
- }
- //指针移位
- sp++, turl++;
- }
- //置结束符
- *sp='\0';
-
- //调用API下载
- URLDownloadToFileA(NULL, aurl, durl, 0, NULL);
-
- //下载状态
- nowMARK=(_access(durl, FILE_EXIST)==0)?TRUE:FALSE;
-
- //增速判断
- if(preMARK && !nowMARK && i[9]!=M[9]){
- break;
- }
-
- //显示下载成功的文件
- if(nowMARK){
- trueDownload++;
- if(*outlog != 0){fprintf(logfp, "[*]%s\n", aurl);}
- }
-
- //下载状态更新
- preMARK=nowMARK;
- }
-
- //释放数组内存
- free(aurl);
- free(durl);
- free(dest);
- free(titl);
- free(ptftr);
-
- //线程结束
- nowsThread--;
- if(*outlog != 0){
- //fprintf(logfp, "\nThe %dth thread end!\n\n", nThreadID+1);
- }
- return (UINT)0;
- }
-
- /*************MAIN函数*************/
- int main(int argc, char** argv)
- {
- int threadNUMS=100;
- char K, *outLOG=NULL;
- while((K=GetOpt(argc,argv,"hi:n:p:l:"))!=-1)
- {
- switch(K)
- {
- case 'h':
- case 'H':
- fprintf(stdout, HELP_INFORMATION);
- exit(0);
-
- case 'i':
- case 'I':
- if(OPTARG !=NULL){
- strcpy(inifile, OPTARG);
- }
- break;
-
- case 'l':
- case 'L':
- if(OPTARG !=NULL){
- strcpy(outlog, OPTARG);
- }
- break;
-
- case 'n':
- case 'N':
- if(OPTARG !=NULL){
- int exnum=atoi(OPTARG);
- threadNUMS=(0<exnum && exnum<SAFE_SIZE*4)?exnum:SAFE_SIZE*4;
- }
- break;
-
- case 'r':
- case 'R':
- if(OPTARG !=NULL){
- strcpy(mpath, OPTARG);
- }
- break;
-
- default:
- fprintf(stdout, "Unknown switch '%c'\n", K);
- exit(1);
- }
- }
-
- //判断配置文件是否存在
- if(access(inifile, FILE_EXIST)!=0){
- FILE* fp=fopen(inifile, "w");
- fprintf(fp, PURL_INI);
- fclose(fp);
- fprintf(stdout, "Please fill in the setting file\n");
- fprintf(stdout, HELP_INFORMATION);
- exit(1);
- }
-
- if(argc==1){
- //无参数则退出
- fprintf(stdout, HELP_INFORMATION);
- exit(0);
- }
-
- //判断根目录是否存在
- if(_access(mpath, FILE_EXIST)!=0){
- _mkdir(mpath);
- }
- if(_access(mpath, FILE_EXIST)==0){
- //切换至下载目录
- _chdir(mpath);
- }else{
- //无法创建根目录则退出
- fprintf(stdout, "Can not creat the root folder\n");
- exit(1);
- }
-
- //读取purl配置文件
- ReadSetting(inifile);
- if(! urlMARK){
- fprintf(stdout, "Please fill in the download url\n");
- exit(1);
- }
-
- //获取控制台输出句柄
- HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);
-
- //线程传参数组
- int inum[3]={0};
-
- //判断是否使用多线程正则符[:0]
- if(! renMARK[0]){
- threadNUMS=1;
- }
-
- //线程数
- int nThreadCount=N[0]-M[0];
- if(nThreadCount<=0 && threadNUMS!=1){
- fprintf(stdout, "\nThe '[:0]' don't get incremental value\n");
- exit(1);
- }
-
- //创建时间结构体
- time_t startTIME, endTIME;
- struct tm* timeinfo;
- time(&startTIME);
- timeinfo=localtime(&startTIME);
-
- //计算线程分组数
- int rThreadAdd =(int)ceil((nThreadCount + 1)*1.0/threadNUMS);
- int rThreadRange =(int)ceil((nThreadCount + 1)*1.0/(rThreadAdd?rThreadAdd:1.0));
-
- //是否开启日志输出
- if(*outlog != 0){
- logfp=fopen(outlog, "w");
- if(logfp == NULL){
- fprintf(stdout, "Open log failed\n");
- exit(1);
- }else{
- fprintf(logfp,
- "================================================================\n"
- "The purl log file, Time: %s"
- "================================================================\n\n"
- ,asctime(timeinfo)
- );
- fprintf(logfp, "[Threads num]\n%d\n\n", rThreadRange);
- fprintf(logfp, "[Root path]\n%s\n\n", mpath);
- fprintf(logfp, "[The URL regular]\n%s\n\n", murl);
- fprintf(logfp, "[Setting ini]\n");
- for(int i=0; i<=9; i++){
- if(settingini[i][0]!=0){
- fprintf(logfp, "%s\n", settingini[i]);
- }
- }
- fprintf(logfp, "\n[Start the download time]\n%s\n", asctime(timeinfo));
- fprintf(logfp, "[Successfully downloaded URL]\n");
- }
- }
- //隐藏光标
- DispyCursor((DWORD)25, FALSE);
- //显示目标网站IP
- DownloadURLtoIP(handle_out, murl);
-
- //分配线程句柄数组
- HANDLE* phaThread =(HANDLE*)calloc(rThreadRange, sizeof(HANDLE));
-
- //创建事件对象
- ghDataEvent =CreateEventA(NULL, FALSE, FALSE, NULL);
-
- //错误号
- int nErr=0;
-
- for(int i=0; i<rThreadRange; i++){
-
- inum[0]=i, inum[1]=M[0]+i*rThreadAdd, inum[2]=M[0]+i*rThreadAdd+rThreadAdd-1;
- if(inum[2]>N[0]){inum[2]=N[0];}
-
- phaThread[i]=(HANDLE)_beginthreadex(NULL, 0, FastDownload, &inum, 2048, NULL);
-
- if(phaThread[i]==0){
- nErr=GetLastError();
- if(nErr==0x08){
- printf("\nOpen thread failed, lack of storage space!\n");
- }else{
- printf("\nOpen thread failed, error number%d\n", nErr);
- }
- break;
- }
- WaitForSingleObject(ghDataEvent, INFINITE);
- }
-
- //色彩代码 紫色1|4|8,红色4|8,绿色2|8,兰色1|2|8,黄色2|4|8,白色1|2|4|8;
-
- //显示最大线程
- ColorString(handle_out, "[MAX-THRE] ", "", 4|8, 4|8, rThreadRange);
-
- //显示开始时间
- ColorString(handle_out, "[STA-TIME] ", asctime(timeinfo), 4|8, 1|4|8, -1);
-
- //绘制进度框
- ColorString(handle_out, "[DOWNLOAD] ", (char*)proGRESS, 4|8, 2|4|8, -1);
-
- //绘制进度条
- int spi=0;
-
- do{
- //进度百分数
- int i=(totalCYC==0)?100:(prointThread*100/totalCYC), j=i/2;
- if(spi==j){
- //缓解CPU占用
- Sleep(30);
- continue;
- }
-
- //显示递增进度
- while(spi<j){
- fputc('=', stdout);
- spi++;
- }
-
- //显示进度百分比
- fprintf(stdout, "%3d%%\b\b\b\b", i);
-
- //线程退出器
- if(prointThread==totalCYC){
- break;
- }
-
- }while(nowsThread);
-
- //补全百分百进度
- if(prointThread==totalCYC){
- while(spi<50){
- fputc('=', stdout);
- spi++;
- }
- fprintf(stdout, "100%%");
- }
- fprintf(stdout, "\n");
-
- //显示结束时间
- time(&endTIME);
- timeinfo=localtime(&endTIME);
- ColorString(handle_out, "[END-TIME] ", asctime(timeinfo), 4|8, 1|4|8, -1);
-
- //显示花费时间
- ColorString(handle_out, "[USE-TIME] ", "", 4|8, 1|2|8, -1);
- fprintf(stdout, "Takes %gs\n", difftime(endTIME, startTIME));
-
- //颜色归位
- SetConsoleTextAttribute(handle_out, 1|2|4);//白色
-
- //关闭日志读写
- if(*outlog != 0){
- fprintf(logfp, "\n[End the download time]\n%s\n", asctime(timeinfo));
- fprintf(logfp, "[Download time-spending]\n%g seconds\n\n", difftime(endTIME, startTIME));
- fprintf(logfp, "[Percent of completion]\n%d%%\n\n", (prointThread==totalCYC)?100:spi*2);
- fprintf(logfp, "[Successfully downloaded files]\n%d", trueDownload);
- fclose(logfp);
- }
- return 0;
- }
复制代码
作者: freesoft00 时间: 2017-8-26 01:13
是我用错了吗?怎么不行。
https://download.mozilla.org/?product=firefox-55.0.3-SSL&os=win&lang=zh-CN
http://ftp.mozilla.org/pub/firefox/releases/55.0.3/win32/zh-CN/Firefox%20Setup%2055.0.3.exe
https://ipmsg.org/archive/ipmsg470src.zip
把这三个网址分别添加到purl.ini中,也不行。弹出错误。
作者: happy886rr 时间: 2017-8-26 08:26
本帖最后由 happy886rr 于 2017-8-26 09:07 编辑
回复 2# freesoft00
代码已经修复,这是多线程批量下载器,只支持批量地址下载,比如www.a01.com, www.a02.com, www.a03.com就是批量的网址,而不是说单一下载某个文件。
单独下载某个文件请使用pget。
purl的目的是针对有规律的数字递增网址,批量多线程下载,而且必须是几千、几万的批量网址才可以成功下载。线程过少的话,主程序很快就跑完了,子线程也就结束了。我把下载量调到5000,你的文件都成功下载了[:0]=0-5000
purl是针对繁重的批量下载任务定制的,个别几个小文件的下载多线程会得不偿失,小文件请使用pget。
作者: freesoft00 时间: 2017-8-26 11:46
回复 3# happy886rr
哦,知道了。用途不一样呀。
作者: llh931886 时间: 2017-9-14 14:39
支持 ssh 链接的 sftp 下载吗?
作者: CrLf 时间: 2017-10-10 00:37
请教下要怎么编译?
gcc和vs均未通过
作者: 523066680 时间: 2017-10-10 09:49
本帖最后由 523066680 于 2017-10-10 10:02 编辑
回复 6# CrLf
试了 MinGW GCC, 稍微改一下可以
添加 <stdbool.h>
注释掉两个 lib 的引入(改为手动)- #include <stdbool.h>
-
- // #pragma comment(lib, "ws2_32.lib")
- // #pragma comment (lib,"urlmon.lib")
复制代码
gcc purl.c -lws2_32 -lurlmon
作者: happy886rr 时间: 2017-10-10 13:39
本帖最后由 happy886rr 于 2017-10-10 14:10 编辑
回复 6# CrLf
大师,好久不见。(后缀一定要改为cpp)
编译现在都已经实现一键了,请参看我之前的帖子http://www.bathome.net/thread-44180-1-1.html
下载那个精简的vc++2010编译器(仅22M大小),把.cpp文件直接拖拽到VC.CMD批处理脚本上,就会自动生成exe。
别看体积小,编译功能与原版VS几乎没有差别。
另外我还发布过手机版的gcc编译器,可以实现代码直接编译为 安卓上可运行的二进制文件。从而实现 win、linux、安卓 各平台通吃。
作者: netdzb 时间: 2019-6-28 13:11
回复 8# happy886rr
手机版本的编译器在哪里?
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |