メモ

主にプログラミング系の備忘録

Yahoo!Japanのテキスト解析APIを使ってみた

Yahoo!Japan デベロッパーネットワークトップ > テキスト解析 > キーフレーズ抽出
https://developer.yahoo.co.jp/webapi/jlp/keyphrase/v1/extract.html

Const APIKEY_Y As String = "取得したAPIキー"
Public Function getKeyWords(ByVal str As String) As String
  Dim sUrl As String: sUrl = "https://jlp.yahooapis.jp/KeyphraseService/V1/extract"
  Dim sSendData As String: sSendData = "appid=" & APIKEY_Y & "&sentence=" & str
  Dim objHttp As XMLHTTP: Set objHttp = New XMLHTTP
  Dim objResponse As DOMDocument
  Dim sRet As String: sRet = ""
  Dim el As IXMLDOMNode
  
  objHttp.Open "POST", sUrl, False
  Call objHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
  objHttp.send (sSendData)
  Set objResponse = objHttp.responseXML
  
  'エラーが返ってきた場合はエラーメッセージを返す
  If objResponse.SelectNodes("/Error").Length > 0 Then
    For Each el In objResponse.SelectNodes("/Error")
      If sRet <> "" Then sRet = sRet & vbCrLf
      sRet = sRet & el.Text
    Next el
    getKeyWords = sRet
    Exit Function
  End If
  
  For Each el In objResponse.SelectNodes("/ResultSet/Result")
    If sRet <> "" Then sRet = sRet & vbCrLf
    sRet = sRet & el.FirstChild.Text & vbTab & el.LastChild.Text
  Next el
  getKeyWords = sRet
  
End Function

校正支援 https://developer.yahoo.co.jp/webapi/jlp/kousei/v1/kousei.html

Public Function getKousei(ByVal str As String)
  Dim sUrl As String: sUrl = "  https://jlp.yahooapis.jp/KouseiService/V1/kousei"
  Dim sSendData As String: sSendData = "appid=" & APIKEY_Y & "&sentence=" & str
  Dim objHttp As XMLHTTP: Set objHttp = New XMLHTTP
  Dim objResponse As DOMDocument
  Dim sRet As String: sRet = ""
  Dim el As IXMLDOMNode
  
  objHttp.Open "POST", sUrl, False
  Call objHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
  objHttp.send (sSendData)
  Set objResponse = objHttp.responseXML
  
  'エラーが返ってきた場合はエラーメッセージを返す
  If objResponse.SelectNodes("/Error").Length > 0 Then
    For Each el In objResponse.SelectNodes("/Error")
      If sRet <> "" Then sRet = sRet & vbCrLf
      sRet = sRet & el.Text
    Next el
    getKousei sRet
    Exit Function
  End If
  For Each el In objResponse.SelectNodes("/ResultSet/Result")
'    Stop
    If sRet <> "" Then sRet = sRet & vbCrLf
    For i = 0 To el.ChildNodes.Length - 1
      sRet = sRet & el.ChildNodes(i).Text & vbTab
    Next i
    sRet = Left(sRet, Len(sRet) - 1)
  Next el
  getKousei = sRet
End Function

パワポのテキストをExcelに書き出す

Const sFileName as String ="パワポファイルをフルパスで"
Sub Export_PPT()
  Dim pptApp As PowerPoint.Application: Set pptApp = New PowerPoint.Application
  Dim pptFile As PowerPoint.Presentation
  Dim dStartTime As Date: dStartTime = Now()
  
  Set pptFile = pptApp.Presentations.Open(sFileName, msoTrue)
  Dim pptSlide As PowerPoint.Slide
  Dim pptShp As PowerPoint.Shape
  Dim nRow As Long: nRow = 2
  Dim i As Long: Dim j As Long
  
  Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets(1)
  ws.Cells.Clear
  
  ws.Range("A1") = "スライド番号"
  ws.Range("B1") = "シェイプ名"
  ws.Range("C1") = "行番号"
  ws.Range("D1") = "列番号"
  ws.Range("E1") = "テキスト"
  ws.Range("E:E").NumberFormatLocal = "@"
  For Each pptSlide In pptFile.Slides
    For Each pptShp In pptSlide.Shapes
      If pptShp.HasTextFrame Then
        If Replace(pptShp.TextFrame.TextRange.Text, Chr(11), vbLf) <> "" Then
        ws.Range("A" & nRow) = pptSlide.SlideNumber
        ws.Range("B" & nRow) = pptShp.Name
        ws.Range("E" & nRow) = Replace(pptShp.TextFrame.TextRange.Text, Chr(11), vbLf)
        nRow = nRow + 1
        End If
      ElseIf pptShp.HasTable Then
        For i = 1 To pptShp.Table.Rows.Count
          For j = 1 To pptShp.Table.Columns.Count
            If pptShp.Table.Cell(i, j).Shape.HasTextFrame Then
              If Replace(pptShp.Table.Cell(i, j).Shape.TextFrame.TextRange.Text, Chr(11), vbLf) <> "" Then
                ws.Range("A" & nRow) = pptSlide.SlideNumber
                ws.Range("B" & nRow) = pptShp.Name
                ws.Range("C" & nRow) = i
                ws.Range("D" & nRow) = j
                ws.Range("E" & nRow) = Replace(pptShp.Table.Cell(i, j).Shape.TextFrame.TextRange.Text, Chr(11), vbLf)
                nRow = nRow + 1
              End If
            End If
          Next j
        Next i
      End If
    
    
    Next pptShp
    DoEvents
  Next pptSlide
  
  pptFile.Close
  pptApp.Quit
  
  MsgBox "書き出したよ(所要時間:" & Format(Now() - dStartTime, "hh:mm:ss") & ")"
  

End Sub

A3RTのText Classification をやってみた

https://a3rt.recruit-tech.co.jp/product/textClassificationAPI/ リファレンスなどはこちら
https://github.com/VBA-tools/VBA-Dictionary JSONの操作で使用
http://blog.goo.ne.jp/xmldtp/e/c7e3c3631d31206f818b30276d0f3091 リクエスト投げるところはここを参考に

うまく結果が返ってきた場合は ラベル{タブ}合致度{改行}のリストを
結果が正しく帰ってこない場合は ステータスコード{タブ}メッセージ
を返します。

09/13 追記
VBA-JSONのURL間違ってた
https://github.com/VBA-tools/VBA-JSON

Const APIKEY As String = "取得したAPIキー"

Public Function getClassifiedResult(ByVal str As String, Optional ByVal model_id As String = "default") As String
    Dim objJSON As Object 'JSONファイルをパースしたもの
    Dim i As Long
    Dim sRet As String: sRet = ""
    target_url = "https://api.a3rt.recruit-tech.co.jp/text_classification/v1/classify"
    sendData = "apikey=" & APIKEY & "&text=" & str & "&model_id=" & model_id

    Set httpobj = CreateObject("MSXML2.XMLHTTP")
    httpobj.Open "POST", target_url, False
    Call httpobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
    httpobj.send (sendData)
    Set objJSON = ParseJson(httpobj.responseText)
    If objJSON("status") <> 0 Then
      getClassifiedResult = objJSON("status") & vbTab & objJSON("message")
      Exit Function
    End If
    
    For i = 1 To objJSON("classes").Count
      If sRet <> "" Then sRet = sRet & vbCrLf
      sRet = sRet & objJSON("classes")(i)("label") & vbTab & FormatPercent(objJSON("classes")(i)("probability"), 2, vbTrue)
    
    Next i
    getClassifiedResult = sRet
End Function

パスワード付のzipファイルを解凍する関数

5/31 追記 自宅環境だとcmdでunzipコマンドが通らない。
どうしたらunzipをcmdで使えるようになるのか調査中。
http://www.info-zip.org/ にあるものを適切にインストールすればよいらしいが引き続き調査中

Public Function unzip(sFileName As String, sPwd As String) As Boolean
  On Error GoTo err_Trap
  
  Dim ShellObj
   
  Set ShellObj = CreateObject("WScript.Shell")
  Debug.Print "unzip -d """ & Replace(sFileName, ".zip", "") & """ -P " & sPwd & """" & sFileName & """"
  ShellObj.Run "unzip -d """ & Replace(sFileName, ".zip", "") & """ -P " & sPwd & " """ & sFileName & """"
  
  unzip = True
  Exit Function
err_Trap:
  Debug.Print Err.Description & Err.Number
  unzip = False
  
 
End Function

アップロード画面への遷移まで

17/05/26追記:Googleへのログインのインターフェースが変わったので現在機能しません。
17/05/31追記:よくわからないClassNameでログインアカウントを選択してよいなら改修できそうな気がする
なお、引っ掛かるのは「(4)ログインアカウントの選択」の工程
クラス名の意味が良くわからないのでこれ使っていいのか悩んでいるところ

定数

Public Const YOURID As String = "【YouTubeアカウント】"
Public Const YOURPWD As String = "【YouTubeパスワード】"

(1)YTトップページに遷移

Public Function YT_Navigate() As InternetExplorer

  Dim ie As InternetExplorer: Set ie = New InternetExplorer
  ie.navigate "https://www.youtube.com/":  Call ieCheck(ie)
  ie.Visible = True
'  Debug.Print "YTトップページに遷移"
  Set YT_Navigate = ie
End Function

(2)YTログアウト

Public Function YT_Logout(ie As InternetExplorer) As Boolean 'ie As InternetExplorer
  Dim dom As HTMLDocument
  Dim el As IHTMLElement
  ie.Visible = True 'debug
  
  Set dom = ie.document
    
  For Each el In dom.getElementsByTagName("a")
'    Debug.Print el.getAttribute("href"), el.innerText
    If Trim(el.innerText) = "ログアウト" Then
      el.click
      Call ieCheck(ie)
      YT_Logout = True
 '     Debug.Print "ログアウトに成功"
      Exit Function
    End If
  Next el
  
  YT_Logout = False 'ログアウト済、という認識になるのかな
'      Debug.Print "ログアウトボタンなし(ログアウト済)"

End Function

(3)YTログインボタンを押下

Public Function YT_Login_Click(ie As InternetExplorer) As Boolean
  Dim dom As HTMLDocument
  Dim el As IHTMLElement
  
  Set dom = ie.document
    
  For Each el In dom.getElementsByTagName("a")
    If Trim(el.innerText) = "ログイン" Then
      el.click
      Call ieCheck(ie)
      YT_Login_Click = True
'      Debug.Print "ログインボタン押下に成功"
      Exit Function
    End If
  Next el
'  Debug.Print "ログインボタン押下に失敗"
  YT_Login_Click = False
  
End Function

(4)ログインアカウントの選択

Public Function YT_SelectLoginAccount(ie As InternetExplorer, sId As String) As Boolean
  
  
  Dim dom As HTMLDocument: Set dom = ie.document
  Dim el As IHTMLElement
  For Each el In dom.getElementsByTagName("button")
  If el.Value = sId Then
    el.click
    Call ieCheck(ie)
'    Debug.Print "アカウント選択に成功"
    YT_SelectLoginAccount = True
    Exit Function
  End If
  Next el
  
  YT_SelectLoginAccount = False
'  Debug.Print "アカウント選択に失敗"
End Function

(5)パスワードを入力し、「ログイン」ボタンを選択

Public Function YT_Login(ie As InternetExplorer, sId As String, sPwd As String) As Boolean
  Dim dom As HTMLDocument
  
  Set dom = ie.document
  Call dom.getElementById("Passwd").setAttribute("value", sPwd)
  dom.getElementById("signIn").click
  Call ieCheck(ie)
  
  YT_Login = True
  Debug.Print "ログイン成功"
End Function

(6)アップロード画面に遷移

Public Function YT_NavigateUpload(ie As InternetExplorer) As Boolean
  
  Dim dom As HTMLDocument
  Dim el As IHTMLElement
  
  Set dom = ie.document
  For Each el In dom.getElementsByTagName("a")
    If el.getAttribute("title") = "アップロード" Then
      el.click
      Call ieCheck(ie)
      YT_NavigateUpload = True
      Exit Function
    End If
  Next el
  
  YT_NavigateUpload = False
  
End Function

これまでのまとめ。

Public Sub YT_Prepare()
  Dim sId As String: sId = YOURID
  Dim sPwd As String: sPwd = YOURPWD
  
  Dim ie As InternetExplorer: Set ie = YT_Navigate()
  Dim i As Long
  Debug.Print "ログアウト:", YT_Logout(ie)
  i = 0
  Do Until YT_Login_Click(ie)
    i = i + 1
    Debug.Print i & "回目ログインボタン押下失敗。0.5秒待ちます。"
    Call MySleep(500)
  Loop
  
  Debug.Print "アカウント選択:", YT_SelectLoginAccount(ie, sId)
  Debug.Print "ログイン:", YT_Login(ie, sPwd)
  Debug.Print "アップロード画面に遷移:", YT_NavigateUpload(ie)
    
    
End Sub

3末でoffなので春スキー検討中。そんなわけで春スキーでも営業しているスキー場の情報をsnow&surfさんからgetしてみた

Public Sub getSnowSurf()
  Dim ie As InternetExplorer: Set ie = New InternetExplorer: ie.navigate "https://snow.gnavi.co.jp/close/": Call ieCheck(ie)
  Dim dom As HTMLDocument: Set dom = ie.document
  Dim el As IHTMLElement
  Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets(1):  ws.Cells.Clear
  Dim i As Long: i = 2
  Dim j As Long
  
  For Each el In dom.getElementById("main").getElementsByClassName("area_ski")
'    Stop
  ws.Range("A" & i) = i - 1
  ws.Range("B" & i) = el.getElementsByTagName("h4")(0).innerText
  ws.Range("C" & i) = el.getElementsByTagName("h3")(0).innerText
  If el.getElementsByClassName("condition")(0).getElementsByTagName("td").Length = 8 Then
    For j = 0 To el.getElementsByClassName("condition")(0).getElementsByTagName("td").Length - 1
      ws.Cells(i, j + 4) = el.getElementsByClassName("condition")(0).getElementsByTagName("td")(j).innerText
    Next j
  Else
    ws.Range("L" & i) = el.getElementsByClassName("condition")(0).getElementsByTagName("td")(0).innerText
    For j = 1 To el.getElementsByClassName("condition")(0).getElementsByTagName("td").Length - 1
      ws.Cells(i, j + 3) = el.getElementsByClassName("condition")(0).getElementsByTagName("td")(j).innerText
    Next j
  
  End If
  i = i + 1
  
  Next el
  ie.Quit


End Sub

動画設定情報を取得するプログラム

YouTube APIのlist処理でとろうとしてたが、一部取れない項目があるらしいので力技で。
設定画面に遷移して情報を取得するので、動画の所有者以外はたぶん無理。

Public Sub getSettingVideo(sId As String)
  Dim ie As InternetExplorer
  Dim dom As HTMLDocument
  Dim el As IHTMLElement
  Dim n As Long
  Dim el2 As IHTMLElement
  Set ie = New InternetExplorer
  ie.Visible = True 'debug
  
  ie.navigate "https://www.youtube.com/edit?video_id=" & sId
  Call ieCheck(ie)
  
  Set dom = ie.document
  Debug.Print dom.getElementsByName("title")(0).Value 'タイトル
  For Each el In dom.getElementsByName("description") '説明。ヘッダでも使われてるので…。

    If el.tagName = "TEXTAREA" Then
      Debug.Print el.innerText
      Exit For
    End If
  Next el
  
  'タグ。これは設定されている数をカウントするようにしよう
  n = 0
  For Each el In dom.getElementsByTagName("span")
    If el.getAttribute("role") = "listitem" Then n = n + 1
    
  Next el
  Debug.Print n
  
  
  '公開設定
  For Each el In dom.getElementsByName("privacy")(0).getElementsByTagName("option")
    If el.getAttribute("selected") Then
      Debug.Print el.innerText
      Exit For
    End If
  
  Next el
  

  'コメントを許可 これ、ページ遷移なしでとれたらいいなぁ
  Debug.Print dom.getElementsByName("allow_comments")(0).Value
  
  '動画の評価をユーザに表示する
  Debug.Print dom.getElementsByName("allow_ratings")(0).Value
  '動画のライセンス
  For Each el In dom.getElementsByName("reuse")(0).getElementsByTagName("option")
    If el.getAttribute("selected") Then
      Debug.Print el.innerText
      Exit For
    End If
  Next el

  'シンジケーション
  For Each el In dom.getElementsByName("syndication")
    If el.getAttribute("checked") Then
      Debug.Print el.Value
      Exit For
    End If
  Next el

  '字幕の設定
  For Each el In dom.getElementById("captions_certificate_reason").getElementsByTagName("option")
    If el.getAttribute("selected") Then
      Debug.Print el.innerText
      Exit For
    End If
  Next el
  
  '埋め込みの可不可
  Debug.Print dom.getElementsByName("allow_embedding")(0).getAttribute("checked")
  'チャンネルを登録者に通知
  Debug.Print dom.getElementsByName("creator_share_feeds")(0).getAttribute("checked")
  '年齢制限
  Debug.Print dom.getElementsByName("self_racy")(0).getAttribute("checked")
    
  'カテゴリ
  For Each el In dom.getElementsByTagName("select")
    If el.getAttribute("data-ng-model") = "category" Then Exit For
  Next el
  
  For Each el2 In el.getElementsByTagName("option")
    If el2.getAttribute("selected") = "selected" Then
      Debug.Print el2.innerText
      Exit For
    End If
  Next el2

  '動画の撮影場所
  Debug.Print dom.getElementsByClassName("location-input")(0).Value
  
  '動画の言語はUIが良くわからないので後回し。
  
  '視聴者への翻訳依頼
  Debug.Print dom.getElementsByName("captions_crowdsource")(0).getAttribute("checked")

  '動画の統計情報
  Debug.Print dom.getElementsByName("allow_public_stats")(0).getAttribute("checked")

  '3D動画
  
  For Each el In dom.getElementsByTagName("input")
    If el.getAttribute("data-ng-model") = "threed.is_3d" Then
      Debug.Print el.getAttribute("checked")
      Exit For
    End If
  Next el

  
  'コンテンツに関する申告
  
  For Each el In dom.getElementsByTagName("input")
    If el.getAttribute("data-ng-model") = "product.has_paid_product_placement" Then
      Debug.Print el.getAttribute("checked")
      Exit For
    End If
  Next el
  
  ie.Quit
  


End Sub