1)acl_master是一个跨平台c/c++库,提供了网络通信库及服务器编程框架,同时提供更多的实用功能库及示例。
下载地址:Github: https://github.com/acl-dev/acl
2)聚合天气预报API接口注册
聚合数据的天气预报API接口其官网有提供,本人采用的是阿里云市场->API市场->生活服务栏下提供的,
*注册阿里云,有需要的阿里云产品通用代金券的可以点击下面链接进行领取:
https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=pfb80n4a
阿里云提供聚合数据的天气预报API的类似描述
该天气预报接口有多种套餐价格,是预购买使用,我们在聚合数据天气预报API接口需要用到APPCode,其API使用方式可以点击“全国天气预报”按键进入查看,页面涉及购买与使用介绍
3)acl http实现聚合数据天气预报信息的抓取
先定义了http抓取的一些参数
struct HttpApiArgWeather
{
HttpApiArgWeather()
: startTime(8)
, endTime(8)
, addr_("weather-ali.juheapi.com")
, path_("/weather/index")
, port_(80)
, dtype_("json")
, format_(1)
, city_("上海")
, authorization("APPCODE *******************************************")
, upTime(60)
{
};
int startTime; //开始抓取信息时间(单位小时),可忽略项目需要
int endTime; //结束抓取信息时间(单位小时),可忽略项目需要
std::string addr_; // web 服务器地址
std::string path_; // 本地请求的数据文件
int port_; //
std::string dtype_; //返回数据格式:json或xml,默认json
int format_; //未来6天预报(future)两种返回格式,1或2,默认1
std::string city_; //
std::string authorization; // 访问授权
int upTime; //天气预报更新间隔,单位秒
};
/*
目前聚合数据的天气预报访问参数
addr_:weather-ali.juheapi.com
path_:/weather/index
city_:""
dtype_:json或xml
format_:1或2
authorization:其格式“APPCODE ***”,***=注册的AppCode
*/
以下是采用acl http库抓取聚合数据天气预报信息的关键代码(本例采用Json格式):
#include "acl_cpp/lib_acl.hpp"
//HttpApiArgWeather myArgHttp
void HttpApiAclWeather::getHttpInfo()
{
bool accept_gzip = false, send_body = false;
//acl::log::stdout_open(true);
acl::string aclurl, acladdr/*,aclContentType*/;
aclurl.format("http://%s%s", myArgHttp.addr_.c_str(), myArgHttp.path_.c_str());
acladdr.format("%s:%d", myArgHttp.addr_.c_str(), myArgHttp.port_);
//aclContentType.format("application/json; charset=%s", myArgHttp.charset_.c_str());
acl::http_request req(acladdr);
acl::http_header& header = req.request_header();
//
//header.set_method(acl::HTTP_METHOD_POST);
header.set_method(acl::HTTP_METHOD_GET);
//
//header.set_keep_alive(true);
header.set_keep_alive(false);
header.accept_gzip(accept_gzip ? true : false);
//url
header.set_url(aclurl);
//host
if (header.get_host() == NULL)
{
header.set_host(myArgHttp.addr_.c_str());
printf(">>>set host: %s\r\n", myArgHttp.addr_.c_str());
}
else
printf(">>>host: %s\r\n", header.get_host());
//content_type
//header.set_content_type(aclContentType);
//header.set_content_length(1024);
//param
header.add_param("dtype", myArgHttp.dtype_.c_str());
header.add_int("format", myArgHttp.format_);
header.add_param("cityname", ASCII2UTF_8(myArgHttp.city_).c_str());
//entry
header.add_entry("Authorization", myArgHttp.authorization.c_str());
//cookie
//header.add_cookie("x-cookie-name", "cookie-value");
bool rc = req.request(NULL, 0);
// 只所以将 build_request 放在 req.request 后面,是因为
// req.request 内部可能会修改请求头中的字段
acl::string hdr;
header.build_request(hdr);
CLogger::createInstance()->Log(eTipMessage, "request header:\r\n%s\r\n", hdr.c_str());
if (rc == false)
{
CLogger::createInstance()->Log(eTipMessage, "send request error");
//break;
return;
}
printf("send request ok!\r\n");
// 取出 HTTP 响应头的 Content-Type 字段
const char* p = req.header_value("Content-Type");
if (p == NULL || *p == 0)
{
CLogger::createInstance()->Log(eTipMessage, "no Content-Type");
return;
}
// 分析 HTTP 响应头的数据类型
acl::http_ctype content_type;
content_type.parse(p);
//p = NULL;
// 响应头数据类型的子类型
const char* stype = content_type.get_stype();
bool ret;
if (stype == NULL)
ret = do_plain(req);
//#ifdef WIN32
//else if (stricmp(stype, "xml") == 0)
//#else
//else if (strcasecmp(stype, "xml") == 0)
//#endif
// ret = do_xml(req);
#ifdef WIN32
else if (stricmp(stype, "json") == 0)//linux->strcasecmp
#else
else if (strcasecmp(stype, "json") == 0)//linux->strcasecmp
#endif
ret = do_json(req);
else
ret = do_plain(req);
if (ret == true)
CLogger::createInstance()->Log(eTipMessage, "read ok!");
//stype = NULL;
};
// 处理 text/plain 类型数据
bool HttpApiAclWeather::do_plain(acl::http_request& req)
{
acl::string body;
if (req.get_body(body/*, to_charset_.c_str()*/) == false)
{
CLogger::createInstance()->Log(eTipMessage, "get http body error");
return false;
}
printf("body:\r\n(%s)\r\n", body.c_str());
return true;
}
// 处理 text/json 类型数据
bool HttpApiAclWeather::do_json(acl::http_request& req)
{
acl::json body;
if (req.get_body(body/*, to_charset_.c_str()*/) == false)
{
CLogger::createInstance()->Log(eTipMessage, "get http body error");
return false;
}
clearWeather();
WeatherData wd;
bool weatherIsRight = false;
acl::json_node* node = body.first_node();
while (node)
{
if (node->tag_name())
{
std::string tagStr = std::string(node->tag_name());
std::string valStr = std::string(node->get_text());
if ("city" == tagStr) {
weatherIsRight = true;
wd.city = UTF_82ASCII(valStr);
}
if ("date_y" == tagStr) {
wd.date = UTF_82ASCII(valStr);
}
if ("week" == tagStr) {
wd.week = UTF_82ASCII(valStr);
}
if ("temperature" == tagStr) {
wd.temperature = UTF_82ASCII(valStr);
}
if ("weather" == tagStr) {
wd.weather = UTF_82ASCII(valStr);
}
if ("wind" == tagStr) {
wd.wind = UTF_82ASCII(valStr);
}
if ("uv_index" == tagStr) {
wd.uv_index = UTF_82ASCII(valStr);
}
printf("tag: %s", node->tag_name());
if (!valStr.empty())
printf(", text: %s\r\n", UTF_82ASCII(valStr).c_str());
else
printf("\r\n");
if ("future" == tagStr) {
break;
}
}
node = body.next_node();
}
if (weatherIsRight) {
char buf[512] = { 0 };
sprintf(buf, "%s,%s,%s,%s,%s,%s,紫外强度:%s",wd.city.c_str(),wd.date.c_str(),wd.week.c_str()
,wd.temperature.c_str(),wd.weather.c_str(),wd.wind.c_str(),wd.uv_index.c_str());
add(std::string(buf));
}
return true;
}