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

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

ただいまの
回答率

90.12%

mechanizeでHTMLframeのsrc属性のファイルをダウンロードしたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,045

dlrowolleh

score 118

前提・実現したいこと→ファイルを取得して保存したい。

あるウェブサイトからファイルを取得したいと考えています。
ファイルは一時間ごとに更新されるため、ファイル名も年月日時間で変化します。
Rubyでファイルをダウンロードし、指定したディレクトリに保存させたいです。

mechanize.rb

をcronに登録し、時間になると実行して、ダウンロードさせたいと思っています。

試したこと

#download.rb
# URLにアクセスするためのライブラリの読み込み                                                                                  
require 'open-uri'

# スクレイピング先のURL
url = 'http://example.com/DataList.php?MstCode=01234567'
# user_agentの設定
user_agent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36'
charset = nil 
html = open(url, "User-Agent" => user_agent) do |f| 
  charset = f.charset # 文字種別を取得
    f.read
    end

# 取得したhtmlを全て表示する
    puts html


を実行しました。

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<title>文字化けしている</title>
</head>
<frameset rows="180,*" cols="*" frameBorder="0">
        <frame name="Titke" src="DataListTitle.php?MstCode=01234567&Time=yyyymmddhhの形式" scrolling="no">
        <frame name="Hyou" src="DataListHyou.php?MstCode=01234567&Time=yyyymmddhhの形式" scrolling="yes">
</frameset>
<noframes></noframes>
</html>


と表示されました。
保存したいファイルは、

DataListHyou.php?MstCode=01234567&Time=yyyymmddhhの形式

です。
保存したい場所は、

/home/(ユーザ名)/Desktop/ファイル

です。

また、文字化けにも対応したいです。
プログラムをどのように修正すればいいでしょうか。
何卒よろしくお願いします。

補足情報(言語/FW/ツール等のバージョンなど)

Ubuntu15.10
Ruby2.2.4です。

追記

ファイル名はそのままで保存したいです。
保存したい場所は

home/(ユーザ名)/Desktop/ファイル

です
Mechanize::File - Seesaa Wiki(ウィキ)を参考にしたのですが、うまくいきませんでした。

  require "mechanize"                                                                                                             
  agent = Mechanize.new
  agent.user_agent_alias = "Windows Chrome"

  url = "http://soramame.taiki.go.jp/DataList.php?MstCode=34204520"

  page = agent.get(url)
     page.root.xpath("//frame").each do |frame|
      if frame["name"] == "Hyou"
      frame_url = frame["src"]
          frame_page = agent.get(frame_url)
      "frame_page.body を 目的のファイルに書き込み"
          path = "/home/ユーザ名/Desktop/file "
          filename = path
          save_as(filename)
          end
          end

          puts page.body.force_encoding(page.encoding).encode("utf-8")

$ ruby mechanize.rb 

と実行したところ

mechanize.rb.rb:15:in `block in <main>': undefined method `save_as' for main:Object (NoMethodError)
    from /home/(ユーザ名)/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/nokogiri-1.6.8.1/lib/nokogiri/xml/node_set.rb:187:in `block in each'
    from /home/(ユーザ名)/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/nokogiri-1.6.8.1/lib/nokogiri/xml/node_set.rb:186:in `upto'
    from /home/(ユーザ名)/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/nokogiri-1.6.8.1/lib/nokogiri/xml/node_set.rb:186:in `each'
    from mechanize.rb:8:in `<main>'


と表示されました。

また、

  require "mechanize"                                                                                                             

  agent = Mechanize.new

      agent.user_agent_alias = "Windows Chrome"
      url = "http://example.com/DataList.php?MstCode=01234567"
      page = agent.get(url)

          page.root.xpath("//frame").each do |frame|
          if frame["name"] == "Hyou"
          frame_url = frame["src"]
              frame_page = agent.get(frame_url)
          "frame_page.body を 目的のファイルに書き込み"
          end

      p frame_page
      puts frame_page
  end


では、

$ ruby mechanize.rb 

nil

#<Mechanize::Page
 {url
  #<URI::HTTP http://example.com/DataList.php?MstCode=01234567>}
 {meta_refresh}
 {title "ホームページ"}
 {iframes}
 {frames}
 {links}
 {forms
  #<Mechanize::Form
   {name "Form1"}
   {method "GET"}
   {action ""}
   {fields [hidden:0x2ab59e31d368 type: hidden name: Err value: ]}
   {radiobuttons}
   {checkboxes}
   {file_uploads}
   {buttons}>}>

#<Mechanize::Page:0x00556b3c27c700>


となります。

やりたいこと、させたい動作はイメージできますが、やり方等知識が圧倒的に不足しています。
知恵をお貸しいただけないでしょうか。
よろしくお願いしたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2016/11/16 06:55

    こちらの質問が他のユーザから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 1

checkベストアンサー

+1

こんな感じでしょうか。Mechanize gemを使います。

require "mechanize"
agent = Mechanize.new
agent.user_agent_alias = "Windows Chrome"

url = "目的のURL"

page = agent.get(url)
page.root.xpath("//frame").each do |frame|
  if frame["name"] == "Hyou"
    frame_url = frame["src"]
    frame_page = agent.get(frame_url)
    open("/home/~~~~","w"){|f| f.write frame_page.body} # euc-jpのままで書く場合
    open("/home/~~~~","w"){|f| f.write frame_page.body.force_encoding(frame_page.encoding).encode("utf-8")} # utf-8に変換して書く場合
  end
end

puts page.body.force_encoding(page.encoding).encode("utf-8")

取得したHTMLファイルのエンコーディングをutf-8に変換して保存したい場合は、最終行を参考にしてください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/11/17 21:02

    ご回答いただきありがとうございます。
    >ファイル名を決めてopenしてwriteしてください。
    とのことですが、
    http://seesaawiki.jp/ruby_mechanize/d/Mechanize%3A%3AFile#filename=
    を参考にしてみたのですが、うまくいきませんでした。
    参考になるページ等ありましたらご教授いただけないでしょうか

    キャンセル

  • 2016/11/17 21:22

    ええと、自分でRubyプログラムを書く能力がゼロということでしょうか?
    回答を書き直しておきました。
    プログラムを書こうと思ったら、まずその言語に「入門」したほうがいいですよ。

    キャンセル

  • 2016/11/29 20:16

    ご回答いただきましてありがとうございます。
    回答を読ませて頂いておりましたが、なかなか理解できず、ご連絡が遅れて失礼しました。
    プログラムはうまく動作しました。
    初めは指定したディレクトリに目的のファイルをダウンロードして
    ため込んでいこう(名前を付けて保存のようなこと)と思っていたのですが、
    今回のケースでは、目的のファイルのデータは文字列なので
    このやり方のように一つのファイルに
    目的のファイルのデータを追記していったほうが、
    ほしいデータだけを抜き出そうとする際等
    管理が楽になりそうで良いと思いました。
    大変勉強になりました。
    ≫言語に「入門」したほうがいい
    やりたいことがイメージできても(目的があっても)手段を知らないと
    何もできないことを身をもって感じました。
    大変勉強になりました。
    心からお礼申し上げます。

    キャンセル

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

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