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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
アクセシビリティから考える情報設計
high_g_engineer
0
300
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
360
Hono + Inertia + React で LP を構築した話
oukayuka
2
220
RSSとCodexを使ってX投稿自動化してみた
ochtum
0
110
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
130
Swift愛好会と私(ウホーイ) / Swift Fan Club and Uhooi
uhooi
0
140
初めての模倣学習とVLA
natsutan
0
500
Deep dive into the select statement (GopherCon UK)
jespino
0
170
【DroidKaigi 2026】「アクセシビリティを利用するとき、 アクセシビリティもまたこちらを利用している」 〜マルウェアによる攻撃と防衛について〜
halunoyo
0
410
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
120
Pythonの実行はどこまで賢くなったのか? CPythonとPyPyから見る最適化のしくみ
curekoshimizu
4
2.8k
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
3
530
Featured
See All Featured
Ethics towards AI in product and experience design
skipperchong
2
360
A Tale of Four Properties
chriscoyier
163
24k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.3k
Music & Morning Musume
bryan
47
7.4k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
270
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Accessibility Awareness
sabderemane
1
200
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
WENDY [Excerpt]
tessaabrams
12
39k
Product Roadmaps are Hard
iamctodd
55
13k
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