APOD - 获取每日天文图片






4.20/5 (3投票s)
检索每日天文图片
引言
NASA 每天分享的太空相关图片总是让我惊叹不已 (参见 http://antwrp.gsfc.nasa.gov/apod/astropix.html)。我经常访问该网站,而且经常(如果不是总是)将图片下载到我的电脑上以便离线查看(我们还没有一个随时在线的世界——至少不是一个经济实惠的世界)。此外,我经常想要下载多张图片(一个月的所有图片),而手动点击下载非常繁琐。
因此,我开发了自己的自动化软件!
此处分享的软件和教程包括:
- 向 APOD 网站发起 HTTP 请求(针对选定的日期)
- 检索和处理 HTML 代码
- 识别并检索 HTML 中包含的 JPG 图片(目前仅支持 JPG)
- 将 JPG 图片存储在可执行文件所在的目录中。图片存储为 <年><月><日>.jpg
此外,我尝试开发一个用户友好的窗口。不过,目前仅允许选择日期。
背景
不需要任何特定背景知识,只需具备 C#(或其他任何面向对象语言和原则)以及 Microsoft Visual Studio 的基本知识即可。
请注意,代码比较“粗糙”,因此文档和代码的整洁度不足。
Using the Code
程序很简单。用户目前可以选择一个特定日期。然后允许执行三个命令:
- 获取图片
- 获取所选月份的所有图片(日期早于所选日期)
- 退出
正如我稍后会解释的那样,2 实际上是 1 的扩展。1 完成了最复杂的工作。
但在我开始之前,我们需要了解 APOD 中的信息和页面的结构——一种非常简单直观的方式:
APOD 的基本 URL 是:
- http://antwrp.gsfc.nasa.gov/
运行该网站的人员既聪明又善良,他们提供了一个庞大的免费图片库(包括当前和过去的图片),可以通过以下方式访问:
- http://antwrp.gsfc.nasa.gov/apod/ap<2位年份><2位月份><2位日期>.html
例如,2009 年 09 月 09 日的图片可以通过以下 URL 访问:
- http://antwrp.gsfc.nasa.gov/apod/ap090916.html
因此,知道了获取任意给定日期页面的规则,就可以开始使用漂亮的 C#、.NET 和 HTTP 技术了。
开始吧!
实际上,当用户按下“GET!”按钮时,操作就开始了。点击事件调用以下代码:
private void buttonGET_Click(object sender, EventArgs e)
{
GetAPODImage(dateTimePicker.Value);
}
GetAPODimage
方法执行主要工作。
首先,我们根据上面解释的规则生成所选日期的 URL。
string url = GenerateAPOD_URL(“http://antwrp.gsfc.nasa.gov/apod/ap”,date);
此方法构建 URL 的方式如下:
private string GenerateAPOD_URL(string rootURL, System.DateTime date)
{
return rootURL
+ Get2DigitYear(date)
+ Get2DigitNumberAsString(date.Month)
+ Get2DigitNumberAsString(date.Day)
+ “.html”;
}
请注意,Get2DigitNumberAsString
返回一个两位数的 string
。例如,如果选定的日期是 1,它返回‘01’。
接下来,我们将检索 HTML 页面。
GetHTTP(url,5000,ref resultHTML);
GetHTTP
方法将从“url
”获取 HTML 页面并将其存储到“resultHTML
”中。请注意,我们传递了“5000”(即 5 秒),这表示等待获取页面的超时时间——这对于防止长时间等待页面非常重要。
GetHTTP
的代码如下:
// create HTTP request
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Timeout = timeout;
req.ReadWriteTimeout = timeout;
// get response
WebResponse resp = req.GetResponse();
// we will read data via the response stream
Stream resStream = resp.GetResponseStream();
int count = 0;
byte[] buf = new byte[8192];
resultHTML = "";
do
{
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text
resultHTML += Encoding.ASCII.GetString(buf, 0, count);
}
}
while (count > 0); // any more data to read
resp.Close();
很简单。好的——现在,如果没有发生异常,我们就必须解析‘resultHTML
’并查找‘JPG’(即我们希望下载的精美图片):
GetHTTPFilesByTypeSuffix(resultHTML, ‘.JPG’, ref list);
我不会在这个函数中过多详细介绍,除了这项工作是查找‘href=
’并获取引用的文件。它仅在是‘.JPG’时才认为是有效的。
例如:如果变量‘resultHTML
’包含“<a href="image/0909/tarantula_gleason.jpg">
”,那么 image/0909/tarantula_gleason.jpg 将被添加到列表中(变量‘list
’)。
既然我们有了图片文件,就应该将它们下载并存储到磁盘(请看粗体代码):
try
{
....
//get and save images
foreach (string file in list)
{
String source = “http://antwrp.gsfc.nasa.gov/apod/”+file;
string dest = GetYYYYMMDD(date)+’.JPG’;
WebClient Client = new WebClient();
Client.DownloadFile(source, dest);
pictureBox.Image = Image.FromFile(dest);
}
}//end try
catch (Exception ex)
{
Console.WriteLine("An exception occurred: " + ex.Message);
pictureBox.Image = Properties.Resources.g_close;
}
请注意
- 图片存储后,我会在
pictureBox
(主窗口中)显示它。 - 如果发生错误,
pictureBox
会显示一个错误图片。
最后,如何获取所选月份(日期早于所选日期)的所有图片?很简单。
private void buttonGETMONTH_Click(object sender, EventArgs e)
{
DateTime date = dateTimePicker.Value;
for (int i = 1; date.Month == dateTimePicker.Value.Month; i++ )
{
GetAPODImage(date);
date = dateTimePicker.Value.AddDays(-i);
}
}
诀窍是初始化一个临时日期变量为所选日期,然后递减天数,直到月份发生变化。
就是这样!希望您喜欢这篇文章。
最后的 remarks
您可以下载 win32 二进制文件并直接运行(需要 .NET 3.5 Framework)。如果您打开解决方案,您会注意到它依赖于 WeAreUtils(也包含在内)。这个库实际上包含了文章中提到的许多实用工具。然而,我决定提供一个简化版本,以便更容易理解。
如果您喜欢这款软件,您可以在 SourceForge 上找到它(http://sourceforge.net/projects/weareapod/)!加入该项目!
历史
- 2009 年 9 月 16 日:初始帖子