人工智能机器人爬取照片的实现

    俗话说“工欲善其事,必先利其器”,自己做的这款小项目的实现,搭载的平台 VS2013 ,要想做出一款只需要用户输入一个url,俗称网址,就能从互联网上得到该网址所需要的照片,并且保存到用户指定的文件夹中。所需要的步骤如下:

1.用户输入网址. 我们并不是分析这一个网址,而是通过这个网址得到相关网址的照片,所以我们需要声明一个队列,来存储解析该网页得到的html页面的所有url.

2.分析url.         从队列中出队,逐个分析网址,得到网址的协议类型,主机名,和资源名

3.初始化网络。 我们要用到SOCKET通信,加载2.2版本的套接字,创建套接字,绑定,连接

4.得到html页面。模拟发送Get请求,连接网络,得到该页面的html页面。

5.筛选url.           先用正则表达式匹配,出以http://开头,并且没有单双引号的网址,我们压入队列

6.下载照片。     我们从筛选好的网址中匹配,find_last_of查找以.png .gif .gpeg,jpg等结尾的我们将其写到文件中,保存下来。

对应的关键代码如下:


//
#include "Spider.h"
#include<WinSock2.h>
//开始抓取函数
void startCatch(string url)
{
    queue<string> q;
    q.push(url);                     //将url压入队列
    while (!q.empty()){              //判断队列是不是为空
        string currentUrl = q.front();
        q.pop();                     //出队
        //cout<< currentUrl << endl;
        CHttp http;
        string html=http.GetHtml(currentUrl);

        //开始匹配网页
        smatch mat;
        regex reg("http://[^\\s'\"]+");  //网址以http开头,没有空格没有单双引号
        string::const_iterator start = html.begin();
        string::const_iterator end = html.end();

        while (regex_search(start, end, mat, reg))
        {
            string per(mat[0].first, mat[0].second);
            cout << per << endl;

            //下载照片
            if (per.find(".jpg") == string::npos&&per.find(".jpeg") == string::npos&&per.find(".gif") == string::npos&&per.find(".png") == string::npos)
            {
                q.push(per);
            }
            else
            {
                //下载图片
                string filename = "./res/" + per.substr(per.find_last_of('/') + 1);
                http.DownLoadImage(per,filename);
            }
            start = mat[0].second;
        }

    }
}
//构造函数
CHttp::CHttp()
{
    m_socket = NULL;
}
//析构函数
CHttp::~CHttp()
{

}
//分析url得到主机号和路径名
bool CHttp::analyseUrl(string url)
{
    //先判断url是否有效
    if (url.length() <= 7)
        return false;
    //没有找到协议类型
    if (url.find("http://") == string::npos&&string::npos == url.find("https://"))
        return false;
    //网址中找到http://,开始匹配主机名和资源名
    if (url.find("http://") != string::npos){   //找到http://
        int pos = url.find('/', 7);     //从第七个字符开始匹配斜杠
        if (pos == string::npos){       //http://www.baidu.com
            m_host = url.substr(7);
            m_object = '/';
        }
        else{
            m_host = url.substr(7, pos-7);  //从第七个开始匹配pos-7个
            m_object = url.substr(pos);
        }

    }
    else{                              //找到https://
        int pos = url.find('/', 8);     //从第8个字符开始匹配斜杠
        if (pos == string::npos){       //https://www.baidu.com
            m_host = url.substr(8);
            m_object = '/';
        }
        else{
            m_host = url.substr(8, pos-8);
            m_object = url.substr(pos);
        }
    }
    //cout << m_host << endl;
    //cout << m_object << endl;     
    return true;
}

//初始化网络
bool CHttp::ConnectNetwork()
{
    //1.加载套接字
    WSADATA wd;
    if (0 != WSAStartup(MAKEWORD(2, 2), &wd)){
        cout << "加载套接字失败!错误码:" << GetLastError() << endl;
        return false;
    }
    //判断是不是2.2版本
    if (2 != HIBYTE(wd.wVersion) || 2 != LOBYTE(wd.wVersion)){
        cout << "加载套接字2.2版本失败!错误码:" << GetLastError() << endl;
        return false;
    }
    //创建套接字
    m_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (m_socket == INVALID_SOCKET){
        cout << "创建套接字失败!错误码:" << GetLastError() << endl;
        return false;
    }
    //连接服务器
    sockaddr_in sa = { AF_INET };    //网络编程结构
    if (SOCKET_ERROR ==bind(m_socket, (sockaddr*)&sa, sizeof(sockaddr))){
        cout << "绑定失败!错误码:" << GetLastError() << endl;
        return false;
    }
    hostent *p = gethostbyname(m_host.c_str()); //p里面存取的是ip地址
    sa.sin_port = htons(80);
    memcpy(&sa.sin_addr, p->h_addr, 4);

    if (SOCKET_ERROR == connect(m_socket, (sockaddr*)&sa, sizeof(sockaddr))){
        cout << "绑定失败!错误码:" << GetLastError() << endl;
        return false;
    }
    return true;
}
//得到html页面
string CHttp::GetHtml(string url)  
{
    if (false==analyseUrl(url) ){
        cout << "分析url失败!错误码:" << GetLastError() << endl;
        return false;
    }
    if (false == ConnectNetwork()){
        cout << "连接网络失败!错误码:" << GetLastError() << endl;
        return false;
    }
    string html;
    string reqInfo = "GET " + m_object + " HTTP/1.1\r\n"
        + "Host: " + m_host + "\r\n"
        //+ "User-Agent: Mozilla/5.0(Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0"
        + "Connection: Close\r\n\r\n";
    if (SOCKET_ERROR == send(m_socket, reqInfo.c_str(), reqInfo.length(), 0)){
        cout << "发送Get请求失败!错误码:" << GetLastError() << endl;
        return false;
    }

    //接收头信息
    char ch;
    int nRecv = 0;
    while ((nRecv=recv(m_socket, &ch, sizeof(ch), 0))>0)
    {
        if (ch == '\r')
        {
            nRecv = recv(m_socket, &ch, sizeof(ch), 0);
            if (nRecv > 0 && ch == '\n')
            {
                nRecv = recv(m_socket, &ch, sizeof(ch), 0);
                if (nRecv > 0 && ch == '\r')
                {
                    nRecv = recv(m_socket, &ch, sizeof(ch), 0);
                    if (nRecv > 0 && ch == '\n')
                    {
                        break;
                    }
                }
            }
        }
    }
    //接收数据
    char szBuffer[11];
    memset(szBuffer, 0, sizeof(szBuffer));
    while (recv(m_socket, szBuffer, 10, 0))
    {
        html += szBuffer;
    }
    return html;
}

//下载照片
bool CHttp::DownLoadImage(string url,string filename)
{
    if (false == analyseUrl(url)){
        cout << "分析url失败!错误码:" << GetLastError() << endl;
        return false;
    }
    if (false == ConnectNetwork()){
        cout << "连接网络失败!错误码:" << GetLastError() << endl;
        return false;
    }
    string html;
    string reqInfo = "GET " + m_object + " HTTP/1.1\r\n"
        + "Host: " + m_host + "\r\n"
        //+ "User-Agent: Mozilla/5.0(Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0"
        + "Connection: Close\r\n\r\n";
    if (SOCKET_ERROR == send(m_socket, reqInfo.c_str(), reqInfo.length(), 0)){
        cout << "发送Get请求失败!错误码:" << GetLastError() << endl;
        return false;
    }

    //接收头信息
    char ch;
    int nRecv = 0;
    while ((nRecv = recv(m_socket, &ch, sizeof(ch), 0))>0)
    {
        if (ch == '\r')
        {
            nRecv = recv(m_socket, &ch, sizeof(ch), 0);
            if (nRecv > 0 && ch == '\n')
            {
                nRecv = recv(m_socket, &ch, sizeof(ch), 0);
                if (nRecv > 0 && ch == '\r')
                {
                    nRecv = recv(m_socket, &ch, sizeof(ch), 0);
                    if (nRecv > 0 && ch == '\n')
                    {
                        break;
                    }
                }
            }
        }
    }
    //写文件
    FILE  *pFile = fopen(filename.c_str(), "wb");
    if (pFile == NULL)
        return false;
    //接收数据
    char szBuffer[11];
    memset(szBuffer, 0, sizeof(szBuffer));
    while ((nRecv=recv(m_socket, szBuffer, 10, 0)))
    {
        fwrite(szBuffer, 1, nRecv, pFile);
    }
    fclose(pFile);
    return true;
}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值