随便找个图片网页https://esports.zol.com.cn/slide/688/6885385_1.html 来练手抓取和下载图片。首先要分析html代码,看下载目标的链接命名是否有规律,有规律就用regex抓取地址,再用wininet中的函数下载;然后再找出下一图集的链接,反复循环就能遍历网站的图片(如要下载其它文件类型也可以)。原理如下图所示:

源代码如下:

#include <iostream>
#include <iomanip>
#include <windows.h>
#include <wininet.h>
#include <string>
#include <regex>
#include <vector>
#include <sstream>
#include <fstream>
using namespace std;string HttpRequest(string strUrl, string strMethod="GET", string strPostData="")
{BOOL bRet;short sPort=80;char *lpHostName, *lpUrl, *lpMethod, *lpPostData;int pos, nPostDataLen=strPostData.size();string tmpUrl, strResponse = "";while ((pos = strUrl.find(" ")) != strUrl.npos) strUrl.erase(pos, 1); //删除网址中的空格 if (strUrl.substr(0,7) == "http://") strUrl=strUrl.substr(7, strUrl.size()-1); //删除网址中的协议名 if (strUrl.substr(0,8) == "https://") strUrl=strUrl.substr(8, strUrl.size()-1);if (strUrl.empty()) return strResponse;if ((pos=strUrl.find("/")) != strUrl.npos){tmpUrl = strUrl.substr(pos+1, strUrl.size()-1);strUrl = strUrl.substr(0, pos);} else tmpUrl = "/";lpUrl = (char*)tmpUrl.data();lpMethod = (char*)strMethod.data();lpHostName = (char*)strUrl.data();lpPostData = (char*)strPostData.data();if ((pos=strUrl.find(":")) != strUrl.npos){tmpUrl = strUrl.substr(pos+1,strUrl.size()-1);strUrl = strUrl.substr(0,pos);sPort = (short)atoi(tmpUrl.c_str());}HINTERNET hInternet, hConnect, hRequest;hInternet = hConnect = hRequest = NULL;hInternet = (HINSTANCE)InternetOpen("User-Agent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);if (!hInternet) return strResponse;hConnect = (HINSTANCE)InternetConnect(hInternet, lpHostName, sPort, NULL, "HTTP/1.1", INTERNET_SERVICE_HTTP, 0, 0);if (!hConnect){if (hInternet) InternetCloseHandle(hInternet);return strResponse;}hRequest = (HINSTANCE)HttpOpenRequest(hConnect, lpMethod, lpUrl, "HTTP/1.1", NULL, NULL, INTERNET_FLAG_RELOAD, 0);if (!hRequest){if (hInternet) InternetCloseHandle(hInternet);if (hConnect) InternetCloseHandle(hConnect);return strResponse;}bRet = HttpSendRequest(hRequest, NULL, 0, lpPostData, nPostDataLen);while (true){char cReadBuffer[4096];unsigned long lNumberOfBytesRead;bRet = InternetReadFile(hRequest, cReadBuffer, sizeof(cReadBuffer)-1, &lNumberOfBytesRead);if (!bRet || !lNumberOfBytesRead) break;cReadBuffer[lNumberOfBytesRead] = 0;strResponse = strResponse + cReadBuffer;}if (hRequest) InternetCloseHandle(hRequest);if (hConnect) InternetCloseHandle(hConnect);if (hInternet) InternetCloseHandle(hInternet);return strResponse;
}bool DownloadFile(string strUrl, string strFullFileName, unsigned int BUF_SIZE_KB = 1)
{size_t pos=0;short sPort=80;BOOL bRet;char *lpHostName, *lpUrl;string tmpUrl, strResponse = "";while ((pos = strUrl.find(" ")) != strUrl.npos) strUrl.erase(pos, 1); //删除网址中的空格 if (strUrl.substr(0,7) == "http://") strUrl=strUrl.substr(7, strUrl.size()-1); //删除网址中的协议名 if (strUrl.substr(0,8) == "https://") strUrl=strUrl.substr(8, strUrl.size()-1);if (strUrl.empty()) return false;if ((pos=strUrl.find("/")) != strUrl.npos){tmpUrl = strUrl.substr(pos+1, strUrl.size()-1);strUrl = strUrl.substr(0, pos);} else tmpUrl = "/";lpUrl = (char*)tmpUrl.data();lpHostName = (char*)strUrl.data();if ((pos=strUrl.find(":")) != strUrl.npos){tmpUrl = strUrl.substr(pos+1,strUrl.size()-1);strUrl = strUrl.substr(0,pos);sPort = (short)atoi(tmpUrl.c_str());}HINTERNET hInternet, hConnect, hRequest;hInternet = hConnect = hRequest = NULL;hInternet = (HINSTANCE)InternetOpen("User-Agent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);if (!hInternet) return false;hConnect = (HINSTANCE)InternetConnect(hInternet, lpHostName, sPort, NULL, "HTTP/1.1", INTERNET_SERVICE_HTTP, 0, 0);if (!hConnect){if (hInternet) InternetCloseHandle(hInternet);return false;}hRequest = (HINSTANCE)HttpOpenRequest(hConnect, "GET", lpUrl, "HTTP/1.1", NULL, NULL, INTERNET_FLAG_RELOAD, 0);if (!hRequest){if (hInternet) InternetCloseHandle(hInternet);if (hConnect) InternetCloseHandle(hConnect);return false;}bRet = HttpSendRequest(hRequest, NULL, 0, NULL, 0);BUF_SIZE_KB = BUF_SIZE_KB==0 ? 1024 : BUF_SIZE_KB*1024;char buf[BUF_SIZE_KB];DWORD buf_len, buf_read;buf_len = buf_read = BUF_SIZE_KB;FILE *fp = fopen(strFullFileName.c_str(), "wb");while (true) {InternetReadFile(hRequest, buf, buf_len, &buf_read);if(buf_read == 0) break;fwrite(buf, 1, buf_read, fp);}free(buf);fclose(fp);if (hRequest) InternetCloseHandle(hRequest);if (hConnect) InternetCloseHandle(hConnect);if (hInternet) InternetCloseHandle(hInternet);return true;
}int regexSplit(string &str,const string str_reg,vector<string>&vect,int pos=0)
{if (pos!=-1) pos=0;  //pos=0 匹配到的位置,pos=-1匹配位置的前一字串 regex myPattern(str_reg); sregex_token_iterator it(str.begin(),str.end(),myPattern,pos); sregex_token_iterator end;for(;it!=end;++it) vect.push_back(*it); return vect.size();  //if 0 没有匹配到,else 匹配到的个数}string replaceAll(string &s, const string sub1, const string sub2)
{   //字符串中指定字符串sub2替换s所有的子串sub1 size_t len,pos=0;if (s.empty()||sub1.empty()||sub2.empty()) return s;if (s.find(sub1)==s.npos) return s; //sub1不是s的子串就退出 len=sub1.size();while((pos=s.find(sub1,pos))!=s.npos)s.replace(pos++,len,sub2);return s;
}string int2str(int i)
{string s;stringstream ss;ss<<setw(5)<<setfill('0')<<i;s=ss.str();ss.clear();return s;
}int main()
{int i=0;bool bRet;size_t pos;string Html, url, reg;vector <string> vect, vimg;url = "https://esports.zol.com.cn/slide/688/6885385_1.html";Html = HttpRequest(url);cout<<"1-"<<endl;while ((pos=Html.find("tutie"))!=string::npos){reg="t_s1280x720(.*?).jpg"; //查找下载目标的网址装入vector regexSplit(Html,reg,vect);for (auto&v:vect){ //抓取在vector里的图片地址,逐个下载 replaceAll(v,"\\/","/");  //网站把图片地址每个/前都插入\字符,全部替换掉 url = "http://article-fd.zol-img.com.cn/"; bRet=DownloadFile(url+v,"D:\\Pictures\\zol"+int2str(++i)+".jpg");//注意:D:\Pictures 文件目录是否存在,代码没作判断if (bRet){cout<<".";if (i%20==0) cout<<endl;if (i%100==0){system("cls");cout<<i+1<<"-"<<endl;}vimg.push_back(url+v); //记录下载成功的链接 if (i>=10000) return 0; //抓取满10000张退出,或者循环到网站没有下一图集标记为止 }}reg="<a href=\"/slide/(.*?)tutie"; //找出下一图集的地址 vect.clear();regexSplit(Html,reg,vect);url = vect.at(0); //格式:<a href="/slide/688/6886276_1.html" class="tutieurl = "https://esports.zol.com.cn" + url.substr(9,url.size()-23);vect.clear();Html = HttpRequest(url);} ofstream out_file("DownList.txt"); //下载成功的链接保存到文件 if (out_file){for(auto v:vimg)out_file << v <<endl; //输出到文件out_file.close();}return 0;
}

下载成果:

本代码在Dev-C++ 5.11上通过无错编译,20分钟左右下载到1902张图片,下载速度要看个人的电脑硬件和网络带宽的,完成后图片链接都保存到源码同文件夹里的下载清单DownList.txt中(实际上是与编译好的可执行文件同路径,没有采用边下载边记录所以中途退出是没有下载清单的)。如果用多线程技术,同时间开启多个线程下载速度会成倍加快,感兴趣的话自己去试试吧。关于多线程请看我的另一篇博文《C++ Beep()演奏简谱的改进以及实现背景音乐》。

注:本代码需要用到wininet.lib 请在工具菜单-"编译器选项"里添加如下命令:-std=c++11 -lwininet。如使用vs系列编译器或在using namespace std;之前插入:#pragma comment(lib,"WinInet.lib")

C++ 抓取和批量下载网站上的图片或文件相关推荐

  1. python批量下载网页文件夹_Python抓取网页批量下载文件方法初探(正则表达式+BeautifulSoup) (转)...

    最近两周都在学习Python抓取网页方法,任务是批量下载网站上的文件.对于一个刚刚入门python的人来说,在很多细节上都有需要注意的地方,以下就分享一下我在初学python过程中遇到的问题及解决方法 ...

  2. 如何提取小程序/APP/网页里图片视频,小程序APP素材抓取软件批量下载图片音频?

    通常我们在看到某一个好的小程序素材想下载来参考时?会思考以下问题: "怎么下载别人小程序里的图标呀?" "怎么抓取小程序的图片.图标之类的?" "怎么 ...

  3. 【数据下载】使用DownThemAll批量下载网站上的文件

    1 下载DownThemAll扩展程序 网址:DownThemAll! 2 批量下载网站上的文件 2.1 全球人工不透水面积GAIA数据 以全球人工不透水面积GAIA数据为例,网页界面如下: 右键后, ...

  4. python爬取汽车之家_python爬虫实战之爬取汽车之家网站上的图片

    随着生活水平的提高和快节奏生活的发展.汽车开始慢慢成为人们的必需品,浏览各种汽车网站便成为购买合适.喜欢车辆的前提.例如汽车之家网站中就有最新的报价和图片以及汽车的相关内容,是提供信息最快最全的中国汽 ...

  5. 利用站点抓取功能批量下载壁纸

    IDM是一款简单.易上手的下载器,,使用IDM下载器可以进行文档.图片.网页等等类型文件的下载,十分方便快捷,可以极大地便利我们的生活与工作.电脑壁纸可以美化桌面,优化我们的使用体验.那么,当你有多张 ...

  6. Scrapy爬虫:抓取大量斗图网站最新表情图片

    一:目标 第一次使用Scrapy框架遇到很多坑,坚持去搜索,修改代码就可以解决问题.这次爬取的是一个斗图网站的最新表情图片www.doutula.com/photo/list,练习使用Scrapy框架 ...

  7. Qt学习笔记-http服务的初步认识(使用程序下载网站上的图片)

    关键是:QNetworkAccessManager类用来协调网络操作,可以调度创建好的请求,并发射信号来报告进度. 运行截图如下: 代码如下: widget.h #ifndef WIDGET_H #d ...

  8. 使用IDM批量抓取音效素材下载

    IDM下载器站点抓取功能,能够抓取网站上的图片.音频.视频.PDF.压缩包等等文件.更重要的是,能够实现批量抓取操作,省时省力.今天就来看一下,如何用IDM巧妙的批量抓取音效素材. 1.进入音效合辑界 ...

  9. 根据专利号到专利查询的网站上抓取想要的信息(上)

    前述:前几天看到有人论要请别人写一个从从网页上抓取某个专利号的收费信息的一个程序,说实话我自己知道那里面的原理是什么,但一直没有自己动手实现以下.根据自己的实际的工作需要一般是有一张Excel表,第一 ...

最新文章

  1. 我们能从大学里学到什么
  2. java中InputStream和OutputStream的使用场景
  3. 双线性内插怎么缩小_汗蒸桶怎么选择才是最好的
  4. 带冲突检测的载波监听多路访问的原理_通信原理课程总结(二)
  5. 题目 2055: 等待戈多(最短路)
  6. HTML+CSS+JS实现 ❤️高光立体游戏卡片悬停ui特效❤️
  7. 玩转Python? 一文总结30种Python的窍门和技巧,不可错过哈!
  8. Abp vnext Web应用程序开发教程 1 —— 创建服务器端
  9. boost学习之BOOST_PP_SEQ_FOR_EACH
  10. java.io.IOException: output.properties data exceeds its limit [2048] hue的调度
  11. 可视化设计的时候应该注意什么
  12. python实现QQ登陆验证码数据采集
  13. 【雨林木风】装机人员常用软件工具盘Y6.5
  14. oracle job定时报错,Oracle定时任务Job笔记
  15. 计算机网络哈勃,「实时热点」美国哈勃已脱机一星期:NASA已尝试修复3次,均以失败告终...
  16. modelsim和vivado仿真不一致——噩梦debug
  17. (2016/02/19)多传感器数据融合算法---9轴惯性传感器
  18. HNU君陌:写点其他的
  19. Android之MediaPlayer(两种)基本使用方式
  20. R在市场调查中的应用--主成分分析

热门文章

  1. 常用英雄胜率怎么刷_王者荣耀英雄胜率怎么刷 王者荣耀如何提高自己的胜率呢...
  2. C++ Enum转字符串
  3. Java-Mail监听新邮件
  4. 亚马逊店群模式怎么解决解决后台绑卡付店铺月租?
  5. Element Tree 树形控件自定义显示样式与hover事件绑定实现添加、删除和修改
  6. 如何利用笔记本自带读卡器放入存储卡+ReadyBoost加快笔记本电脑的速度
  7. C++基础知识的总结(主要针对面试)
  8. 欧鹏浏览器html5用不了,HTML5新时代 欧朋浏览器H5体验版试用
  9. (个人翻译)Scrivener交互式手册中文版FowWindows 01从这里开始
  10. java面试之常见场景题