質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.19%

あるサイトに保存されているPDFファイルが更新されたことを知る方法はありますか?

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,337

rickey

score 24

【背景】法律や条例等が更新されたことを知りたく、全都道府県の複数の法律の関するページを開き、1つ1つPDFを開いてはその更新日を見て、更新されているかを確認しています。膨大な数のHPのPDFを1つ1つ開くのが大変なので、「どのページのどのPDFが更新されたかがわかることができれば、あとはそれだけを開いて確認する」という方法ができれば時間短縮できると考えました。

【現在やったこと】市や県のHPで、内容が更新された場合、そのページの上部に更新日が書いてあることが多くそれをウェブスクレイピングするEXCEL VBAで、ページが更新されたことはわかるようにできました。
しかし、そこに保存されている目的のPDFファイルが新しくなったかは、やはり一度開いて見ないとわからない現状です。

例えば、保存しているファイルの名前があって、その名前を保存しておき、ファイルが変わった時にファイル名が変わっていれば、その違いでファイルが更新したことがわかる、とかそんなことができるのでしょうか?
何か他に方法をご存知でしたら教えてください。
↓参考までに、そのページが更新されたかをを知るのに下記のコードを作りました。
開くとこの中にたくさんのPDFがあることがわかります。
もしアイディア等あればご教授ください。

Sub 岡山県()
Dim objIE As InternetExplorer

Call ieView(objIE, "http://www.pref.okayama.jp/page/detail-3445.html")
ThisWorkbook.Sheets(1).Cells(10, 8) = objIE.document.getElementById("content_header").Children(1).innerText

End Sub

'①指定URLを表示するサブルーチン「ieView」
Sub ieView(objIE As InternetExplorer, _
           urlName As String, _
           Optional viewFlg As Boolean = True, _
           Optional ieTop As Integer = 0, _
           Optional ieLeft As Integer = 0, _
           Optional ieWidth As Integer = 600, _
           Optional ieHeight As Integer = 800)

    'IE(InternetExplorer)のオブジェクトを作成する
    Set objIE = CreateObject("InternetExplorer.Application")

    With objIE
        'IE(InternetExplorer)を表示・非表示
        .Visible = viewFlg
        .Top = ieTop  'Y位置
        .Left = ieLeft  'X位置
        .Width = ieWidth  '幅
        .Height = ieHeight  '高さ

        '指定したURLのページを表示する
        .navigate urlName

    End With
    'IE(InternetExplorer)が完全表示されるまで待機
    Call ieCheck(objIE)

End Sub

'②Webページ完全読込待機処理サブルーチン「ieCheck」
Sub ieCheck(objIE As InternetExplorer)

  Dim timeOut As Date

  timeOut = Now + TimeSerial(0, 0, 20)

  Do While objIE.Busy = True Or objIE.readyState <> 4
    DoEvents
    Sleep 1
    If Now > timeOut Then
      objIE.Refresh
      timeOut = Now + TimeSerial(0, 0, 20)
    End If
  Loop

  timeOut = Now + TimeSerial(0, 0, 20)

  Do While objIE.document.readyState <> "complete"
    DoEvents
    Sleep 1
    If Now > timeOut Then
      objIE.Refresh
      timeOut = Now + TimeSerial(0, 0, 20)
    End If
   Loop

End Sub

【アドバイスを受けて試したこと】

Sub 岡山()
Dim objIE As InternetExplorer
Call ieView(objIE, "http://www.pref.okayama.jp/page/detail-3445.html")
ThisWorkbook.Sheets(1).Cells(10, 8) = objIE.document.getElementById("content_header").Children(1).innerText
Call GetLastModified(URL, "http://www.pref.okayama.jp/page/detail-3445.html")
End Sub

Function GetLastModified(URL As String) As String
Dim httpReq As Object
Set httpReq = CreateObject("MSXML2.XMLHTTP")
httpReq.Open "GET", URL, False
httpReq.send

GetLastModified = httpReq.getResponseHeader("Last-Modified")
Set httpReq = Nothing
End Function


知識不足でエラーで動かなかったので
MSXML2.XMLHTTPで検索し、
https://tonari-it.com/excel-vba-http-request/
のサイトと回答者様のアドバイスを参考に以下のコードを作成。

Sub 読み込む()
    Dim GetLastModified As String
    Dim httpReq As Object
    Set httpReq = CreateObject("MSXML2.XMLHTTP")
    httpReq.Open "GET", "http://www.pref.okayama.jp/page/detail-3445.html", False
    httpReq.send
    GetLastModified = httpReq.getResponseHeader("Last-Modified")
    Debug.Print GetLastModified
    Set httpReq = Nothing
End Sub


Wed, 04 Apr 2018 19:04:26 GMT
を出力することができた。

これが意味するところがなんだかわかりません。
おそらく、更新されたものがあるってことなのか?
このページにある全てのPDFについて更新日をチェックするには
どのようにすればいいんでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+6

HTTP ヘッダーに 'Last-Modified: ' がありますので、HTTP ヘッダーを取得して、Last-Modified: をチェックすれば、ファイルの更新日を確認できると思います。
(なお、Last-Modified は、ファイルの中身が変わっていなくても上書き保存してアップロードした場合等に更新される場合もあります。)

確認のために、質問に記載されているURL先の PDF ファイルを curl コマンドで、HTTP レスポンスを確認してみると Last-Modified: が取得できました。

$ curl --head -A "Mozilla/5.0"  http://www.pref.okayama.jp/hoken/seiei/suidou/suido_pdf/03_shoukibo_youryou.pdf

HTTP/1.1 200 OK
Date: Thu, 05 Apr 2018 00:22:10 GMT
Server: Apache
Last-Modified: Fri, 19 Apr 2013 05:40:48 GMT
ETag: "10c65-4dab0293ff800"
Accept-Ranges: bytes
Content-Length: 68709
Connection: close
Content-Type: application/pdf

VBAの場合、MSXML2.XMLHTTP を使うことで、http ヘッダを取得できると思います。参照設定で追加してください。

テストしていませんが、コードとしては、こんな感じでしょうか。(エラーチェックとか入れていないので、URLやファイルがない場合等にエラーが発生すると思いますので、適宜追加してください。)

Function GetLastModified(URL As String) As String
    Dim HttpReq As Object
    Set HttpReq = CreateObject("MSXML2.XMLHTTP")
    HttpReq.Open "GET", URL, False
    HttpReq.send
    GetLastModified = HttpReq.getResponseHeader("Last-Modified")
    Set HttpReq = Nothing
End Function

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/05 10:07

    HTTPヘッダ参照するだけなら、ローカルキャッシュいらないですね。
    勉強になりました。

    キャンセル

  • 2018/04/05 11:13

    CHERRY様
    なんとか出来ることがわかり本当にうれしいです。アドバイスありがとうございます。
    書いてくださったことが、全ては理解できなかったので、自分で新たに検索をして
    コードを書いて、なんとか動きました。どんな文字で検索していいかもわからなかったので、
    本当にありがとうございます。

    教えていただいた内容をもとにプログラムを実行したのですが、
    Wed, 04 Apr 2018 19:04:26 GMT
    という回答がでました(プログラムは質問に追加しました)
    これがこのページのどれの更新日に当るのかがわかりませんでした。

    このページのそれぞれのPDFを指定して、特定のファイルの更新日を取得することは
    できるのしょうか?

    キャンセル

  • 2018/04/05 13:28

    URL で指定したファイルの更新日です。

    URL にhtml ファイルを指定したら htmlファイルの更新日が、pdf ファイルを指定したら pdf ファイルの更新日が取得できます。

    キャンセル

  • 2018/04/06 14:26

    教えていただいた方法で各種ページから更新日を取得できました。本当にありがとうございました。「curl コマンドで、HTTP レスポンスを確認」というのがわからなかったのですが、調べたらVBAでも出来るようで、
    以下のプログラミングでできました。おかげで本件解決できました。ありがとうございます。
    Function HTTPのヘッダーを取得(url As String)

    Dim httpReq As Object
    Set httpReq = CreateObject("MSXML2.XMLHTTP")

    Call httpReq.Open("POST", url, False, user, Password)
    Call httpReq.setRequestHeader("Content-Type", "application/json;charset=utf-8")
    Call httpReq.setRequestHeader("User-Agent", "fuga")

    Dim postData As Variant
    postData = "name=hoge&body=piyo"

    Call httpReq.send(postData)
    Dim respData As String
    If httpReq.Status = 200 Then
    respData = httpReq.getAllResponseHeaders
    MsgBox respData
    End If
    End Function

    キャンセル

+3

似たようなスクレイピングをやったことがあります。

どのPDFが更新されたかがわかることができれば

ローカルにいったんPDFをダウンロードしておき、MD5やSHAのハッシュ値を計算して、その値が変わっていたら内容が更新されたと判断する、みたいにすればいいのかなと思います。

http://www.atmarkit.co.jp/ait/articles/0507/30/news017.html
Windowsで標準で付属しているcertutilを使うのがよさそうです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/05 11:56 編集

    ハッシュで、、、と思ったらすでに回答されていましたので、こちらに関連情報をコメント。
    [Excel VBA で SHA256](https://qiita.com/nobu-maple/items/ac0094a226e1d7d25ec3)

    キャンセル

  • 2018/04/06 09:26

    回答ありがとうございます。全くしらない事がだったんですが、調べてみると、ファイルの比較できるみたいですね。ちょっとまだ理解ができてないのですが、調べてみて挑戦してみます。
    ありがとうございました。

    キャンセル

+1

元のPDFがあるなら、両方のPDFをバイナリ形式で読込んで、
差異があるかをチェックすればいいんじゃないかなぁ。

どこかに差異があるなら、更新されたということになるので、
自分のDiffツールでは、差分を抽出する前に、
先に差異がそもそもあるのかどうかをチェックする為に処理してます。
※PDFでも同様にバイナリ形式で読込めたので、チェック可能かと。

また、探せばVBAでPDFからテキストを抽出できそうなので、
テキストファイルをWinMerge等になげれば、
何が変わったかもすぐに分かるようになるでしょう。
http://hansuke.net/excel-vba-pdf-text 
※PDF テキスト抽出 VBA で検索

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/06 09:25

    ファイル自体を比較することができるんですね。今後使えそうなので、いろいろと調べてやってみます。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.19%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる