爬虫的全国气温排行程序/c++"/>
基于网络爬虫的全国气温排行程序/c++
最近天气很热,想想这么高的温度在全国应该排的上号的吧,在全国气温排行的话能排多少呢? 打开手机天气app 没找到排行功能。。。。 打开网页搜索一下相关网站,是我打开方式不对? 点了几个做天气相关的网站,有几个有高温前十排行,大西安竟然没上前十榜单。这把人热成狗的温度没进前十 肯定也是第十一,但找了好几个网站都没找到全国温度排行 这类的功能。
好吧,自己弄一个。
最粗暴的想法,找一个气象网站,给它发http get请求,把收到的数据包处理,抓出其中的各个城市对应的页面资源名称
such as -》 /weather/BeiJing.html /weather/ShangHai.html
然后把全国的的这些城市都抓出来,再循环对每一个城市对应的页面 想服务器发送http请求
such as-》 Get /BeiJing.html HTTP/1.1 Host:www.tianqi
然后对每一个页面返回的数据进行处理 筛选出 城市名称 和最高温度,存起来 然后排一下。OK
之前只听说过网络爬虫这么个概念,这次从网上找了个c++ 的简单例子,然后自己弄了个抓天气数据的,说是爬虫有点牵强吧,就爬了两层就不爬了。。。。
#include <string>
#include <iostream>
#include <vector>
#include <time.h>
#include <queue>
#include<netdb.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>using namespace std; #define MALLOC_SIZE (1024*1024)
#define DEFAULT_PAGE_BUF_SIZE (1024*1024)
class data
{
public:data(char* city_name,char* city_degree):name(city_name),degree(city_degree){}string name;string degree;
};bool wea_cmp(data n1,data n2)
{return (atoi( n1.degree.c_str()) > atoi(n2.degree.c_str()));
}//发送get请求 获得数据
bool GetHttpResponse(string &resource, char * &response, int &bytesRead )
{ // string resource = "/quanguo";string host = "tianqi.114la";//建立socket struct hostent *hp;hp= gethostbyname(host.c_str() ); if( hp==NULL ){ cout<< "Can not find host address"<<endl; return false; } int sock = socket(PF_INET,SOCK_STREAM,0);if(sock < 0){printf("creat socket error\n");}struct sockaddr_in address;bzero(&address,sizeof(address));address.sin_family = AF_INET;memcpy(&(address.sin_addr.s_addr),hp->h_addr_list[0],hp->h_length);address.sin_port = htons(80);int ret = connect(sock,(struct sockaddr*)&address,sizeof(address));if(ret < 0){printf("client connect error\n");close(sock);return false;}//构造 http请求 string request = "GET " + resource + " HTTP/1.1\r\nHost:" + host + "\r\nConnection:Close\r\n\r\n"; if(-1 ==send( sock, request.c_str(), request.size(), 0 ) ){ cout << "send error" <<endl; close( sock ); return false; } int m_nContentLength = DEFAULT_PAGE_BUF_SIZE; char *pageBuf = (char *)malloc(m_nContentLength); memset(pageBuf, 0, m_nContentLength); bytesRead = 0; ret = 1; 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); } } pageBuf[bytesRead] = '\0'; response = pageBuf; close( sock ); return true; //cout<< response <<endl;
} //获得某一个城市的名字和气温
void Get_weather_info(char *resp,vector<data> &v_weather_data)
{char *tag1 = "<title>";char *tag2 = "firstWeather";char *tag3 = "red\">";char *pos = strstr(resp,tag1);if(pos == NULL){cout<<"get city name failed"<<endl;return;}pos += strlen(tag1);char city_name[100];char city_degree[20];sscanf(pos,"%[^,]",city_name);city_name[strlen(city_name)-12] = '\0';cout<<"city_name "<<city_name<<endl;pos = strstr(pos,tag2);pos = strstr(pos,tag3);pos += strlen(tag3);sscanf(pos,"%[^<]",city_degree);cout<<"city_degree "<<city_degree<<endl;data city_data(city_name,city_degree);v_weather_data.push_back(city_data);
}//找到主页中 全国各个城市所对应的页面资源
void find_resource(char * resp,vector<string> &vec)
{char *tag1 = "wordStart";char *tag2 = "href=\"";char *tag3 = "/YunNan/ZhaoTong";char *pos = strstr(resp,tag1);if(pos == NULL){cout<<"cant find wordstart"<<endl;}char res[100];int j = 0;while(pos){if(strncmp(pos,tag3,15) == 0)// if(j > 100)break;pos = strstr(pos,tag2);pos += strlen(tag2);int readnum = sscanf(pos,"%[^\"]",res);//res[readnum] = '\0';vec.push_back(res);j++;}}int main()
{ char* resp = (char*)malloc(MALLOC_SIZE);int byteread;vector<string> vec;vector<data> v_weather_data;string res_quanguo = "/quanguo";GetHttpResponse(res_quanguo,resp,byteread);cout<<"byteread"<<byteread<<endl;//获取各个城市的页面名称find_resource(resp,vec);vector<string>::iterator iter = vec.begin();int k = 1;vec[126] = "/GuangDong/JiangMen.html";for(; iter!=vec.end(); iter++){cout<<k++<<" "<<*iter<<endl;}//获取各个城市页面的信息,然后找到名字和温度 插入vec// 多次建立拆除链接,效率低下for(k=0;k<vec.size();++k){memset(resp,'\0',MALLOC_SIZE);GetHttpResponse(vec[k],resp,byteread);Get_weather_info(resp,v_weather_data);}//将vec按温度排序sort(v_weather_data.begin(),v_weather_data.end(),wea_cmp);vector<data>::iterator iter1 = v_weather_data.begin();int No = 1;for(; iter1 != v_weather_data.end(); iter1++ ){cout<<"No."<<No<<(*iter1).name<<" "<<(*iter1).degree<<endl;No++;}free(resp);return 0;
}
搞完跑一下 能拿到排行,但有个很大的问题,要跑上五分钟才能出结果... 300多个城市,每一个都建立连接,获取数据,拆除连接,好low 然后查了下 浏览器请求一个有很多资源的页面时,大都用长连接,keep-alive
这样 一个连接传输 多个资源,可以考虑这种方法试一下,但一次请求300个应该也费劲,(不太清楚请求报文的最大长度限制)有些web服务器 只读取请求报文的前100字节。但一次只请求一个有些浪费了,使用长连接应该程序效率能高许多。
今天排了一下,大西安果然不负我望
更多推荐
基于网络爬虫的全国气温排行程序/c++
发布评论