SlideShare a Scribd company logo
実践スクレイピング
       不条理な現実との折り合いの付け方




ふるかわだいすけ/mogya.com
ふるかわだいすけ

フリーランスWEBエンジニア


            http://mogya.com/
            http://mogya com/
            Twitter: @mogya



     自己紹介
ふるかわだいすけ

フリーランスWEBエンジニア



            http://maidmail.jp/


     自己紹介
http://oasis.mogya.com/


モバイラーズオアシス
http://oasis.mogya.com/


携帯/スマートフォン対応
実践スクレイピング



  今日のテーマ
はじめてのスクレイピング
・Hpricot
 X th
・Xpath
・店名を取ってみる
実践スクレイピング
・1ページに全部入っている場合
 id
・id=xxx方式
        方式
・一覧ページ→詳細ページ
・「次へ」対応
 「次へ 対応
現実のスクレイピング
まとめ


          目次
photo by Big Ben(Gaijin Bikers)




はじめてのスクレイピング
例えばこんなページ
    http://www.mcdonalds.co.jp/shop/map/map.php?strcode=01570
こうなっているところから
      http://www.mcdonalds.co.jp/shop/map/map.php?strcode=01570
require 'rubygems'
require 'hpricot'
require 'open-uri'
url =
'http://www mcdonalds map php?strcode=01570'
 http://www.mcdonalds…map.php?strcode=01570
page = Hpricot( open(url).read );nil
page sea c ( S op a e 3 )
page.search(".Shopname h3").inner_te t
                                 e text




            店名を取ってみる
Hpricot
  • HTMLパーサー
  • xpathでHTMLから切り出しができる




               Hpricot
page = Hpricot( open(url).read )
page.search(".Shopname h3").inner_text



                           “body div h1”




                           “div#Content1
                           “di #C t t1 h1”




                                 “.content title”
                                  .content_title
                                  (page/".content_title")[0].inner_text



        XPath(XML Path Language)
/html/body/table/tbody/tr[3]/td/
              勝手にtbodyとか補足する点に注意


Firebugを使うとラクチン
        http://www.mcdonalds.co.jp/shop/map/map.php?strcode=01570
require 'rubygems'
require 'hpricot'
require 'open-uri'
         open-uri
url =
'http://www.mcdonalds・・・map.php?strcode=01570'
page = Hp icot( open( l) ead ) nil
        Hpricot( open(url).read );nil
page.search(".Shopname h3").inner_text




               店名を取ってみる
page = Hpricot( open(url).read )
↓
page = Hpricot( open(url).read );nil

                     irbの場合
userAgent =
  "mogya scraper under construction. ”+
  ”you can contact me at mogya+scraper@mogya.com"
page = Hpricot( open(_url, "User-Agent" => userAgent ).read )




          連絡がつくようにしておく
Require “kconv”
userAgent =
  "mogya scraper under construction. ”+
  ”you can contact me at mogya+scraper@mogya.com"
page = Hpricot( open(url, "User-Agent" => userAgent ).read.toutf8 )



                      ※読みにくいので、以降のサンプルでは省略しました




                  文字コードの問題
• Aj でデ タを動的ロ ド
  Ajaxでデータを動的ロード
   →スクレイピングだとデータが取れない
• JSの読み出し元を見ればいいんじゃね?
•ブラウザでアクセスしてみる
   →403 forbidden
•以降、サイトまるごと403 forbiddenになった
   →「本気だ!」




                         ※このデザインになる前の話


         余談:防衛反応
                  http://www.mcdonalds.co.jp/shop/map/map.php?strcode=01570
photo by Big Ben(Gaijin Bikers)




実践スクレイピング
http://www.burgerkingjapan.co.jp/locations/




1ページに全部入っている場合
                                                 http://www.first-kitchen.co.jp/shop/
バーガーキング
      http://www.burgerkingjapan.co.jp/locations/
require 'rubygems'
     i ' b         '
require 'hpricot'
require 'open-uri'
url = 'htt //
  l 'http://www.burgerkingjapan.co.jp/locations/'
                    b   ki j         j /l ti   /'
page = Hpricot( open(url).read );nil

page.search( li dl ).each{|part|
page search(".li dl") each{|part|
   p part.search("dd h4 a").inner_text
}




                     バーガーキング
                                              http://www.burgerkingjapan.co.jp/locations/
id=xxxx方式
     http://www.mcdonalds.co.jp/shop/map/map.php?strcode=01578
require 'rubygems'
require 'hp icot'
 eq i e 'hpricot'
require 'open-uriʻ
url_template
url template =
     'http://www.mcdonalds ・・・ strcode=%05i'
0.upto(10000){|i|
       url = sprintf(url_template,i)
       page = Hpricot( open(url).read );nil
       p page search(" Shopname h3") inner text
         page.search(".Shopname h3").inner_text
       sleep 3
}



                 id=xxxx方式
                          http://www.mcdonalds.co.jp/shop/map/map.php?strcode=01578
新店舗情報を見ると idのmax値がわかることが多い
新店舗情報を見ると、idのmax値がわかることが多い



  id=xxxx方式
         http://www.mcdonalds.co.jp/shop/map/map.php?strcode=01578
飛び飛びで見て最低値を推測

0.step(10000,100){|i|
        url = sprintf(url template i)
              sprintf(url_template,i)
        page = Hpricot( open(url).read );nil
        p "#{url}:"+page.search(".Shopname h3").inner_text
        sleep 3
}




                        id=xxxx方式
飛び飛びで見て最低値を推測

0.step(10000,100){|i|
        url = sprintf(url template i)
              sprintf(url_template,i)
        page = Hpricot( open(url).read );nil
        p "#{url}:"+page.search(".Shopname h3").inner_text
        sleep 3
}




                        id=xxxx方式
一覧ページ→詳細ページ
        http://www.bagus-99.com/company/shop.html
一覧ページ→詳細ページ
        http://www.bagus-99.com/company/shop.html
require 'rubygems'
  q         yg
require 'hpricot'
require 'open-uri'
archive_url = 'http://www.bagus-99.com/netcafe/store/'
archive_page = Hpricot( open(archive_url).read );nil
archive_page.search("td.darker2/a").each{|url_part|
      url = archive_url + url_part['href']
      page = Hpricot( open(url).read ) il
                   i (      ( l)     d );nil
         以下略
      sleep 1
}




             一覧ページ→詳細ページ
                                                http://www.bagus-99.com/company/shop.html
「次へ」対応
         http://www.mapion.co.jp・・・search=mapAreabtn
「次ページへ」がある時




「次ページへ」がない時
 次ペ ジへ」がない時




XPATHではムリ!




              「次へ」対応
                       http://www.mapion.co.jp・・・search=mapAreabtn
def parse(url)
    p     ( )
        page = Hpricot( open(url).read )
        page.search(".address").each{|part|
           p part.search("h2").inner_text
        }
        next_url =
           (page.inner_html.scan(
             /HREF="(.*)"><strong>次ページへ/
             /        "( *)"            次    ジ /
           )[0][0]) rescue nil
        if (next_url)
           parse("http://www.mapion.co.jp"+next_url)
                 ("htt //            i     j "+  t l)
        end
end

url = “http://www.mapion.co.jp/c/f?・・・admi3=13101・・・"
parse(url)




                      「次へ」対応
                                              http://www.mapion.co.jp・・・search=mapAreabtn
photo by Big Ben(Gaijin Bikers)




現実のスクレイピング
現実1:データ大杉
       http://www.doutor.co.jp/shopsearch/index.html#
→ 47回回せばOK?

現実1:データ大杉
            http://www.mapion.co.jp・・・BT=all
現実1:データ大杉
            http://www.mapion.co.jp・・・BT=all
URLをじーっと眺めると。
1.東京都の各エリア
http://www.mapion.co.jp/c/f?・・・&admi2code=13&BT=all&admi3=13101&search.x=15&search.y=8
http://www mapion co jp/c/f?   &admi2code 13&BT all&admi3 13101&search x 15&search y 8
http://www.mapion.co.jp/c/f?・・・&admi2code=13&BT=all&admi3=13102&search.x=25&search.y=5
:
2.それ以外の県
  . れ以外 県
http://www.mapion.co.jp/c/f?・・・&admi2code=40&mx=100&vp=10&BT=all
http://www.mapion.co.jp/c/f?・・・&admi2code=41&mx=100&vp=10&BT=all



→2パターンに分けてスクレイピング
      に分        グ




                       対処1:地道に対応
Flashの検索フォーム
                                    検索




現実2:強敵Flash
      http://sp.chizumaru.com/dbh/lotteria/top.aspx?account=lotteria
Flashの検索フォーム
                                    検索




現実2:強敵Flash
      http://sp.chizumaru.com/dbh/lotteria/top.aspx?account=lotteria
現実2:強敵Flash
              http://sp.chizumaru.com/・・・&arg=
http://sp.chizumaru.com/dbh/lotteria/detailmap.aspx?accou
nt=lotteria&accmd=0&arg=&c1=&c2=&c3=&c4=&c5=&c6=
&c7 &c8 &c9 &c10 &c11 &c12 &c13 &c14 &c15 &c16
&c7=&c8=&c9=&c10=&c11=&c12=&c13=&c14=&c15=&c16
=&c17=&c18=&c19=&c20=&c21=&c22=&c23=&c24=&c25
=&c26=&c27=&c28=&c29=&c30=&mode=11&key=&pg=1&
                    ad &b d
                    adr=&bid=113106
                                3 06

                                                 6桁とかw


      現実2:強敵Flash
                      http://sp.chizumaru.com/dbh/lotteria/detailmap.aspx・・・bid=113106
http://sp.chizumaru.com/dbh/lotteria/detailmap.aspx?accoun
                  t=lotteria&bid=113106




      現実2:強敵Flash
鉄壁!
・ページリスト:取れない(Flashだから)
・一覧ページのURL:取れない
      (座標指定なのでパターンを読めない)
・個別ページ:id多すぎ




         現実2:強敵Flash
対応:偶然発見!
http://www.pronto.co.jp/solare/
          注)BGMが鳴ります




現実3:強敵Flash2
数が少ないので手作業で片付けましたw




     対策3:あきらめる
余談:渡る世間に鬼はなし
               http://www.manboo.co.jp/
余談:渡る世間に鬼はなし
               http://www.manboo.co.jp/
現実4:Tableレイアウト
現実4:Tableレイアウト
XPATHがこんなふうになる
 page.search("/html/body/table/tr[3]/td/table/tr/td/table/tr/td[2]/tab
 le/tr[3]/td/table/tr[3]/td/table/tr/td/table/tr/td/a )
 le/tr[3]/td/table/tr[3]/td/table/tr/td/table/tr/td/a”)

ひどい場合、そもそもXPATHで表現できないことも


対応
 ・1カ所くらいclassがついていることもある
 ・FireBugで何とかなる間はなんとかする
 ・どうにもならない時は、正規表現で取得




           現実4:Tableレイアウト
現実5:InvalidなHTML
現実5:InvalidなHTML
問題:xpathで読めなくなってしまう
対策:読み込んだタイミングで直してしまう

page =
  Hpricot(
  H i t(
    open(url).read.gsub(
        "</script>¥n<body>","</script>¥n“
         </script>¥n<body> </script>¥n
    )
  );nil




         対策:アドホックに直す
th便利
・xpath便利
・スクレイピングは個別対応の嵐
 スクレイピングは個別対応の嵐
・validなHTMLを書きましょう




         まとめ
おしまい
おしまいだってば!
もうないよ!
時間があまった?
じゃあしょうがない
About
モバイラーズオアシス
モバイラ ズオアシス


    おまけ
「情報はどこから?」
 情報はどこから?」




  よくいただく質問
こたえ
ブログ
・・・正直ムリ(><)
twitter
• t itt で「電源 OR コンセント -切」をwatch
  twitterで「電源    ンセント 切 を t h
• 99%はどうでもいい話だけど、
    高速で読み飛ばせるので対応可能
• 敵はbotと診断メーカー




               twitter
• t itt で「電源 OR コンセント -切」をwatch
  twitterで「電源    ンセント 切 を t h
• 99%はどうでもいい話だけど、
    高速で読み飛ばせるので対応可能
• 効能
   •電源情報収集
   •宣伝
   •SEO
    顧客の声を聞く
   •顧客の声を聞く




               twitter
on ExpressionEngine




   バックエンド
管理をCMSに投げる
システム構成
• Ce tOS5 3
  CentOS5.3
• Apache2.2.3
• E pressionEngine v.1.6.4
  ExpressionEngine 1 6 4
• MySQL 5.0
• jQuery 1.3.2
         132
• GoogleMapsAPI




               システム構成
システム構成
                        ee_Net_UserAgent_Mobile
                        ee Net UserAgent Mobile
通常のリクエスト
通常 リク  ト
           Expression   spot_search
結果ページの       Engine
リクエスト



                            DB
検索クエリ      Search.php




           システム構成

More Related Content

PDF
Tour of Scraping
PPTX
Webクローリング&スクレイピングの最前線 公開用
PDF
45分で理解する webクローリング入門 斉藤之雄
PPTX
MongoDB World 2014に行ってきた!
PDF
Introduction to MongoDB
PPT
「ネット家電」の別名を歴史から考えてみた
PDF
Anemoneによるクローラー入門
PPTX
ウェブから情報をあつめる
Tour of Scraping
Webクローリング&スクレイピングの最前線 公開用
45分で理解する webクローリング入門 斉藤之雄
MongoDB World 2014に行ってきた!
Introduction to MongoDB
「ネット家電」の別名を歴史から考えてみた
Anemoneによるクローラー入門
ウェブから情報をあつめる

What's hot (20)

PDF
はじめてのモバイルウェブアプリ 3 SPARQLハンズオン オープンデータ水位ゲーム
PDF
MongoDBの使い方
PDF
20150209 甲府-web新世紀2
PDF
Webスライスから始めるmicroformats
PDF
ハンズオン勉強会 はじめてのJavaScriptとSPARQL
PDF
elasticsearchソースコードを読みはじめてみた
PPTX
Webスクレイピング用の言語っぽいものを作ったよ
PDF
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
PDF
BMXUG つきじ#4
PDF
(きっと)あなたにも出来る!Hyperledger composer でブロックチェーンアプリを動かしてみた
PDF
長いの
PDF
オープンデータセミナー in 鳥取
PDF
2012.02.28 IAMAS GeekLab #037 MyScripts
PDF
Go言語で作る webアプリ@gocon 2013 spring
PDF
Doshisha(20101108)
PDF
いろいろ考えると日本語の全文検索もMySQLがいいね!
PDF
Web技術勉強会 第38回
PDF
Hadoop_startup
PDF
Firefox Add-on SDK 入門
ODP
Lt
はじめてのモバイルウェブアプリ 3 SPARQLハンズオン オープンデータ水位ゲーム
MongoDBの使い方
20150209 甲府-web新世紀2
Webスライスから始めるmicroformats
ハンズオン勉強会 はじめてのJavaScriptとSPARQL
elasticsearchソースコードを読みはじめてみた
Webスクレイピング用の言語っぽいものを作ったよ
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
BMXUG つきじ#4
(きっと)あなたにも出来る!Hyperledger composer でブロックチェーンアプリを動かしてみた
長いの
オープンデータセミナー in 鳥取
2012.02.28 IAMAS GeekLab #037 MyScripts
Go言語で作る webアプリ@gocon 2013 spring
Doshisha(20101108)
いろいろ考えると日本語の全文検索もMySQLがいいね!
Web技術勉強会 第38回
Hadoop_startup
Firefox Add-on SDK 入門
Lt
Ad

Viewers also liked (13)

PDF
2016 Seleniumゆく年くる年 @ 第4回 日本Seleniumユーザーコミュニティ勉強会
PDF
BootstrapとRailsで、 高速にWebサイトを作ってみた
PDF
伝わるプレゼンをする方法
PPTX
プレゼンの基本
PDF
綺麗なプレゼン資料の作り方、10のテクニック
PDF
魅せるPowerPointビジネスプレゼン【実践編】 
PDF
良いプレゼン 良いスライド
PPT
素敵なプレゼン資料を作るためのKnow-Howてんこ盛りセッション:プレゼン道場 Ver 2.2
PDF
しょぼいプレゼンをパワポのせいにするな! by @jessedee
PDF
ビジネスマン必見!キレイな提案書を作るためのデザインの基礎知識
PPT
色彩センスのいらない配色講座
PDF
見やすいプレゼン資料の作り方 - リニューアル増量版
2016 Seleniumゆく年くる年 @ 第4回 日本Seleniumユーザーコミュニティ勉強会
BootstrapとRailsで、 高速にWebサイトを作ってみた
伝わるプレゼンをする方法
プレゼンの基本
綺麗なプレゼン資料の作り方、10のテクニック
魅せるPowerPointビジネスプレゼン【実践編】 
良いプレゼン 良いスライド
素敵なプレゼン資料を作るためのKnow-Howてんこ盛りセッション:プレゼン道場 Ver 2.2
しょぼいプレゼンをパワポのせいにするな! by @jessedee
ビジネスマン必見!キレイな提案書を作るためのデザインの基礎知識
色彩センスのいらない配色講座
見やすいプレゼン資料の作り方 - リニューアル増量版
Ad

Similar to 実践スクレイピング (20)

PDF
Web技術勉強会23回目
PDF
Hadoopによるリクルートでの技術調査とその活用
PPTX
徳丸本に載っていないWebアプリケーションセキュリティ
PPTX
130329 perl casual_ruik
PDF
Rubyで始めるWebスクレイピング
PDF
はせがわようすけ
PDF
RESTとRailsスタイル
PDF
Fc2blog setting
PDF
WordPressで提供するWeb API
PDF
飲食店サイトのスクレイピング
PDF
エコなWebサーバー
PPTX
Xoopsec
PDF
⑱jQueryをおぼえよう!その4
PDF
「Webサービスのつくり方」 のつくり方
PDF
どきっ!三行で作るランダムダンジョン!?~WEBもあるよ!~ - 2010/8/21 群馬Web研究会(勉強会)
PDF
㉗HTML5+jQueryでお絵かき
KEY
Mojoliciousをウェブ制作現場で使ってみてる
PDF
良いUrlを設計する
PDF
20130412 titanium meetupvol7
PDF
OSMを使ったスマホ&Web開発入門
Web技術勉強会23回目
Hadoopによるリクルートでの技術調査とその活用
徳丸本に載っていないWebアプリケーションセキュリティ
130329 perl casual_ruik
Rubyで始めるWebスクレイピング
はせがわようすけ
RESTとRailsスタイル
Fc2blog setting
WordPressで提供するWeb API
飲食店サイトのスクレイピング
エコなWebサーバー
Xoopsec
⑱jQueryをおぼえよう!その4
「Webサービスのつくり方」 のつくり方
どきっ!三行で作るランダムダンジョン!?~WEBもあるよ!~ - 2010/8/21 群馬Web研究会(勉強会)
㉗HTML5+jQueryでお絵かき
Mojoliciousをウェブ制作現場で使ってみてる
良いUrlを設計する
20130412 titanium meetupvol7
OSMを使ったスマホ&Web開発入門

More from だいすけ ふるかわ (19)

PDF
スタートアップツールチラ見せナイト エニタイムズ
KEY
FireFoxによるWebデザイン
KEY
Ti.developers.meeting
PDF
Titanium mobile
PDF
LibraHack後の スクレイピングを 考える
PDF
Html5で作るiPhoneアプリケーション2010
PDF
HTML5で作るiPhoneアプリケーション
PDF
Webteko#10 GoogleMaps
PDF
すまべん20091114
PDF
Webteko 20090925
PDF
プログラマがデザインをがんばってみた
PDF
PDF
Java Script入門
PPT
メールフォームを作る
PPT
メイドめーる
PDF
メイドめーる
PPT
ememo_plesentation_2008-02-26
PPT
Human Date20070907
スタートアップツールチラ見せナイト エニタイムズ
FireFoxによるWebデザイン
Ti.developers.meeting
Titanium mobile
LibraHack後の スクレイピングを 考える
Html5で作るiPhoneアプリケーション2010
HTML5で作るiPhoneアプリケーション
Webteko#10 GoogleMaps
すまべん20091114
Webteko 20090925
プログラマがデザインをがんばってみた
Java Script入門
メールフォームを作る
メイドめーる
メイドめーる
ememo_plesentation_2008-02-26
Human Date20070907

実践スクレイピング