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
shida
August 21, 2016
Programming
4
2k
スクレイピングの安定運用のために苦労したところ、工夫したところ
Bayside Tech Bridge 2 016.08.21
クローリングのスペシャリストが語る、クローラー運用の裏側!
shida
August 21, 2016
Tweet
Share
More Decks by shida
See All by shida
受託開発で ビジネスづくりを楽しむ
shida
0
2.4k
受託アジャイルでの契約書作り請求や、外注パートナーへの支払いスキームまで
shida
0
870
DevLOVEリンスタカフェ vol.7
shida
1
130
DevLOVE リンスタカフェ vol2 成長を促すKPIが見つからん
shida
0
71
現場の開発者でもできるユーザー中心かつ 仮説検証型の企画アプローチ
shida
0
2.7k
ユーザーが「それいいね!」と言うまで
shida
0
3.1k
ハイブリッドアプリの 受け入れテスト自動化
shida
0
200
SkypインタビューとKA法による分析
shida
4
920
CucumberによるHTML5アプリの 受け入れテスト自動化
shida
1
390
Other Decks in Programming
See All in Programming
Запуск 1С:УХ в крупном энтерпрайзе: мечта и реальность ПМа
lamodatech
0
960
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
7
1.4k
情報漏洩させないための設計
kubotak
5
1.3k
Amazon Nova Reelの可能性
hideg
0
210
shadcn/uiを使ってReactでの開発を加速させよう!
lef237
0
300
ErdMap: Thinking about a map for Rails applications
makicamel
1
700
歴史と現在から考えるスケーラブルなソフトウェア開発のプラクティス
i10416
0
300
PHPカンファレンス 2024|共創を加速するための若手の技術挑戦
weddingpark
0
140
ISUCON14感想戦で85万点まで頑張ってみた
ponyo877
1
610
Scaling your build logic
antalmonori
1
100
return文におけるstd::moveについて
onihusube
1
1.4k
ASP.NET Core の OpenAPIサポート
h455h1
0
120
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
348
20k
Building Your Own Lightsaber
phodgson
104
6.2k
RailsConf 2023
tenderlove
29
980
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
192
16k
Building Applications with DynamoDB
mza
93
6.2k
The Cost Of JavaScript in 2023
addyosmani
46
7.2k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.7k
Writing Fast Ruby
sferik
628
61k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Faster Mobile Websites
deanohume
305
30k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
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໊ ࢀՃऀ֤͕ࣗؔΘ͍ͬͯΔαʔϏεͷݱঢ়ใࠂɺ໘͍ͯ͠Δ ՝ͷڞ༗ͱ૬ޓΞυόΠεͱ͔ɺϦϯελܥͷຊͷಡॻձ ͝ڵຯ͋ΕΛ͔͚͍ͯͩ͘͞!