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

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

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

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

Q&A

2回答

2162閲覧

効率がわるいのか?処理が間に合わない。mechanizeを用いてのRubyスクレイピング,CSVで保存

famlwrem

総合スコア11

Ruby

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

0グッド

1クリップ

投稿2014/09/25 08:36

原因は#ほんとは上記コメントアウトの2行を加えたいのですが、処理が追いつかないのかな?下に記しました
のコード辺りだと思うのですが、効率のいい書き方(全体的に)がありましたらご教授お願いします。

エラー概要
xmlXPathCompOpEval: function content not found (RuntimeError)

lang

1#coding : utf-8 2require 'kconv' 3require 'open-uri' 4require 'mechanize' 5require 'csv' 6 7agent = Mechanize.new 8header = ["会社名","メールアドレス","代表者名","所在地","TEL","FAX"] 9CSV.open("XXX.csv","w", :headers => header, :write_headers => true) do |csv| 10 #47都道府県 11 for num in 1..47 do 12 if num < 2 then 13 pi = 1 14 elsif num < 8 then 15 pi = 2 16 elsif num < 15 then 17 pi = 3 18 elsif num < 25 then 19 pi = 4 20 elsif num < 31 then 21 pi = 5 22 elsif num < 36 then 23 pi = 6 24 elsif num < 40 then 25 pi = 7 26 else num < 48 27 pi = 8 28 end 29 url = "http://XXXXXXXXXXXXX" + pi.to_s + "&pref_id=" + num.to_s 30 31 html = open(url,"r:EUC-JP") 32 page = Nokogiri.HTML(html,nil,"EUC-JP") 33 count = 0 34 @company = [] 35 #1ページに30社 36 while count < 30 do 37 #個別会社ページの要素を1つずつ取得 38 page.search(".mini2+ .mini2 a").each do |kaisya_search| 39 sleep(1) 40 count += 1 41 kaisya_url = kaisya_search[:href] 42 kaisya_html = open(kaisya_url,"r:EUC-JP") 43 kaisya_page = Nokogiri.HTML(kaisya_html,nil,"EUC-JP") 44 #tr:nth-child(1)もしくはtr:nth-child(3)のCSS3にメールアドレス 45 valid_address = /[\w\d_-]+@[\w\d_-]+.[\w\d._-]+/ 46 mail_address = kaisya_page.search('tr:nth-child(1) a').text 47 if valid_address =~ mail_address 48 @company.push(kaisya_search.text.toutf8) 49 @company.push(kaisya_page.search('tr:nth-child(1) a').to_s.scan(/[\w\d_-]+@[\w\d_-]+.[\w\d._-]+/)[1]) 50 @company.push(kaisya_page.search('.grid-7 tr:nth-child(2) td').text) 51 @company.push(kaisya_page.search('.grid-7 tr:nth-child(3) td').text) 52 #@company.push(kaisya_page.search('.grid-7 tr:nth-child(4) td').text) 53 #@company.push(kaisya_page.search(':content("ファックス")+ td').text) 54 55 #ほんとは上記コメントアウトの2行を加えたいのですが、処理が追いつかないのかな?下に記しました 56 57 else 58 @company.push(kaisya_search.text.toutf8) 59 @company.push(kaisya_page.search('tr:nth-child(3) a').to_s.scan(/[\w\d_-]+@[\w\d_-]+.[\w\d._-]+/)[1]) 60 @company.push(kaisya_page.search('tr:nth-child(4) .standard').text) 61 @company.push(kaisya_page.search('tr:nth-child(6) .standard').text) 62 #@company.push(kaisya_page.search('td td tr:nth-child(8) .standard').text) 63 #@company.push(kaisya_page.search('tr:nth-child(10) .standard').text) 64 65 #同上 66 67 end 68 csv << @company.to_a.pop(4)#daihyousya,syozaichi,tel,fax, 69 #次のページに移動、 70 if count == 30 71 unless page.search("span+ a").empty? 72 next_30_url = page.search("span+ a")[0][:href] 73 next_30_html = "http://www.akabou.ne.jp/" + next_30_url 74 next_html = open(next_30_html,"r:EUC-JP") 75 page = Nokogiri.HTML(next_html,nil,"EUC-JP") 76 count = 0 77 sleep(1) 78 end 79 end 80 end 81 end 82 end 83end

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

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

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

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

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

guest

回答2

0

xmlXPathCompOpEval: function content not found (RuntimeError)
というエラーで検索してもズバリのものが見付からなかったのですが、パーサ Nokogiri が内部で使っているライブラリ libxml2 に関連するエラーのようです。
想像するに、 Nokogiri でパースするために kaisya_page.search で指定しておられる css が正しくないのでは、と思います。
(クロール対象のサイトが分からないですし、おそらく認証が必要なサイトなのでは、と想像していますので指摘も出来ませんが。また agent が宣言されつつ内部で全く使われていないのは、公開できないところで使っているのかなと思ったりしました。)
その他ですが、

  • 都道府県コードと思われる num を if 節で分岐しておられますが、case〜when〜else〜end を使う方が見やすいかなと思います。
  • ローカル変数 csv に代入するときに @company に push したものをまとめて pop しておられますが、余計に読みづらいのではないかと思いました。コメントに #daihyousya,syozaichi,tel,fax, と書くのであれば、 @company の代わりにそれらを変数名にして使えばいいのではないかと。
  • インデントレベルが乱れてますので誤読しかねません。

あまり回答になってない気もしますが、公開情報が限られていますのでこれぐらいになりました。
お役に立てば幸いです。

投稿2014/09/25 16:01

riocampos

総合スコア241

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

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

0

例示されたコードですが、すこし読みづらいとおもったので、書き換えてみました。(本題と関係なくてゴメンナサイ)

https://gist.github.com/gouf/ec880c381d4b606b522e

  • 処理の塊に名前を付けてあげる(関数に書き出す)
  • 重複を排除する
  • インデントレベルが深くなっているのところを浅くする
  • for やwhile はなるべく使用しない

このあたりを意識して書くと、読み易いコードが書けるように思います。

投稿2014/09/26 04:21

gouf

総合スコア2321

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問