Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
スクレイピングの安定運用のために苦労したところ、工夫したところ
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
shida
August 21, 2016
Programming
2.1k
4
Share
スクレイピングの安定運用のために苦労したところ、工夫したところ
Bayside Tech Bridge 2 016.08.21
クローリングのスペシャリストが語る、クローラー運用の裏側!
shida
August 21, 2016
More Decks by shida
See All by shida
受託開発で ビジネスづくりを楽しむ
shida
0
2.5k
受託アジャイルでの契約書作り請求や、外注パートナーへの支払いスキームまで
shida
0
940
DevLOVEリンスタカフェ vol.7
shida
1
200
DevLOVE リンスタカフェ vol2 成長を促すKPIが見つからん
shida
0
140
現場の開発者でもできるユーザー中心かつ 仮説検証型の企画アプローチ
shida
0
3k
ユーザーが「それいいね!」と言うまで
shida
0
3.3k
ハイブリッドアプリの 受け入れテスト自動化
shida
0
250
SkypインタビューとKA法による分析
shida
4
1k
CucumberによるHTML5アプリの 受け入れテスト自動化
shida
1
510
Other Decks in Programming
See All in Programming
PHP で mp3 プレイヤーを実装しよう
m3m0r7
PRO
0
280
10 Tips of AWS ~Gen AI on AWS~
licux
5
410
SREに優しいTerraform構成 modulesとstateの組み方
hiyanger
2
130
(Re)make Regexp in Ruby: Democratizing internals for the JIT
makenowjust
2
180
Lightning-Fast Method Calls with Ruby 4.1 ZJIT / RubyKaigi 2026
k0kubun
3
410
tRPCの概要と少しだけパフォーマンス
misoton665
2
210
検索設計から 推論設計への重心移動と Recall-First Retrieval
po3rin
0
140
Vibe하게 만드는 Flutter GenUI App With ADK , 박제창, BWAI Incheon 2026
itsmedreamwalker
0
550
実践CRDT
tamadeveloper
0
570
CDK Deployのための ”反響定位”
watany
4
780
Server-Side Kotlin LT大会 vol.18 [Kotlin-lspの最新情報と Neovimのlsp設定例]
yasunori0418
1
150
AIベース静的検査器の偽陽性率を抑える工夫3選
orgachem
PRO
3
310
Featured
See All Featured
Navigating Weather and Climate Data
rabernat
0
170
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
320
The Curse of the Amulet
leimatthew05
1
11k
Evolving SEO for Evolving Search Engines
ryanjones
0
180
Writing Fast Ruby
sferik
630
63k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
340
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.5k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
140
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
How to Talk to Developers About Accessibility
jct
2
180
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
140
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
110k
Transcript
εΫϨΠϐϯάͷ҆ఆӡ༻ͷͨΊʹ ۤ࿑ͨ͠ͱ͜Ζɺͨ͠ͱ͜Ζ #BZTJEF5FDI#SJEHF ΫϩʔϦϯάͷεϖγϟϦετ͕ޠΔɺΫϩʔϥʔӡ༻ͷཪଆʂ ג ϏʔɾΞδϟΠϧ݉ɺδʔΫϥυ ג ࢤా༟थ
גࣜձࣾϏʔɾΞδϟΠϧ(΄΅ϑϦʔϥϯεɺ2012ΑΓ) δʔΫϥυגࣜձࣾ औక ݉ ϑϦʔϥϯε͕ू·ͬͯɺνʔϜ։ൃ डୗ։ൃ(8ׂ)ɺࣗࣾαʔϏε։ൃ(2ׂ) ϦʔϯɾελʔτΞοϓɺΞδϟΠϧ(اըɺ։ൃɺӡ༻) RailsɺSwiftɺ Java for
Android ։ൃҊ݅ɺҰॹʹಇ͖͍ͨϑϦʔϥϯεͷํ େืूத!!! ຊൃදͰɺࣗࣾαʔϏεͷ҆ఆӡ༻ͷͨΊʹۤ ࿑ͨ͠ͱ͜Ζɺͨ͠ͱ͜ΖΛ͝հ
ۤ࿑ͨ͠ͱ͜Ζ
+BWB4DSJQU͕࣮ߦ͞Εͳ͍ͱ ใ͕ͱΕͳ͍ αΠτଆͰ+4ͰಈతʹϖʔδΛߏஙͯ͠ΔͨΊ
1PSUFSHFJTUͰεΫϨΠϐϯά Ruby Capybara Poltergeist PhantomJS ରαΠτ Safariͱಉ͡JSΤϯδϯ͕ಈ͘ Headlessϒϥβ CapybaraͷPhantomJSυϥΠό ड͚ೖΕςετ༻ςεςΟϯά
ϑϨʔϜϫʔΫ
require 'capybara/poltergeist' Capybara.register_driver :poltergeist do |app| Capybara::Poltergeist::Driver.new(app) end Capybara.default_driver =
:poltergeist agent = Capybara.current_session agent.visit('URL') number = agent.find('CSSηϨΫλ').text.to_i 1PSUFSHFJTUͰεΫϨΠϐϯά
Ϣʔβʔೝূ͠ͳ͍ͱ ใ͕ͱΕͳ͍
agent.visit login_url agent.find('input[name="email"]').set(email) agent.find('input[name="pasword"]').set(password) agent.find('#login-btn').trigger('click') agent.visit account_url ೝূ͔ͯ͠Βର63-ʹΞΫηε
ຖճೝূ͕͠͠ॏ͍
def save_cookie(agent, user) cookies_str = Base64.encode64( Marshal.dump( agent.driver.browser.cookies)) user.update_attributes(cookies: cookies_str)
end def load_cookie(agent, user) cookies = Marshal.load( Base64.decode64(user.cookies)) cookies.values.each do |cookie| cookie_hash = JSON.parse(cookie.to_json) ["attributes"] agent.driver.browser.set_cookie(cookie_hash) end end $PPLJFʹΑΔೝূ
DPPLJFͷ༗ޮظݶ͕ Ε͍ͯΔ͕࣌͋Δ
DPPLJF͕Ε͍ͯͨΒSFUSZ scrape(need_login: true) do agent.visit('URL') agent.find('CSSηϨΫλ').text.to_i end # εΫϨΠϐϯά͢ΔՕॴ༻ڞ௨ϝιου def
scrape need_login: false begin yield rescue => e if need_login && ! login? login retry end end end
ԿೝূτϥΠ͍ͯ͠Δͱ ϩοΫ͞ΕΔ
agent.driver.headers = { "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS
X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 #{Time.now.to_f.to_s}" } 6TFS"HFOUΛͪΐ͍ͪΐ͍ม͑Δ
ΞΫηε͠·͍ͬͯ͘Δͱ ϒϩοΫ͞ΕΔ
Proxy1 (AWS) ΞϓϦ αʔό ର αΠτ ΞΫηεݩΛͪΐ͍ͪΐ͍ม͑Δ Proxy1 (AWS) ᶃϒϩοΫ
ᶄ৽͘͠ىಈ
)5.-ߏ͕มΘΓ εΫϨΠϐϯάࣦഊ ͱ͔
"#ςετͯ͠ΔΒ͘͠ ΞΧϯτຖͰ)5.-͕ҧ͏
Ͱ͖Δ͚ͩදࣔܥ͔ΒεΫϨΠϐϯά͠ͳ͍ ॓ധਓ 9໊ ใදࣔը໘ ॓ധਓ 9 ϑΥʔϜը໘ ໊ ϑΥʔϜ෦ͷϚʔΫΞοϓαʔόʔαΠυͷϓϩάϥϜͱ࿈ ܞ͍ͯ͠ΔͷͰมߋ͕ൃੜ͠ʹ͍͘
<div data-bootstrap-data="{a: 'b', ... }" /> JavaScriptଆʹJSONจࣈྻͰใΛ͍ͯ͠Δͱ͜Ζͱ͔ม ߋ͕ൃੜ͠ʹ͍͘ http://example.com/users/12345678 URLมߋ͕ൃੜ͠ʹ͍͘
αΠτ͕ॏͯ͘ ͨ·ʹλΠϜΞτͨ͠Γ མͪͨΓ͢Δ
ϩʔυͪɺදࣔ࣌ؒΛԆ͢ Capybara.register_driver :poltergeist do |app| Capybara::Poltergeist::Driver.new(app, :timeout => 60) end
Capybara.default_driver = :poltergeist Capybara.default_max_wait_time = 30 agent = Capybara.current_session # ࠷େ60ඵͬͯ͘ΕΔ agent.visit('URL') # ࠷େ30ඵJavaScriptͷඇಉظߋ৽ͳͲͷऴྃΛͬͯ͘ΕΔ number = agent.find('CSSηϨΫλ').text.to_i
εΫϨΠϐϯάࣦഊ ඞ͓͖ͣΔ )5.-ߏͷมԽ ӬଓతΤϥʔ ଓΤϥʔ Ұ࣌తͳΤϥʔ
ϢχοτςετΛఆظతʹࣗಈ࣮ߦ project='ϦϙδτϦ໊' branch='master' api_token='APIτʔΫϯ' url=https://circleci.com/api/v1/project/${project}/ tree/${branch}?circle-token=${api_token} curl \ --header "Accept:
application/json" \ --header "Content-Type: application/json" \ --request POST ${url} CircleCIͷϏϧυΛAPIΛͬͯcron͔Βఆظ࣮ߦ ͚ͨ͜ΒCircleCI͕Slackʹ௨ͯ͘͠ΕΔ
4JEFLJRͷར༻ # 1000ళฮ͋ͬͨͱͯ͠ shops.each do |shop| # ͠10ళฮͰΤϥʔͰॲཧ͕ͱ·ͬͯ͠·ͬͨΒ # 990ళฮ͕ະॲཧʹͳͬͯ͠·͏
shop.scrape end Ұ࣌తͳଓΤϥʔ ಛఆͷshopʹ͚ͩൃੜ͢Δఆ֎ͷΤϥʔ
4JEFLJRͷར༻ ಛఆͷshopͰམͪͯɺଞͷshopͷॲཧݺΕΔ
4JEFLJRͷͦͷଞར ಛఆͷshopͰམͪͯɺଞͷshopͷॲཧݺΕΔ εϨουىಈىಈ·Ͱͷͪ࣌ؒΛ੍ޚ͠ɺରαΠτʹ ෛՙΛ͔͚ա͗ͳ͍ མͪͨ࣌ʹslackʹ௨ͯ͘͠ΕΔ མͪͨεϨουΛϦτϥΠͯ͘͠ΕΔ ࠷େϦτϥΠճࢦఆՄೳ దʹϦτϥΠִؒΛ͛ͳ͕Β(15, 16, 31,
96, 271, ... ) ϦτϥΠ࣌ͷslack௨ΛؒҾ͍ͨΓͰ͖Δ ฒྻॲཧαʔόʔͷεέʔϧΞτͰύϑΥʔϚϯεΞοϓ
·ͱΊ વͰ͖Δ͚ͩεΫϨΠϐϯάΤϥʔɺଓΤϥʔΛճආ͢ ΔΑ͏ʹྗ ͦΕͰશʹճආͰ͖ͳ͍ εΫϨΠϐϯάΤϥʔΛ͔ʹݕ͢ΔΈΛ༻ҙ Ұ࣌తʹଓΤϥʔෆଌͷΤϥʔ͕ൃੜͨ͠߹ɺ֘ॲ ཧҟৗऴྃͭͭ͠ɺ༧ఆ͍ͯͨ͠όονॲཧܧଓ Ұ࣌తΤϥʔ(ଓΤϥʔɺcookie༗ޮظݶΕ)ϦτϥΠ εΫϨΠϐϯάͷӡ༻ʹ͔͔Δ࣌ؒίετΛ͋Β͔͡ΊϓϩδΣ Ϋτॳظʹؔऀʹཧղͯ͠Β͏ඞཁ͕͋Δ(߹ʹΑͬͯ
Ϣʔβʔʹ)
࠷ޙʹએϦϯελΧϑΣ ΦϯϥΠϯ ϦʔϯɾελʔτΞοϓ(ͦͷଞྨࣅ)ख๏Λϕʔεʹͨ͠αʔ Ϗεاըɾ։ൃͷ࣮ફऀͷͨΊͷίϛϡχςΟ աڈ8ճͷΦϑϥΠϯษڧձΛ࣮ࢪ ΠϯλϏϡʔͷํɺϢʔβʔςετͷํɺMVPͷܾΊ ํɺࣾελʔτΞοϓͷۤ࿑ɺͳͲͳͲ ͦΕͷΦϯϥΠϯ൛ ຖिਫ༵ 21:30
GoogleϋϯάΞτʹͯ ݱࡏϝϯόʔ 4໊ ࢀՃऀ֤͕ࣗؔΘ͍ͬͯΔαʔϏεͷݱঢ়ใࠂɺ໘͍ͯ͠Δ ՝ͷڞ༗ͱ૬ޓΞυόΠεͱ͔ɺϦϯελܥͷຊͷಡॻձ ͝ڵຯ͋ΕΛ͔͚͍ͯͩ͘͞!