重要的不是代码,是方法。

首先自己肯定是没办法预报天气的,没有钱也没有人去做一堆数据采集分析之类的工作,所以实现这个功能正常都是调用别人给的接口来查询。

首先,先提供个最傻瓜式的,也是实在没有办法的办法,这也适用于其他能在网上查的到的信息。

方法一:下载整个网页

如果你想知道某个信息,但实在找不到别人提供的接口在哪,可是能够在某个网站查到,那可能就能用这个方法(只要那个信息是静态显示而不是动态加载的,否则还得做一堆分析别人代码的工作)。

首先,要知道的是,你看到的网页实际上是浏览器根据一堆文本(html和js和css)来显示出来的,浏览网站其实就是服务器给你发来了一堆文本,然后浏览器解释那些文本来显示给你看,在网页空白处    右键→查看源代码你就能看到原始文本。所以,要是你要找的信息就在这些文本里,那就可以直接把全部文本下载下来(所以这网页越小越好,否则要下载好久)然后提取出来那个信息。

好,现在我想预报上海的天气,并找到了个网页 http://shanghaicity.openservice.kankanews.com/public/default/Weather上面显示了气温天气等。右键→查看源代码。然后发现中间的这几句:

<div class="weather">晴转多云</div>
<div class="wind">东南风(3-4级)</div>
<div class="temp">21~31℃</div>
<div class="date" id='nl'>星期二</div>
<div class="source">上海中心气象台 2016-06-14 发布</div>

那好,那思路就清晰了,如果我要知道今天的天气,那我就把网页下载下来,然后就是处理字符串的工作了,比如要知道气温,那我就提取出网页中<div class="temp">到下一个</div>之间的字符串就行了。至于下载网页,只要用IdHttp的get方法就行了。

uses
  IdHTTP;
function TForm1.gethtml(url: string): string;
var
  HTTP: TIdHTTP;
begin
  HTTP := TIdHTTP.Create(self);
  Result := HTTP.get(url);
  HTTP.DisposeOf;
end;
// 使用
procedure TForm1.Button1Click(Sender: TObject);
var
  str:string;
begin
  str := gethtml('http://shanghaicity.openservice.kankanews.com/public/default/Weather');
end;
应该蛮详细的了,得到的字符串后期处理什么的是自己的事。

方法二:调用webservice

直接下载网页可以解决很多问题,但最大的问题就是同时下载了大量无用信息,不仅占流量,如果遇上网速很慢,那简直要命。所以条件允许的话都是直接调用webservice,这样可以基本只返回有用信息。

要调用网络服务首先要找接口,搜索一下“天气预报api”,有各式各样的api,收费的免费的,直接可以用的要注册账号的,每个的协议还不一样。具体用哪个还是自己看情况选择吧。这里只是举个例子。

比如我想用http://www.webxml.com.cn/webservices/weatherwebservice.asmx 的网络服务来查询天气,然后查看他的说明,可以用getWeatherbyCityName接口来查询城市天气,它支持HTTP Get和HTTP Post方法,接受一个参数:theCityName。

简单的讲,Get方法把参数用?param1Name=Value1&param2Name=Value1……的形式包含在链接(url)中传递给服务器,所以我要用Get方法获得它的服务的话本质上就是构造个符合它要求的url。比如我要查询北京的天气,那按要求我就得这样构造http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=北京

打开这个链接就可以发现返回结果是个XML文档,里头包含了北京的各种天气信息(顺便说下,打开网页用的就是HTTP Get方法,所以这和上面那个打开网页,本质上是一样的,只是定制了返回的文本)


<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://WebXml.com.cn/">
<style type="text/css"/>
<string>直辖市</string>
<string>北京</string>
<string>54511</string>
<string>54511.jpg</string>
<string>2016-6-14 13:01:03</string>
<string>20℃/32℃</string>
<string>6月14日 多云转阴</string>
<string>无持续风向微风</string>
<string>1.gif</string>
<string>2.gif</string>
<string>今日天气实况:气温:20℃;风向/风力:东风 3级;湿度:71%;紫外线强度:弱。空气质量:中。</string>
<string>
紫外线指数:弱,辐射较弱,涂擦SPF12-15、PA+护肤品。 感冒指数:少发,感冒机率较低,避免长期处于空调屋中。 穿衣指数:炎热,建议穿短衫、短裤等清凉夏季服装。 洗车指数:较适宜,无雨且风力较小,易保持清洁度。 运动指数:较适宜,户外运动请注意防晒。 空气污染指数:中,易感人群应适当减少室外活动。
</string>
<string>18℃/25℃</string>
<string>6月15日 雷阵雨</string>
<string>无持续风向微风</string>
<string>4.gif</string>
<string>4.gif</string>
<string>17℃/26℃</string>
<string>6月16日 雷阵雨转阵雨</string>
<string>无持续风向微风转北风3-4级</string>
<string>4.gif</string>
<string>3.gif</string>
<string>
北京位于华北平原西北边缘,市中心位于北纬39度,东经116度,四周被河北省围着,东南和天津市相接。全市面积一万六千多平方公里,辖12区6县,人口1100余万。北京为暖温带半湿润大陆性季风气候,夏季炎热多雨,冬季寒冷干燥,春、秋短促,年平均气温10-12摄氏度。北京是世界历史文化名城和古都之一。早在七十万年前,北京周口店地区就出现了原始人群部落“北京人”。而北京建城也已有两千多年的历史,最初见于记载的名字为“蓟”。公元前1045年北京成为蓟、燕等诸侯国的都城;公元前221年秦始皇统一中国以来,北京一直是中国北方重镇和地方中心;自公元938年以来,北京又先后成为辽陪都、金上都、元大都、明清国都。1949年10月1日正式定为中华人民共和国首都。北京具有丰富的旅游资源,对外开放的旅游景点达200多处,有世界上最大的皇宫紫禁城、祭天神庙天坛、皇家花园北海、皇家园林颐和园,还有八达岭、慕田峪、司马台长城以及世界上最大的四合院恭王府等各胜古迹。全市共有文物古迹7309项,其中国家文物保护单位42个,市级文物保护单位222个。北京的市树为国槐和侧柏,市花为月季和菊花。另外,北京出产的象牙雕刻、玉器雕刻、景泰蓝、地毯等传统手工艺品驰誉世界。
</string>
</ArrayOfString>

程序中获得它的方式和方法一一样,然后得到文本后直接暴力解析字符串,还是用比如TXMLDocument解析它就是你自己的事了。一般网页返回的不是XML就是JSON字符串,怎么解析它们自己搜索一下一大把教程,这里不讲这个。代码示例:

uses
  HttpApp,XMLDoc;
procedure TForm1.Button1Click(Sender: TObject);
var
  XMLDocument:TXMLDocument;
begin
  XMLDocument := TXMLDocument.Create(self);
  XMLDocument.LoadFromXML(gethtml('http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName='+HTTPEncode('北京')));
  ShowMessage('北京今日温度:' + XMLDocument.DocumentElement.ChildValues[5]);
  FreeAndNil(XMLDocument);
end;

要注意的是url中要把中文进行编码(比如用HTTPEncode),否则会出错。直接在浏览器中输入中文没有问题的原因大概是浏览器在内部帮忙编码了。

然后试试用Post方法,Post方法的好处就是别人没法直接通过看url就知道你给服务器了什么参数,比较安全,IdHttp也提供了Post方法,你需要把参数存在TStrings中传递给它。所以代码是这样的:

procedure TForm1.Button1Click(Sender: TObject);
var
  XMLDocument:TXMLDocument;
  HTTP: TIdHTTP;
  Params:TStringList;
begin
  XMLDocument := TXMLDocument.Create(self);
  HTTP := TIdHTTP.Create(self);
  Params:=TStringList.Create;
  Params.Add('theCityName=北京');
  XMLDocument.LoadFromXML(HTTP.Post('http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName',Params));
  ShowMessage('北京今日温度:' + XMLDocument.DocumentElement.ChildValues[5]);
  FreeAndNil(Params);
  FreeAndNil(XMLDocument);
  FreeAndNil(HTTP);
end;

delphi 实现天气预报基本就介绍到这啦,当然你在调用其他网站提供的接口的时候不见得和这个示例完全一样,可能还会遇到各种各样的问题,比如字符串编码的问题等。那些等我遇到并解决后,或者有空时再继续完善吧。

以上代码在delphiXE10 fmx下测试通过。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐