最近工作中需求定时爬取不同城市每天的温度。其实就是通过编程的方法去抓取不同网站网页进行分析筛选的过程。.NET提供了很多类去访问并获得远程网页的数据,比如WebClient类和HttpWebRequest类。这些类对于利用HTTP去访问远端的网页并且下载下来是很有用的,但在对于所下载下来的HTML的解析能力方面,则显得功能很弱了。推荐一个开源的组件HTML Agility Pack(http://htmlagilitypack.codeplex.com/),它的设计目标是尽可能简化对HTML文档的读和写。这个包本身是利用了DOM文档对象模型去解析HTML的。在此顺便记录一下最近收集的爬取历史和当前天气的网站备用:
- 支持历史天气查询的中文网站:http://lishi.tianqi.com/
- 类似网站:http://tianqi.2345.com/wea_history/59287.htm (最近2-3年数据)
- 网站:http://www.wunderground.com/history/ (最近18年数据)
- 这个网站支持的时间更长: http://www.tutiempo.net/en/Climate/
- 中国天气网:http://www.weather.com.cn/,
中国天气网(Weather.com.cn)
- 该网提供有如下三个Json格式的查询接口,以北京为例:
- http://www.weather.com.cn/data/sk/101010100.html
- http://www.weather.com.cn/data/cityinfo/101010100.html
- http://m.weather.com.cn/data/101010100.html
- ID是一个9位的数字,按照长度可以分为如下四部分:101(国家代号) 01(省) 01(二级地区) 00(三级地区)
- 要获取所有的地区代号,通过如下方式:https://wqbot.blob.core.windows.net/botdemo/CityCode.xml
示例Demo
编程使用示例如下:我们要获取如下网页中的天气信息:
下载HTML Agility Pack组件,新建控制台程序,在你的工程中引用相应framework版本对应的组件,示例代码如下:
string url = @"http://lishi.tianqi.com/beijing/201701.html"; var webGet = new HtmlWeb(); var document = webGet.Load(url); var div = document.DocumentNode.SelectNodes("//div[@class='tqtongji2']/ul"); foreach (HtmlNode node in div) { var tmpNode = node.SelectNodes("li"); Console.WriteLine(string.Format("{0}-----------{1}---------{2}----------{3}", tmpNode[0].InnerText, tmpNode[1].InnerText, tmpNode[2].InnerText, tmpNode[3].InnerText)); } Console.ReadKey();
程序运行效果:中文存在乱码,如下图
通过分析HTML Agility Pack源码,在HtmlWeb类的Get(Uri uri, string method, string path, HtmlDocument doc)方法中,局部变量 resp是http请求的response。设置断点发现resp.ContentEncoding为空。因此通过HttpWebRequest来下载数据,示例代码如下:
string url = @"http://lishi.tianqi.com/beijing/201701.html"; HttpWebRequest req = WebRequest.Create(new Uri(url)) as HttpWebRequest; req.Method = "GET"; WebResponse rs = req.GetResponse(); Stream rss = rs.GetResponseStream(); HtmlDocument doc = new HtmlDocument(); doc.Load(rss); var div = doc.DocumentNode.SelectNodes("//div[@class='tqtongji2']/ul"); foreach (HtmlNode node in div) { var tmpNode = node.SelectNodes("li"); Console.WriteLine(string.Format("{0}-----------{1}---------{2}----------{3}", tmpNode[0].InnerText, tmpNode[1].InnerText, tmpNode[2].InnerText, tmpNode[3].InnerText)); } Console.ReadKey();
代码运行效果如下:
that's ok!!!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库