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
WebView からデータをスクレイピングする
Search
Tatsunori Nakano
October 02, 2021
Programming
640
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
WebView からデータをスクレイピングする
React Native 祭での LT に使った資料です。
https://reactnative-matsuri.com/ja
Tatsunori Nakano
October 02, 2021
Other Decks in Programming
See All in Programming
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
7.7k
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.5k
不幸な GC
chencmd
0
670
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
160
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
350
170k Jobs a Day on GKE: Scaling Mercari's CI Platform - and What's Next for AI-Native Development
junyaokabe
0
120
まずはプロンプトガイドを読もう、話はそれからだ
kiakiraki
1
200
Go 1.27 における memory allocation の高速化
andpad
0
300
「つくるAI」だけではバグは見つからない ~テストに必要な「見つけるAI」を分離させる戦略~
mfunaki
0
160
初めての模倣学習とVLA
natsutan
0
200
運用ダッシュボードの設計を誰も教えてくれないのだけどみなさんどうしてるんですか? - チームに監視するという文化を根付かせるための第一歩を踏みたい -
satoshi256kbyte
1
140
異なる設計思想のフレームワークを経験して得た学び
amekuhideki
1
290
Featured
See All Featured
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
350
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
260
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Why Our Code Smells
bkeepers
PRO
340
58k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
280
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
280
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
Docker and Python
trallard
47
4.1k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
380
How to make the Groovebox
asonas
2
2.3k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
440
Transcript
WebView ͔Β σʔλΛεΫϨΠϐϯά͢Δ Tatsunori Nakano
ࣗݾհ • Tatsunori Nakano • ࡳຈग़ → ౦ژ • ฏͷ
Web ܥͷձࣾͰ React Λॻ͍͍ͯ·͢ɻ • ࠓ͔Β React Native ৮Γ࢝ΊɺिʹΞϓϦΛ࡞ͬͨΓ͍ͯ͠·͢ɻ
͢͜ͱ • ࡞ͨ͠ΞϓϦͷհ • WebView ͱΞϓϦͷσʔλͷΓऔΓʹ͍ͭͯ
ϋΠϥΠτɾϚωʔδϟʔ ɾKindle ͷϋΠϥΠτΛΠϯϙʔτ ɾෳͷຊͷϋΠϥΠτΛΞϓϦͰҰݩཧ ɾϥϯμϜදࣔϦϚΠϯυػೳͰهԱΛఆண
CSV ΤΫεϙʔτ PDF ΤΫεϙʔτ ݩʑ Kindle ʹΤΫεϙʔτػೳ͕උΘ͍ͬͯΔ ͕ɺΞϓϦͰѻ͍ʹ͍͘😥
Kindle ͷϋΠϥΠτϒϥβ͔ΒΞΫηεͰ͖Δ WebView Ͱ։͍ͯϋΠϥΠτΛऔಘ͢Δ💡
WebView ͰʮϝϞͱϋΠϥΠτʯΛ։͘ ຊͷҰཡใΛऔಘͯ͠දࣔ͢Δ બͨ͠ຊͷϋΠϥΠτΛऔಘ͢Δ
document.querySelectorAll("a.a-text-normal").forEach((a,index) => console.log(index,a.text)) ※ ຊͷλΠτϧҰཡΛऔಘ
injectJavaScript() • WebView ্Ͱ JavaScript ͷίʔυΛ࣮ߦ͢Δ • Ҿʹ࣮ߦ͍ͨ͠ JavaScript ͷίʔυΛ
string Ͱ͢ • WebView ʹ ref Λઃఆ͠ɺͦͷ ref ʹର࣮ͯ͠ߦ͢Δ // ྫɿഎܠΛ੨͘͢Δ webviewRef.current.injectJavaScript("document.body.style.backgroundColor = 'blue'")
window.ReactNativeWebView.postMessage() • WebView ͔ΒΞϓϦଆϝοηʔδΛ͛Δ • Ҿʹ͍͛ͨϝοηʔδΛ string Ͱ͢ // ྫɿΞϓϦଆʹ
"Hello" ͱ͍͏จࣈྻΛ͛Δ window.ReactNativeWebView.postMessage("Hello!")
onMessage • WebView ͷϓϩύςΟ • postMessage() ʹΑͬͯඈ͞ΕͨϝοηʔδΛड͚औΔ // ྫɿඈΜͰ͖ͨϝοηʔδΛ alert
Ͱදࣔ͢Δ return ( <View style={{ flex: 1 }}> <WebView source={{ html }} onMessage={(event) => { alert(event.nativeEvent.data); }} /> </View> );
ɾinjectJavaScript() ɾwindow.ReactNativeWebView.postMessage() ɾonMessage ͜ͷ 3 ͭΛΈ߹Θͤͯ WebView ͔ΒใΛऔಘ͠·͢
document.querySelectorAll("a.a-text-normal").forEach((a,index) => console.log(index,a.text)) ※ ຊͷλΠτϧҰཡΛऔಘ
document.querySelectorAll("a.a-text-normal").forEach((a,index) => console.log(index,a.text)) document.querySelectorAll("a.a-text-normal").forEach((a,index) => window.ReactNativeWebView.postMessage([index,a.text])) const getTitleList = 'document.querySelectorAll("a.a-text-normal").forEach((a,index)
=> window.ReactNativeWebView.postMessage([index,a.text]))' // WebView ͷ ref const webviewRef = useRef<WebView>(null!); // JavaScript ࣮ߦ༻ͷؔ const runJS = (code: string) => { webviewRef.current.injectJavaScript(code); }; return ( <SafeAreaView> <WebView source={{ uri: 'https://read.amazon.co.jp/notebook' }} onNavigationStateChange={() => runJS(getTitleList)} onMessage={(event) => { console.log(event.nativeEvent.data) }} ref={webviewRef} /> </SafeAreaView> );
string Λ Ճͯ͠ը໘ʹඳը͢Δ
// WebView Ͱ࣮ߦͤ͞Δ JavaScript ͷίʔυ const codes = { getTitleList:
'document.querySelectorAll("a.a-text-normal").forEach((a,i) => window.ReactNativeWebView.postMessage([i,a.text]))', getAsinList: 'document.querySelectorAll("#kp-notebook-library>div").forEach((div, i)=> window.ReactNativeWebView.postMessage([i,div.id,"asin"]))', click: 'document.querySelectorAll("a.a-text-normal")[number].click()', loadingCheck: 'window.ReactNativeWebView.postMessage(document.querySelector("div#kp-notebook-spinner.kp-spinner").style.display)', getTitle: 'window.ReactNativeWebView.postMessage(document.querySelector("#annotation-scroller div.a-column.a-span-last > h3").textContent)', getImg: 'window.ReactNativeWebView.postMessage(document.querySelector("#annotation-scroller div.a-column.a-span3 > a img").src)', getLocation:'window.ReactNativeWebView.postMessage([[...[...document.querySelectorAll("#kp-notebook-annotations > div > div > div > input")].filter(input => {return input.parentNode.nextElementSibling.contains(input.parentNode.nextElementSibling.querySelector(".a-alert-inline")) === false})].map(input => input.value)])', getText: 'window.ReactNativeWebView.postMessage([...document.querySelectorAll("#highlight")].map(span => span.textContent + "#*#--*#*"))', }; ຊͷλΠτϧऔಘ༻ɺΫϦοΫ༻ɺϋΠϥΠτऔಘ༻ͳͲͷ JavaScript ͷίʔυΛ·ͱΊͨ Object Λ༻ҙ͓͖ͯ͠ɺ ͷૢ࡞ʹԠͯ͡ injectJavaScript() Ͱ࣮ߦ
·ͱΊ • injectJavaScript() • window.ReactNativeWebView.postMessage() • onMessage ͜ͷ 3ͭΛΈ߹Θͤͯ WebView
͔ΒใΛऔಘ͠·͢
͋Γ͕ͱ͏͍͟͝·ͨ͠ @centerfield77