猫史档案馆


爵士OIer

爵士OIer

Lv.1

无情刀永不知错 无缘份之叹奈何

获赞:2147收藏:1255浏览:61922作品收藏:509

签名:卷文化课的同时准备竞赛。

回复帖子评论
上一页106 页 / 共 147下一页

【超大型投票讨论活动】编程猫社区今昔10个对比!欢迎投票~ 中回复

2020-05-09T18:33:19 点赞:0

【爬虫必备】编程猫社区的API 中回复

网络爬虫,但是基本都是用什么python或者JAVA写,貌似很少看到用c++写的,我在网上找了一个,看到其实还是很简单的算法

算法讲解:1.遍历资源网站

     2.获取html信息

       3.然后解析网址和图片url下载。

       4.递归调用搜索网址

BFS是最重要的处理:          先是获取网页响应,保存到文本里面,然后找到其中的图片链接H喵LParse,

       下载所有图片DownLoadImg。

//广度遍历  
void BFS( const string & url ){  
	char * response;  
	int bytes;  
	// 获取网页的相应,放入response中。  
	if( !GetHttpResponse( url, response, bytes ) ){  
		cout << "The url is wrong! ignore." << endl;  
		return;  
	}  
	string httpResponse=response;  
	free( response );  
	string filename = ToFileName( url );  
	ofstream ofile( "./html/"+filename );  
	if( ofile.is_open() ){  
		// 保存该网页的文本内容  
		ofile << httpResponse << endl;  
		ofile.close();  
	}  
	vector<string> imgurls;  
	//解析该网页的所有图片链接,放入imgurls里面  
	H喵LParse( httpResponse,  imgurls, url );  

	//下载所有的图片资源  
	DownLoadImg( imgurls, url );  
}  

 

2020-05-13T21:57:11 点赞:0

【爬虫必备】编程猫社区的API 中回复

 

然后附上代码:

#include "stdafx.h"
 
//#include <Windows.h> 
#include <string> 
#include <iostream> 
#include <fstream> 
#include <vector> 
#include "winsock2.h" 
#include <time.h> 
#include <queue> 
#include <hash_set> 
 
#pragma comment(lib, "ws2_32.lib")  
using namespace std; 
 
#define DEFAULT_PAGE_BUF_SIZE 1048576 
 
queue<string> hrefUrl; 
hash_set<string> visitedUrl; 
hash_set<string> visitedImg; 
int depth=0; 
int g_ImgCnt=1; 
 
//解析URL,解析出主机名,资源名 
bool ParseURL( const string & url, string & host, string & resource){ 
    if ( strlen(url.c_str()) > 2000 ) { 
        return false; 
    } 
 
    const char * pos = strstr( url.c_str()喵e pos += strlen("http://"); 
    if( strstr( pos, "/")==0 ) 
        return false; 
    char pHost[100]; 
    char pResource[2000]; 
    sscanf( pos, "%[^/]%s", pHost, pResource ); 
    host = pHost; 
    resource = pResource; 
    return true; 
} 
 
//使用Get请求,得到响应 
bool GetHttpResponse( const string & url, char * &response, int &bytesRead ){ 
    string host, resource; 
    if(!ParseURL( url, host, resource )){ 
        cout << "Can not parse the url"<<endl; 
        return false; 
    } 
 
    //建立socket 
    struct hostent * hp= gethostbyname( host.c_str() ); 
    if( hp==NULL ){ 
        cout<< "Can not find host address"<<endl; 
        return false; 
    } 
 
    SOCKET sock = socket( AF_INET, SOCK_STREAM, IPPROTO_T喵); 
    if( sock == -1 || sock == -2 ){ 
        cout << "Can not create sock."<<endl; 
        return false; 
    } 
 
    //建立服务器地址 
    SOCKADDR_IN sa; 
    sa.sin_family = AF_INET; 
    sa.sin_port = htons( 80 ); 
    //char addr[5]; 
    //memcpy( addr, hp->h_addr, 4 ); 
    //sa.sin_addr.s_addr = inet_addr(hp->h_addr); 
    memcpy( &sa.sin_addr, hp->h_addr, 4 ); 
 
    //建立连接 
    if( 0!= connect( sock, (SOCKADDR*)&sa, sizeof(sa) ) ){ 
        cout << "Can not connect: "<< url <<endl; 
        closesocket(sock); 
        return false; 
    }; 
 
    //准备发送数据 
    string request = "GET " + resource + " HTTP/1.1\r\nHost:" + host + "\r\nConnection:Close\r\n\r\n"; 
 
    //发送数据 
    if( SOCKET_ERROR ==send( sock, request.c_str(), request.size(), 0 ) ){ 
        cout << "send error" <<endl; 
        closesocket( sock ); 
        return false; 
    } 
 
    //接收数据 
    int m_nContentLength = DEFAULT_PAGE_BUF_SIZE; 
    char *pageBuf = (char *)malloc(m_nContentLength); 
    memset(pageBuf, 0, m_nContentLength); 
 
    bytesRead = 0; 
    int ret = 1; 
    cout <<"Read: "; 
    while(ret > 0){ 
        ret = recv(sock, pageBuf + bytesRead, m_nContentLength - bytesRead, 0); 
 
        if(ret > 0) 
        { 
            bytesRead += ret; 
        } 
 
        if( m_nContentLength - bytesRead<100){ 
            cout << "\nRealloc memorry"<<endl; 
            m_nContentLength *=2; 
            pageBuf = (char*)realloc( pageBuf, m_nContentLength);       //重新分配内存 
        } 
        cout << ret <<" "; 
    } 
    cout <<endl; 
 
    pageBuf[bytesRead] = '\0'; 
    response = pageBuf; 
    closesocket( sock ); 
    return true; 
    //cout<< response <<endl; 
} 
 
//提取所有的URL以及图片URL 
void H喵LParse ( string & htmlResponse, vector<string> & imgurls, const string & host ){ 
    //找所有连接,加入queue中 
    const char *p= htmlResponse.c_str(); 
    char *tag="href=\""; 
    const char *pos = strstr( p, tag ); 
    ofstream ofile("url.txt", ios::app); 
    while( pos ){ 
        pos +=strlen(tag); 
        const char * nextQ = strstr( pos, "\"" ); 
        if( nextQ ){ 
            char * url = new char[ nextQ-pos+1 ]; 
            //char url[100]; //固定大小的会发生缓冲区溢出的危险 
            sscanf( pos, "%[^\"]", url); 
            string surl = url;  // 转换成string类型,可以自动释放内存 
            if( visitedUrl.find( surl ) == visitedUrl.end() ){ 
                visitedUrl.insert( surl ); 
                ofile << surl<<endl; 
                hrefUrl.push( surl ); 
            } 
            pos = strstr(pos, tag ); 
            delete [] url;  // 释放掉申请的内存 
        } 
    } 
    ofile << endl << endl; 
    ofile.close(); 
 
    tag ="<img "; 
    const char* att1= "src=\""; 
    const char* att2="lazy-src=\""; 
    const char *pos0 = strstr( p, tag ); 
    while( pos0 ){ 
        pos0 += strlen( tag ); 
        const char* pos2 = strstr( pos0, att2 ); 
        if( !pos2 || pos2 > strstr( pos0, ">") ) { 
            pos = strstr( pos0, att1); 
            if(!pos) { 
                pos0 = strstr(att1, tag ); 
                continue; 
            } else { 
                pos = pos + strlen(att1); 
            } 
        } 
        else { 
            pos = pos2 + strlen(att2); 
        } 
 
        const char * nextQ = strstr( pos, "\""); 
        if( nextQ ){ 
            char * url = new char[nextQ-pos+1]; 
            sscanf( pos, "%[^\"]", url); 
            cout << url<<endl; 
            string imgUrl = url; 
            if( visitedImg.find( imgUrl ) == visitedImg.end() ){ 
                visitedImg.insert( imgUrl ); 
                imgurls.push_back( imgUrl ); 
            } 
            pos0 = strstr(pos0, tag ); 
            delete [] url; 
        } 
    } 
    cout << "end of Parse this html"<<endl; 
} 
 
//把URL转化为文件名 
string ToFileName( const string &url ){ 
    string fileName; 
    fileName.resize( url.size()); 
    int k=0; 
    for( int i=0; i<(int)url.size(); i++){ 
        char ch = url[i]; 
        if( ch!='\\'&&ch!='/'&&ch!=':'&&ch!='*'&&ch!='?'&&ch!='"'&&ch!='<'&&ch!='>'&&ch!='|') 
            fileName[k++]=ch; 
    } 
    return fileName.substr(0,k) + ".txt"; 
} 
 
//下载图片到img文件夹 
void DownLoadImg( vector<string> & imgurls, const string &url ){ 
 
    //生成保存该url下图片的文件夹 
    string foldname = ToFileName( url ); 
    foldname = "./img/"+foldname; 
    if(!CreateDirectory( foldname.c_str(),NULL )) 
        cout << "Can not create directory:"<< foldname<<endl; 
    char *image; 
    int byteRead; 
    for( int i=0; i<imgurls.size(); i++){ 
        //判断是否为图片,bmp,jgp,jpeg,gif  
        string str = imgurls[i]; 
        int pos = str.find_last_of("."); 
        if( pos == string::npos ) 
            continue; 
        else{ 
            string ext = str.substr( pos+1, str.size()-pos-1 ); 
            if( ext!="bmp"&& ext!="jpg" && ext!="jpeg"&& ext!="gif"&&ext!="png") 
                continue; 
        } 
        //下载其中的内容 
        if( GetHttpResponse(imgurls[i], image, byteRead)){ 
            if ( strlen(image) ==0 ) { 
                continue; 
            } 
            const char *p=image; 
            const char * pos = strstr(p,"\r\n\r\n")+strlen("\r\n\r\n"); 
            int index = imgurls[i].find_last_of("/"); 
            if( index!=string::npos ){ 
                string imgname = imgurls[i].substr( index , imgurls[i].size() ); 
                ofstream ofile( foldname+imgname, ios::binary ); 
                if( !ofile.is_open() ) 
                    continue; 
                cout <<g_ImgCnt++<< foldname+imgname<<endl; 
                ofile.write( pos, byteRead- (pos-p) ); 
                ofile.close(); 
            } 
            free(image); 
        } 
    } 
} 
 
 

2020-05-13T21:58:09 点赞:0

【爬虫必备】编程猫社区的API 中回复

接上:


 
//广度遍历 
void BFS( const string & url ){ 
    char * response; 
    int bytes; 
    // 获取网页的相应,放入response中。 
    if( !GetHttpResponse( url, response, bytes ) ){ 
        cout << "The url is wrong! ignore." << endl; 
        return; 
    } 
    string httpResponse=response; 
    free( response ); 
    string filename = ToFileName( url ); 
    ofstream ofile( "./html/"+filename ); 
    if( ofile.is_open() ){ 
        // 保存该网页的文本内容 
        ofile << httpResponse << endl; 
        ofile.close(); 
    } 
    vector<string> imgurls; 
    //解析该网页的所有图片链接,放入imgurls里面 
    H喵LParse( httpResponse,  imgurls, url ); 
 
    //下载所有的图片资源 
    DownLoadImg( imgurls, url ); 
} 
 
void main() 
{ 
    //初始化socket,用于tcp网络连接 
    WSADATA wsaData; 
    if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0 ){ 
        return; 
    } 
 
    // 创建文件夹,保存图片和网页文本文件 
    CreateDirectory( "./img",0); 
    CreateDirectory("./html",0); 
    //string urlStart = "http://hao.360.cn/meinvdaohang.html"; 
 
    // 遍历的起始地址 
     string urlStart = "http://desk.zol.com.cn/bizhi/7018_87137_2.html"; 
    //string urlStart = "http://item.taobao.com/item.htm?spm=a230r.1.14.19.sBBNbz&id=36366887850&ns=1#detail"; 
 
    // 使用广度遍历 
    // 提取网页中的超链接放入hrefUrl中,提取图片链接,下载图片。 
    BFS( urlStart ); 
 
    // 访问过的网址保存起来 
    visitedUrl.insert( urlStart ); 
 
    while( hrefUrl.size()!=0 ){ 
        string url = hrefUrl.front();  // 从队列的最开始取出一个网址 
        cout << url << endl; 
        BFS( url );                   // 遍历提取出来的那个网页,找它里面的超链接网页放入hrefUrl,下载它里面的文本,图片 
        hrefUrl.pop();                 // 遍历完之后,删除这个网址 
    } 
    WSACleanup(); 
    return; 
} 

2020-05-13T22:00:11 点赞:0

【爬虫必备】编程猫社区的API 中回复

BFS(Baidu First Search)万岁

2020-05-13T22:01:02 点赞:0

如何用F12改金币 中回复

审查元素(有的地方叫检查)只需单击右键

2020-05-13T22:06:48 点赞:0

我是个ZZ【为什么!】 中回复

tql,博士I!()

2020-05-13T22:07:32 点赞:0

【社区星推荐】第12期·咚当家族 中回复

这是厉害

2020-05-13T22:11:13 点赞:0

【C++教程 / 图论基础讲解】C++图论从入门到精通:图的连通 中回复

2020-05-16T08:49:25 点赞:0

暂退书o(╥﹏╥)o 中回复

首充电气!

2020-05-16T09:03:42 点赞:0

【学术讨论而已】传说中的硬科幻 中回复

热一、量子力学说的两个观点是能量守恒,信息量守恒

2020-05-18T22:19:22 点赞:1

众所周知,4,6,9是质数 中回复

tql,我去围观

这样的题只能打表,写不出代码的()

2020-05-20T21:50:06 点赞:0

众所周知,4,6,9是质数 中回复

有数据范围和时间限制吗,没有的话跑双层循环再加上循环优化喵过

2020-05-20T21:58:09 点赞:0

再见了,社区👋🏻 中回复

发照片的谥坹()

2020-05-20T22:01:13 点赞:0

再见了,社区👋🏻 中回复

刷题它不香吗,不刷题你哪能得奖啊emotion_笑cry

2020-05-20T22:02:49 点赞:0

卧 槽 卧 槽 卧 槽 你们爆照不怕喵隐私吗 中回复

IP地址不是网站的地址吗

和发帖卫视有什么关系emotion_doge

2020-05-20T22:06:14 点赞:1

【社区星推荐】第13期·小鹿工作室deer 中回复

我想我上不了的emotion_doge

2020-05-20T22:12:59 点赞:0

【官方真的很不容易】希望大家可以尊重一点官方 中回复

喵()

2020-05-20T22:18:00 点赞:0

[无内鬼,来点数学题] 中回复

面对疾风吧(emotion_喵喵emotion_doge

小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至
下堆放成一列。她用1到n的正整数给每本书都编了号。
小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。
由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位
置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放
在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去
时这本书上面就只可能有X-1、X或X+1本书。
当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时
候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离
开。
久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书
就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的
一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从
上到下第i本书的编号是多少。

2020-05-21T22:16:22 点赞:0

卧 槽 卧 槽 卧 槽 你们爆照不怕喵隐私吗 中回复

center_image

自己理解,不解释

三次都是这么考过来的

不会有错

2020-05-21T22:21:31 点赞:0

【从零开始学C++】C++爵士教程/第一课:C++入门1 中回复

dd

2020-05-22T17:15:33 点赞:0

【C++教程 / 图论基础讲解】C++图论从入门到精通:图的连通 中回复

dd

2020-05-22T17:16:01 点赞:0

【民科见闻】经典语录 中回复

dd

2020-05-22T17:17:29 点赞:0

有趣的数学 中回复

2

它是素数

2020-05-22T17:20:37 点赞:0

【带数学家】【1=0的又一种证明!!!】 中回复

有A+1<A,反例为任意数,得出所有数都相等,数学大厦崩塌emotion_dogeemotion_喵喵

2020-05-22T17:22:57 点赞:0

【带数学家】【1=0的又一种证明!!!】 中回复

民科的带数学家增加了:

【无穷大等于0!】https://shequ.codemao.cn/community/299728

2020-05-22T17:33:30 点赞:0

[无内鬼,来点数学题] 中回复

无穷大等于零!https://shequ.codemao.cn/community/299728完美证明

2020-05-22T17:36:29 点赞:0

【抗议】编程猫不是战场! 中回复

第一次见违反《中华人名共和国未成年人保护法》的“社会保护”的工作室,限制玩游戏什么鬼

2020-05-22T17:40:06 点赞:0

【发现】来看看爵士在源码世界的新发现 中回复

侵删

emotion_doge

2020-05-22T17:57:35 点赞:0

【带数学家番外】阿喀琉斯与乌龟的赛跑 中回复

E:作者没有验证此无穷等比级数是否发散

2020-05-22T18:02:43 点赞:0