C++实现图片爬虫

C++实现图片爬虫

代码是从B站学的,所以并不是很原创

实现思路

  1. 输入需要爬取的网址加入网址队列;
  2. 使用BFS:
    1. 获取网址队列队首中的网址,并从队列中弹出,解析出网址中的主机名以及文件(html、jpg等文件)存放的目录;
    2. 通过解析出的解析出的信息使用Socket套接字建立连接,发送GET请求;
    3. 获取GET得到的HTML文件内容,并使用正则表达式获得其中关于JPG(或者其他格式的图片)的链接和跳转链接分别存于两个vector数组;
    4. 遍历存放图片链接的vector数组,建立连接,使用GET方法获取JPG图片,存放至文件夹,遍历结束后清空数组(因为当前html页面中的图片都获取了);
    5. 遍历存放跳转链接的vector数组,如果没有获取过该网址的图片(使用map对爬过的网址进行标记)则加入到网址队列。

实现代码

广度优先遍历该网站 BFS

  BFS需要获得起始网址的链接。

void bfs(string beginUrl)
{
   
    queue<string>q;
    q.push(beginUrl);
    while (!q.empty())
    {
   
        string cur = q.front();
        mp[cur]++;
        q.pop();
        char tmp[800];
        strcpy(tmp, cur.c_str());
        analyUrl(tmp);  //得到主机名和子链接
        preConnect();   //连接服务器GET发送请求图片数据
        HandleHTML(); //获取并解析HTML文件中的图片和跳转链接
        for(int i=0;i<photoUrl.size();i++)
            OutImage(photoUrl[i]);  //获取每个图片
        photoUrl.clear();
        for(int i=0;i<comUrl.size();i++)
            if (mp[comUrl[i]] == 0) //将跳转链接加入到队列
                q.push(comUrl[i]);
        comUrl.clear();
    }
}

处理HTML文本 HandleHTML

  调用recv函数接收HTML文本,并调用函数进行解析

void HandleHTML()
{
   
    
    int n;
    char buf[1024];
    //if (recv(sock, buf, sizeof(buf) - 1, 0) == SOCKET_ERROR) cout << "error";
    while ((n = recv(sock, buf, sizeof(buf) - 1, 0)) > 0)
    {
   
        buf[n] = '\0';
        allHtml += string(buf);
    }
    regexGetimage(allHtml);
    regexGetcom(allHtml);
}

解析网址 analyUrl

  analyUrl需要参数url即存放待解析的网址数组的地址
  使用strstr判断其中是否有"http:// "的信息,如果没有则结束,如果有则从http:// 的下一个位置开始(所以pos要+7)使用sscanf读取到’/'之前的内容即host,以及之后的内容即文件存放的位置othPath。

bool analyUrl(char* url)
{
   
    char* pos = strstr(url, "http://");
    if (pos == NULL) return NULL;
    else
    {
   
        pos += 7;
    }
    sscanf(pos, "%[^/]%s", host, othPath);
    cout << "host: " << host << " repath: " << othPath << endl;
    return true;
}

读取HTML中的图片链接 regexGetimage

  其中allHTML为获得的HTML文本内容,参考正则表达式的使用,图片链接是 src=“链接” 的形式,所以正则表达式为"src="“开头(’'反斜杠是转义符),其中的链接应以.jpg结尾,”.?“中.为匹配除”\n"之外的任何单个字符,*是多个字符,最后?是最短匹配即可,那么从allHTML头开始至结尾使用pattern模式进行匹配,mat[0]为匹配上的串,mat[1]为"(.?.jpg)"中匹配上的串,跳转到mat[0]的下一个位置继续匹配。
   正则表达式的使用在文后附上参考博客链接

void regexGetimage(string& allHtml)
{
   
    smatch mat;
    regex pattern("src=\"(.*?\.jpg)\"");
    string::const_iterator start = allHtml.begin();
    string::const_iterator end = allHtml.end();
    while (regex_search(start, end, mat, pattern))
    {
   
        string msg(mat[1].first, mat[1].second);
        //photoUrl.push_back(msg);
        photoUrl.push_back("http:"+msg);    //有的网站html文件中图片不在本网站,链接前又没有HTTP://
        start = mat[0].second;
    
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值