Как-то воскресным вечером я смотрел картинки, передаваемые с веб-камер, расположенных на Фарерских островах. Я слежу за погодой в этих местах, так как мы планируем семейную поездку по Фарерским островам, Исландии и Ирландии.

.

Сценарий GetWebJPG.vbs запускается с помощью хост-среды CScript WSH. Он создает выходную папку для хранения изображений с веб-камеры (если она еще не существует). После того как папка создана, сценарий посылает в веб-сервер запрос HTTP GET, чтобы получить очередной jpg-файл из камеры и сохранить его локально. Затем GetWebJPG.vbs ожидает следующего изображения. Каждому локально сохраненному файлу присваивается последовательный номер.

GetWebJPG.vbs обращается к веб-серверу через заданные интервалы времени, пока количество обращений не достигнет максимального значения, установленного константой MAXLOOP. Выполнение сценария останавливается, если происходит «фатальный» сбой (например, нарушается связь веб-сервера с Интернетом). Если перезапустить сценарий, выполнение возобновляется с последнего сохраненного файла.

Существует возможность распознавать или исключить из GetWebJPG.vbs ошибки различных типов. Например, выполнение сценария продолжается при распространенной ошибке 404 «not found», которая может быть следствием мелкого сбоя на сервере. Совсем ни к чему завершать работу сценария из-за единственного пропущенного файла. Меры для проверки ошибок в сценарии минимальны, но их можно расширить в зависимости от конкретных требований, игнорируя одни ошибки и останавливая сценарий при возникновении других.

Чтобы углубиться в GetWebJPG.vbs, просмотрите код в листинге 1. В сценарии указана рабочая веб-камера, и вы сможете получить jpg-файлы из единственного аэропорта на Фарерских островах. Как показано в листинге 2, сценарий получает копии jpg-файлов с веб-камеры, формируемые по адресу http://212.55.50.150/webcam/image.jpg. Новые jpg-файлы поступают через каждые 15 секунд в течение более 40 часов (10 000 циклов) и сохраняются в папке C:\WebShots. Каждому файлу присваивается последовательный номер начиная с FAE000001.jpg; поэтому следующие файлы будут иметь имена FAE000001.jpg, FAE000002.jpg, FAE000003.jpg и т. д.

Можно запустить несколько сценариев для веб-сервера и получать изображения с различных камер на нем. Например, чтобы запустить второй сценарий для сбора снимков со второй веб-камеры в аэропорту Фарерских островов, следует изменить значение константы WEBFILE на «webcam/image31.jpg», а константы PREFIX на «FAE2». Префиксы файлов с первой и второй веб-камер разные, поэтому изображения с обеих камер можно хранить в одной папке.

Выполнив в Интернете поиск по ключевым словам webcams или web cameras, можно найти другие сайты с веб-камерами. В частности, можно получить jpg-файлы с камеры на сайте Wiley Coyote (http://www.acmecoyote.com/wiley/cam/roadrunner.jpg). Предположим, нам нужно получать jpg-файл через каждые 30 секунд в течение 24 часов (2880 циклов) и сохранить изображения в папке D:\WebShots. Каждому файлу будет присвоен последовательный номер начиная с RR000001.jpg, поэтому следующие файлы будут иметь имена RR000001.jpg RR000002.jpg, RR000003.jpg и т. д. Для этого требуется изменить константы, показанные в листинге 3, а затем запустить сценарий. Обратите внимание, что сайта http://www.acmecoyote.com/wiley/cam/roadrunner.jpg в действительности не существует, поэтому запуская сценарий, необходимо заменить веб-камеру или использовать GetWebJPG.vbs в первоначальном виде.

Спустя 24 часа можно проверить изображения и выбрать все или некоторые из них для анимационного видеофильма. Обрезать изображения, вставляемые в фильм,

позволяет Microsoft Office Picture Manager (он входит в состав Microsoft Office).

  1. Откройте Microsoft Office Picture Manager и выберите команду Add Picture Shortcut из меню File. Перейдите к папке, содержащей jpg-файлы, выделите ее и нажмите кнопку Add.
  2. Выберите пункт Thumbnails в меню View, а затем Select All в меню Edit.
  3. Щелкните Edit Pictures, а затем выберите Crop в области Edit Pictures.
  4. Обрежьте первое изображение так, как нужно обрезать все изображения. Нажмите OK.
  5. Сохраните все изображения для анимационного видеофильма, выбрав пункт Save All в меню File.

Готовые файлы можно объединить в фильм с помощью привычного редактора изображений или видеоредактора. Я загрузил изображения и подготовил два фильма с использованием Windows Live Movie Maker (explore.live.com/windows-live-moviemaker).

В первом видеофильме события, произошедшие в аэропорту почти за три часа, сжаты в 18 секунд. В другом фильме показано, каким пустынным был аэропорт после извержения вулкана в Исландии весной 2010 г. Он также показывает, насколько переменчивой может быть погода в течение трех часов, сжатых до 23 секунд.

Сейчас на моем компьютере функционирует несколько сценариев, сохраняющих снимки с веб-камер на жестком диске. Нагрузка на процессор и оперативную память невелика, а результаты подчас потрясающие.

Харри Вердж — старший технолог крупной телекоммуникационной компании в Калгари. Отвечает за групповые политики Active Directory (AD), написание сценариев для большого количества компьютеров и поиск неисправностей

Листинг 1. Сценарий GetWebJPG.vbs
‘ -----------------------------------------------------------
' HARRY VERGE - APR 2010
' Scrape WebCam JPG picture to local computer. Gets JPG image
 file
' from web server and saves incremental copies to local
 computer.
' Tested on XPSP3 and Windows 7.
' To use with a proxy, you must first set the proxy
 connection.
' For more information, at a CMD prompt:
'  In WINXP type 'PROXYCFG'
'  In WIN7  type 'NETSH WINHTTP SET PROXY'
' -----------------------------------------------------------
' You First need to modify the script so it knows what JPG
 to get
' from the web.
' For example, if the Web Cam image is generated at the URL
' http://www.acme-coyote.com/wiley/webcam/roadrunner.jpg
 then modify
' the following to reflect this:
'  WEBROOT = "www.acme-coyote.com"
'  WEBFILE = "wiley/webcam/roadrunner.jpg"
' Next, to save them to the local folder "D:\WebShots"
 with a new
' subfolder based on the WEBROOT shown above,
 modify the local
' computer save location as follows:
'  DRIVE = "D:"
'  DOWNLOADS = "WebShots"
' To specify a 30-second interval between each new file,
 modify
' the following:
' MAXSECONDS = 30
' And last, to force a maximum number of times the script will
 loop
' before it exits, modify the following to your desired
 number.
 This
' example assumes 2 shots per minute for 24 hours:
' MAXLOOP = 2880
' -----------------------------------------------------------
Option Explicit
On Error Resume Next
Const SCRIPTNAME = "Get WebCam Picture"
Const SUCCESS = 0
Const ERROR = 1
Const MAXSECONDS = 15 ' Max seconds between picture copies.
Const MAXLOOP    = 10000 ' Max times to loop & copy picture.
Const PREFIX     = "FAE" ' Start saved pictures with this
 prefix.
Const DRIVE      = "C:"  ' Drive letter for
  folder.
Const DOWNLOADS  = "WebShots" ' Name of root folder.
Const WEBROOT = "212.55.50.150" ' IP or DNS for Web Root.
Const WEBFILE   = "webcam/image.jpg" ' Path and name of image
 file on web server.
Dim strFullWebURL, strMsgHead, strComputer, strLastOne,
 strMsgEvent, strNewFile
Dim GetURLBinary
Dim i, iCounter
Dim objShell, objFSO, objWMIService, objFile, objHTTP,
 objStream, colFiles
strFullWebURL = "http://" & WEBROOT & "/" & WEBFILE
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
' -----------------------------------------------------------
' Force VBS to use Cscript instead of Wscript if not using it
 already:
' -----------------------------------------------------------
If Instr(1, WScript.FullName, «CScript», vbTextCompare) = 0
 Then
   objShell.Run "cscript //nologo """ & WScript.ScriptFullName
 & """", 1, False
   WScript.Quit
End If
' -----------------------------------------------------------
' Build standard message header for event log and error
 message boxes:
' -----------------------------------------------------------
strMsgHead = vbcrlf & vbcrlf &_
   "Script Name: " & vbtab & Wscript.ScriptName & vbcrlf &_
   "Script Path: " & vbtab &_
    Replace(Wscript.ScriptFullName, "\" & Wscript.ScriptName,
 "") & vbcrlf &_
   "Get JPG From:" & vbtab & strFullWebURL & vbcrlf &_
   "Save JPG to:" & vbtab & DRIVE & "\" & DOWNLOADS & "\" &
 WEBROOT & vbcrlf &_
   "Save Interval:" & vbtab & "Every " & MAXSECONDS & "
 seconds." & vbcrlf & vbcrlf
' -----------------------------------------------------------
'  Create saved picture directory structure if not already
 there:
' -----------------------------------------------------------
If Not objFSO.FolderExists(DRIVE & "\" & DOWNLOADS) Then _
   objFSO.CreateFolder(DRIVE & "\" & DOWNLOADS)
If Err.Number <> 0 Then ErrorCheck
If Not objFSO.FolderExists(DRIVE & "\" & DOWNLOADS & "\" &
 WEBROOT) Then _
   objFSO.CreateFolder(DRIVE & "\" & DOWNLOADS & "\" &
 WEBROOT)
If Err.Number <> 0 Then ErrorCheck
' -----------------------------------------------------------
' Grab last picture saved in folder so we can build counter
 start value:
' -----------------------------------------------------------
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer
 & "\root\cimv2")
Set colFiles = objWMIService. _
    ExecQuery("Select * from CIM_DataFile where " &_
              "Drive = '" & DRIVE & "' and " &_
              "Path = '\\" & DOWNLOADS & "\\" & WEBROOT
 & "\\' and " &_
              "FileName like '" & PREFIX & "%' ")
For Each objFile in colFiles
    strLastOne = Mid(objFile.FileName, Len(PREFIX)+1,
 Len(objFile.FileName)-Len(PREFIX))
Next
If strLastOne = "" Then
   iCounter = 0
   strMsgEvent = "Script Started at " & Now() & "."
Else
   iCounter = strLastOne
   strMsgEvent = "Script Started at " & Now() & ".
 Continuing from picture " &_
     PREFIX & iCounter & ".JPG."
End If
' -----------------------------------------------------------
' Show start, write to App Event Log, then begin main
 processing loop:
' -----------------------------------------------------------
Wscript.Echo SCRIPTNAME & vbcrlf &_
   "Script Started at " & Now() &_
   ". Saving picture every " & MAXSECONDS & " seconds."
 & vbcrlf
objShell.LogEvent SUCCESS, SCRIPTNAME & strMsgHead &
 strMsgEvent
For i = 1 to MAXLOOP
'   ---------------------------------------------------------
'   Send off web request:
'   ---------------------------------------------------------
    Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
    objHTTP.Open "GET", strFullWebURL, False
    Err.Clear
    objHTTP.Send
    If Err.Number <> 0 Then ErrorCheck
    GetURLBinary = objHTTP.ResponseBody
    If Not objHTTP.Status = 200 Then ErrorHTTP
‘   ---------------------------------------------------------
'   Save download as JPG binary:
'   ---------------------------------------------------------
    Err.Clear
    iCounter = iCounter + 1
    iCounter = Right("000000" & iCounter, 6)  ' Build in
 leading zeroes. Increase mask if needed.
    strNewFile = DRIVE & "\" & DOWNLOADS & "\" & WEBROOT
 & "\" & PREFIX & iCounter & ".JPG"
    Set objStream = CreateObject("ADODB.Stream")
    objStream.Type = 1 ' Set ADODB Stream as binary
    objStream.Open
    objStream.Write GetURLBinary
    objStream.SaveToFile strNewFile, 2 ' Overwrite file if it
 exists
    objStream.Close
    If Err.Number <> 0 Then ErrorCheck
'   ---------------------------------------------------------
'   Show progress in console window, then sleep until next
 interval:
'   ---------------------------------------------------------
    Wscript.Echo Now() & ": Wrote " & strNewFile
    Set objStream = Nothing
    Set objHTTP = Nothing
    If i = MAXLOOP Then Exit For
    WScript.Sleep(MAXSECONDS * 1000)
Next
' -----------------------------------------------------------
' Outside loop? Then the MAXLOOP limit was reached:
' -----------------------------------------------------------
strMsgEvent = "Maximum [" & MAXLOOP & "] reached. End of
 script. " &_
  "Last picture was " & PREFIX & iCounter & ".JPG"
objShell.LogEvent SUCCESS, SCRIPTNAME & strMsgHead &
 strMsgEvent
Wscript.Echo vbcrlf & Now() & ": Maximum [" & MAXLOOP & "]
 reached. End of script."
‘ -----------------------------------------------------------
‘ Error Handlers:
' -----------------------------------------------------------
Sub ErrorCheck()
    strMsgEvent = "ERROR:" & vbcrlf & vbcrlf &_
      "Number:" & vbtab & vbtab & Err.Number & vbcrlf &_
      "Description:" & vbtab & Err.Description
    If Err.Number = 71 Then
       strMsgEvent = strMsgEvent & vbcrlf & vbcrlf &_
         "Most likely reason is you do not have a '" & DRIVE &
 "' drive.    "
       ShowError
       Wscript.Quit
    End If
    If Err.Number = -2147012867 Then
       strMsgEvent = strMsgEvent & vbcrlf & vbcrlf &_
         "Most likely reason(s): Server is down, or you are
 using a proxy connection.    "
       ShowError
       Wscript.Quit  
    End If
    ShowError
End Sub
Sub ErrorHTTP()
    strMsgEvent = vbcrlf & vbcrlf &_
      "Error getting file." & vbcrlf & vbcrlf &_
      "Web URL:" & vbtab & strFullWebURL & vbcrlf &_
      "Server Response:" & vbtab & objHTTP.status &_
      " [" & objHTTP.StatusText & "]"
    If objHTTP.status = 404 Then
       strMsgEvent = strMsgEvent & vbcrlf & vbcrlf &_
      "Likely reason is Web Server is working, but URL
 could not be found.   "
    End If
    ShowError
End Sub
Sub ShowError()
    objShell.LogEvent ERROR, SCRIPTNAME & strMsgHead &
 strMsgEvent
    Wscript.Echo Now() & ": ERROR " & strMsgEvent
'   ---------------------------------------------------------
'   Modify/Enable/Disable this optional escape from script:
'   ---------------------------------------------------------
'   If Not Err.Number = 3001 Then
'      MsgBox SCRIPTNAME & vbcrlf & vbcrlf & strMsgEvent,
 vbCritical, "ERROR"
'      Wscript.Quit
'   End If
End Sub
Листинг 2. Значения констант в первоначальной версии GetWebJPG.vbs
Const WEBFILE = "webcam/image.jpg"
Const MAXSECONDS = 15
Const MAXLOOP = 10000
Const DRIVE = "C:"
Const DOWNLOADS = "WebShots"
Const PREFIX = "FAE"
Листинг 3. Пример изменения констант
Const WEBROOT = "www.acmecoyote.com"
Const WEBFILE = "wiley/cam/roadrunner.jpg"
Const MAXSECONDS = 30
Const MAXLOOP = 2880
Const DRIVE = "D:"
Const DOWNLOADS = "WebShots"
Const PREFIX = "RR"