4
$\begingroup$

Bing has nice images that change daily. How can we download them regularly and also maybe download an archive of previous images? There is an extensive discussion here, can we implement it in Mathematica elegantly and efficiently?

To recap the info from the link above, the url for the image is http://www.bing.com/HPImageArchive.aspx?format=xml&idx={index}&n={number}&mkt=en-US, where index is the number of days to go back and number is the number of images to retrieve starting from the index date.

After some experimentation, we can see that the maximum number of days you can go back index is 7, and the maximum number of images you can retrieve is 8. At the maximum of index=7, the maximum of number=2 (we can only go back one week when index=7, but then we can also go one additional day back using number=2). Also, if index=-1, we can see tomorrow's picture. So we can get total of 10 pictures. If anybody knows how to get more, that would be cool.

Following this idea, if we open this link, for example, we get a very nicely formatted XML response for October 17th.

https://www.bing.com/HPImageArchive.aspx?format=xml&idx=7&n=1&mkt=en-US

Now, in the response, we can get the <url> tag

<url>
"/az/hprichbg/rb/ElkValleyVideo_EN-US7645555683_1366x768.jpg"
</url>

which we now have to merge with "https://www.bing.com" to get this link that contains the pictire:

https://www.bing.com/az/hprichbg/rb/ElkValleyVideo_EN-US7645555683_1366x768.jpg

In addition, there is a description of this image:

<copyright>
Elk River in the East Kootenays of British Columbia, Canada (© Carson Ganci/First Light/age fotostock)
</copyright>

It would also be good to add this text to the JPG "Title" tag so that it is visible in viewers that use it.

$\endgroup$
15
$\begingroup$

I would use RawJSON to import the information:

bingJSON = Import[
    "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=10&mkt=en-US",
    "RawJSON"
];

Then, create a template:

URLTemplate="https://bing.com/`urlBase`_`resolution`.jpg";

Finally, Import the template with the given data:

Table[
    Import @ TemplateApply[
        URLTemplate,
        <|"urlBase" -> bingJSON["images"][[i, "urlbase"]], "resolution"->"1920x1080"|>
    ],
    {i, Length @ bingJSON["images"]}
]

enter image description here

$\endgroup$
  • $\begingroup$ Nice ;) +1 Templating is neat. $\endgroup$ – Vitaliy Kaurov Oct 25 '17 at 0:43
  • $\begingroup$ Thanks! Very elegant! I wouldn't think of RawJSON and TemplateApply $\endgroup$ – Stitch Oct 25 '17 at 0:43
  • $\begingroup$ Do you have any ideas how to export EXIF tag with the title? I know we can import EXIF, but can we export? $\endgroup$ – Stitch Oct 30 '17 at 0:07
5
$\begingroup$

Perhaps this:

base = "https://www.bing.com";
info = base <> "/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US";
Import[base <> Import[info, "JSON"][[1, 2, 1, 6, 2]]]

or similar, but more robust if they change structure of "JSON" in future.

base = "https://www.bing.com";
info = base <> "/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US";
Import[base <> Cases[
  Import[info, "JSON"], 
  HoldPattern["url" -> x_String] :> x, Infinity][[1]]
]
$\endgroup$
  • $\begingroup$ That's very nice, using JSON instead of XML. +1 Any idea about tagging the JPG file? $\endgroup$ – Stitch Oct 25 '17 at 1:00
3
$\begingroup$

As a first approximation, we can do the following. We read the xml file from the Web

xml = URLRead["https://www.bing.com/HPImageArchive.aspx?format=xml&idx=7&n=1&mkt=en-US"]

HTTPResponse[Status: OK, Content type: text/xml;charset=utf-8]

Then, we can import it as an XML object

xmlobject = Import[xml, "XML"];

And find the element that contains the picture name

urlElement = Cases[xmlobject, XMLElement["url", _, _], Infinity]

{XMLElement["url", {}, {"/az/hprichbg/rb/ElkValleyVideo_EN-US7645555683_1366x768.jpg"}]}

Parse it to get the string

url = First@Cases[urlElement, XMLElement["url", _, {urls_}] -> urls]

"/az/hprichbg/rb/ElkValleyVideo_EN-US7645555683_1366x768.jpg"

Get the position in the file name that contains resolution info

resolutionPos = First@
                StringPosition[url, "_" ~~ NumberString ~~ "x" ~~ NumberString ~~ ".jpg"]

{47, 59}

Replace the part of the file name with the HD resolution

urlHD = StringReplacePart[url, "_1920x1080.jpg", resolutionPos]

"/az/hprichbg/rb/ElkValleyVideo_EN-US7645555683_1920x1080.jpg"

Build a full URL

urlPicture = "https://bing.com" <> urlHD

"https://bing.com/az/hprichbg/rb/ElkValleyVideo_EN-US7645555683_1920x1080.jpg"

And finally, download the picture

URLDownload[urlPicture, "c:/temp/" <> Last@FileNameSplit[urlPicture]];

This is, of course, very simple, and might be improved in terms of efficiency by using an XML response that has more than one image, and downloading all 10 files at the same time. Additionally, I am not sure how to add the JPG "Title" tag.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.