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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSS

RSS(Really Simple Syndication)はブログのエントリやニュースの見出し、標準のフォーマットの音声やビデオなどを発行するために使われるウェブフィードのフォーマットの集合体です。

Q&A

解決済

1回答

3494閲覧

Rubyでクローラーの作成

nazo_o

総合スコア99

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSS

RSS(Really Simple Syndication)はブログのエントリやニュースの見出し、標準のフォーマットの音声やビデオなどを発行するために使われるウェブフィードのフォーマットの集合体です。

0グッド

0クリップ

投稿2016/09/15 23:54

"Rubyによるクローラー開発技法"という本を見ながら簡易クローラーを作成しているのですが、うまくいきません。

Ruby

1# -*- coding: utf-8 -*- 2require 'cgi' 3require 'open-uri' 4require 'rss' 5require 'kconv' 6require 'webrick' 7 8class Site 9 def initialize(url:"", title:"") 10 @url, @title = url, title 11 end 12 attr_reader :url, :title 13 14 def page_source 15 @page_source ||= open(@url, &:read).toutf8 16 end 17 18 def output(formatter_klass) 19 formatter_klass.new(self).format(parse) 20 end 21end 22 23class SbcrTopics < Site 24 def parse 25 dates = page_source.scan(%r!(\d+)年 ?(\d+)月 ?(\d+)日<br />!) 26 url_titles = page_source.scan(%r!^<a href="(.+?)">(.+?)</a><br />!) 27 url_titles.zip(dates).map{|(aurl, atitle), 28 ymd|[CGI.unescapeHTML(aurl), 29 CGI.unescapeHTML(atitle), Time.local(*ymd)] 30 } 31 end 32end 33 34class Formatter 35 def initialize(site) 36 @url = site.url 37 @title = site.title 38 end 39 attr_reader :url, :title 40end 41 42class TextFormatter < Formatter 43 def format(url_title_time_ary) 44 s = "Title: #{title}\nURL: #{url}\n\n" 45 url_title_time_ary.each do |aurl, atitle, atime| 46 s << "* (#{atime})#{atitle}\n" 47 s << " #{aurl}\n" 48 end 49 s 50 end 51end 52 53class RSSFormatter < Formatter 54 def format(url_title_time_ary) 55 RSS::Maker.make("2.0") do |maker| 56 maker.channel.updated = Time.now.to_s 57 maker.channel.link = url 58 maker.channel.title = title 59 maker.channel.description = title 60 url_title_time_ary.each do |aurl, atitle, atime| 61 maker.items.new_item do |item| 62 item.link = aurl 63 item.title = atitle 64 item.updated = atime 65 item.description = atitle 66 end 67 end 68 end 69 end 70end 71 72class RSSServlet < WEBrick::HTTPServlet::AbstractServlet 73 def do_GET(req, res) 74 klass, opts = @options 75 res.body = klass.new(opts).output(RSSFormatter).to_s 76 res.content_type = "application/xml; charset=utf-8" 77 end 78end 79 80def start_server 81 srv = WEBrick::HTTPServer.new(:BindAddress => '127.0.0.1', :Port => 7777) 82 srv.mount('/rss.xml', RSSServlet, SbcrTopics, 83 url:"http://scrawler.sbcr.jp/samplepage.html", 84 title:"WWW.SBCR.JP トピックス") 85 # 場合によってはsrv.mount行を追加する 86 trap("INT"){ srv.shutdown } 87 srv.start 88end 89 90if ARGV.first == 'server' 91 start_server 92else 93 site = SbcrTopics.new( 94 url:"http://crawler.sbcr.jp/samplepage.html", 95 title:"WWW.SBCR.JP トピックス") 96 case ARGV.first 97 when "rss-output" 98 puts site.output RSSFormatter 99 when "text-output" 100 puts site.output TextFormatter 101 end 102end

コードは以上の通りです。

これを実行(ruby rssserver2.rb server)した状態で、ブラウザにてhttp://127.0.0.1:7777/rss.xmlに移動して見ると、

Internal Server Error

getaddrinfo: nodename nor servname provided, or not known

のように表示され、予想していたRSSの画面になりません。

何が原因なのでしょうか?わかる方がいらっしゃいましたら、ご教授宜しくお願い致します。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

結論

簡単なスペルミスが原因です。
http://scrawler.sbcr.jp/samplepage.html
http://crawler.sbcr.jp/samplepage.html

該当部分

ruby

1def start_server 2 srv = WEBrick::HTTPServer.new(:BindAddress => '127.0.0.1', :Port => 7777) 3 srv.mount('/rss.xml', RSSServlet, SbcrTopics, 4 url:"http://scrawler.sbcr.jp/samplepage.html", 5 title:"WWW.SBCR.JP トピックス") 6 # 場合によってはsrv.mount行を追加する 7 trap("INT"){ srv.shutdown } 8 srv.start 9end

こちらの「scrawler.sbcr.jp」を「crawler.sbcr.jp」に直せば動きます。

詳細な説明

上記の通りなので、こちらは蛇足ですが原因を自分で調査できるようになって欲しいので
エラーの原因の特定の仕方を書いておきますね。

※以下の説明は、まだスペルミスとは分かっていない、
ソースコードが正しく記載されているという前提の元で調査している状態で書いたものです。

実行環境が書いていないので、分からないのですが、
CentOS6で実行してみました。
掲載してもらったコードをcrawler_sample.rbとして保存したものと思ってください。
同じように実行してみました。

まず実行してみました。

(1) サーバーを起動(ターミナル1)

bash

1$ ruby crawler_sample.rb server 2[2016-09-16 10:56:34] INFO WEBrick 1.3.1 3[2016-09-16 10:56:34] INFO ruby 2.3.1 (2016-04-26) [x86_64-linux] 4[2016-09-16 10:56:34] INFO WEBrick::HTTPServer#start: pid=42224 port=7777

(2) 別のターミナルで rss.xmlにアクセス(ターミナル2)

bash

1 wget http://127.0.0.1:7777/rss.xml 2--2016-09-16 10:57:02-- http://127.0.0.1:7777/rss.xml 3Connecting to 127.0.0.1:7777... connected. 4HTTP request sent, awaiting response... 500 Internal Server Error 52016-09-16 10:57:02 ERROR 500: Internal Server Error.

(3) ターミナル1でエラーが表示される

bash

1[2016-09-16 10:56:34] INFO WEBrick 1.3.1 2[2016-09-16 10:56:34] INFO ruby 2.3.1 (2016-04-26) [x86_64-linux] 3[2016-09-16 10:56:34] INFO WEBrick::HTTPServer#start: pid=42224 port=7777 4[2016-09-16 10:57:02] ERROR OpenURI::HTTPError: 404 Not Found 5 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:359:in `open_http' 6 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:737:in `buffer_open' 7 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:212:in `block in open_loop' 8 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:210:in `catch' 9 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:210:in `open_loop' 10 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:151:in `open_uri' 11 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:717:in `open' 12 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/open-uri.rb:35:in `open' 13 crawler_sample.rb:15:in `page_source' 14 crawler_sample.rb:25:in `parse' 15 crawler_sample.rb:19:in `output' 16 crawler_sample.rb:75:in `do_GET' 17 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/webrick/httpservlet/abstract.rb:107:in `service' 18 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/webrick/httpserver.rb:140:in `service' 19 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/webrick/httpserver.rb:96:in `run' 20 /home/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/webrick/server.rb:296:in `block in start_thread' 21127.0.0.1 - - [16/Sep/2016:10:57:02 JST] "GET /rss.xml HTTP/1.0" 500 293 22- -> /rss.xml

原因について

(3)のエラーを見ると、「ERROR OpenURI::HTTPError: 404 Not Found」となっていますので、
どこかのページが存在しないという事が分かります。
見るべきところは、コマンドライン引数に「server」を受け取って処理しているところです。
つまり、この部分になります。

ruby

1def start_server 2 srv = WEBrick::HTTPServer.new(:BindAddress => '127.0.0.1', :Port => 7777) 3 srv.mount('/rss.xml', RSSServlet, SbcrTopics, 4 url:"http://scrawler.sbcr.jp/samplepage.html", 5 title:"WWW.SBCR.JP トピックス") 6 # 場合によってはsrv.mount行を追加する 7 trap("INT"){ srv.shutdown } 8 srv.start 9end

この時点でなんとなく予想がついているかもしれませんが、
このソースは、http://127.0.0.1:7777/rss.xml というアクセスに対して、
http://scrawler.sbcr.jp/samplepage.html の内容をRSSとして表示しようとしています。
という事は、http://scrawler.sbcr.jp/samplepage.html が存在しないのではないか?と予想できます。
もちろん実際に、ブラウザでアクセスすると見ることができませんので、これが原因です。

全体のソースコードのほかの部分を見てみると、似たようなURLを書いてある箇所があります。

ruby

1if ARGV.first == 'server' 2 start_server 3else 4 site = SbcrTopics.new( 5 url:"http://crawler.sbcr.jp/samplepage.html", 6 title:"WWW.SBCR.JP トピックス") 7 case ARGV.first 8 when "rss-output" 9 puts site.output RSSFormatter 10 when "text-output" 11 puts site.output TextFormatter 12 end 13end

こちらでは、
http://scrawler.sbcr.jp/samplepage.html ではなく、
http://crawler.sbcr.jp/samplepage.html と書かれています。
こちらはブラウザで見る事が出来ます。

なので、打ち間違いで、crawler.sbcr.jp を scrawler.sbcr.jpと書いてしまっていた事が分かりました。
先ほどの部分をcrawler.sbcr.jpに修正すればOKです。

投稿2016/09/16 02:23

mingos

総合スコア4025

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nazo_o

2016/09/16 14:58

とてもわかりやすい説明をありがとうございます! 頑張ります!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問