VB.NetでRadikoの週間番組表を取得してみる

# VB.NetでRadikoの週間番組表を取得してみる
Radikoの週間番組表は
http://radiko.jp/v2/api/program/station/weekly?station_id=[RadikoStationId]
で取得できるらしいので
[HtmlAgilityPack](https://htmlagilitypack.codeplex.com/)を使ってみた

## 準備
プロジェクトでHtmlAgilityPackを使えるようにする

> PM> Install-Package HtmlAgilityPack

## 週間番組表を扱うコードを書いてみる

```vbnet:RadikoProgram.vb

''' <summary>
''' Radikoの週間番組表を取得するUrl
''' </summary>
Dim RadikoProgramsBaseUrl = "http://radiko.jp/v2/api/program/station/weekly?station_id={0}"

''' <summary>
''' Radikoの番組データ
''' </summary>
Public Class Program

    Property title As String
    Property sub_title As String
    Property desc As String
    Property info As String
    Property Start As DateTime
    Property Duration As Integer

End Class

''' <summary>
''' Radikoの週間番組表
''' </summary>
Property Programs As List(Of Program)

''' <summary>
''' 番組表が取得が終わったEvent
''' </summary>
Event Programs_GetCompleted()

Public Sub New()

    Programs = New List(Of Program)

End Sub

Public Async Sub GetPrograms(RadikoStationId As String)

    Dim requestUri As String = String.Format(RadikoProgramsBaseUrl, RadikoStationId)
    Dim Response = Await RadikoPrograms(requestUri)

    Dim htmlDoc01 = New HtmlAgilityPack.HtmlDocument()
    htmlDoc01.LoadHtml(Response)

    Dim WeeklyPrograms = htmlDoc01.
        DocumentNode.
        SelectNodes("/radiko[1]/stations[1]/station[1]/scd[1]/progs").ToList

    For Each DailyPrograms In WeeklyPrograms

        Dim htmlDoc02 = New HtmlAgilityPack.HtmlDocument()
        htmlDoc02.LoadHtml(DailyPrograms.InnerHtml)

        Programs.AddRange(
            htmlDoc02.
            DocumentNode.
            SelectNodes("/prog").
            Select(Function(x) New Program With {
                       .title = x.ChildNodes.Item("title").InnerText,
                       .sub_title = x.ChildNodes.Item("sub_title").InnerText,
                       .desc = RemoveHTMLTag(x.ChildNodes.Item("desc").InnerText),
                       .info = RemoveHTMLTag(x.ChildNodes.Item("info").InnerText),
                       .Start = ToDateTime(x.Attributes("ft").Value),
                       .Duration = ToDuration(x.Attributes("dur").Value)
                   }).ToList)

    Next

    RaiseEvent Programs_GetCompleted()

End Sub

Private Async Function RadikoPrograms(requestUri As String) As Task(Of String)

    Dim client As Net.Http.HttpClient = New Net.Http.HttpClient()
    Dim getStringTask As Task(Of String) = client.GetStringAsync(requestUri)

    Dim urlContents As String = Await getStringTask
    Return urlContents

End Function

#Region "データの加工処理"

Private Function RemoveHTMLTag(args As String) As String

    Dim RemovePattern As String = "&lt;.*?&gt;"
    Return System.Text.RegularExpressions.Regex.Replace(args, RemovePattern, String.Empty)

End Function

Private Function ToDateTime(args As String) As DateTime

    '20150101125959 -> 2015/01/01 12:59:59
    Dim year = args.Substring(0, 4)
    Dim month = args.Substring(4, 2)
    Dim day = args.Substring(6, 2)
    Dim hour = args.Substring(8, 2)
    Dim minute = args.Substring(10, 2)

    Return New DateTime(year, month, day, hour, minute, 0)

End Function

Private Function ToDuration(args As String) As Integer

    Dim sec As Integer
    If Integer.TryParse(args, sec) Then
        Return sec / 60
    Else
        Return 0
    End If

End Function

#End Region

```

## 書いたコードを使ってみる
終わった番組が表示されても仕方ないので、現在時刻以降の番組をDataGridに表示してみる

```vbnet:Radiko.vb

Dim RadikoProgram As New RadikoProgram
AddHandler RadikoProgram.Programs_GetCompleted, Sub()
				DataGrid.ItemsSource = RadikoProgram.Programs.Where(Function(x) x.Start > System.DateTime.Now)
			End Sub

Dim StationID = "QRR"
RadikoProgram.GetPrograms(RadikoStationId)

```

DataGridのItemsSourceに突っ込むだけでそれらしくなるWPFは便利