WEBVTT

1
00:00:00.080 --> 00:00:02.359
<v Speaker 1>So if you tell your web automation script to seeply

2
00:00:03.120 --> 00:00:06.519
<v Speaker 1>execute a standard click method on a file upload button,

3
00:00:06.879 --> 00:00:09.519
<v Speaker 1>your entire program will well, it'll instantly freeze.

4
00:00:09.599 --> 00:00:11.679
<v Speaker 2>Yeah, it just hanged. I mean the console stalls out

5
00:00:11.720 --> 00:00:13.279
<v Speaker 2>and the automation basically dies.

6
00:00:13.160 --> 00:00:16.480
<v Speaker 1>Right there, which is incredibly frustrating. So today we are

7
00:00:16.519 --> 00:00:19.879
<v Speaker 1>pulling back the curtain to examine exactly why that happens.

8
00:00:20.399 --> 00:00:22.839
<v Speaker 1>We're looking at the rigid boundary between a web browser

9
00:00:22.879 --> 00:00:27.559
<v Speaker 1>and an operating system. Why crossing that boundary breaks bots?

10
00:00:28.199 --> 00:00:31.760
<v Speaker 1>And while the developer cheat code used to bypass it entirely,

11
00:00:32.119 --> 00:00:33.679
<v Speaker 1>So welcome to the deep dive.

12
00:00:33.880 --> 00:00:37.079
<v Speaker 2>Thanks. Yeah, it's a mechanic that fundamentally changes how you

13
00:00:37.119 --> 00:00:40.759
<v Speaker 2>look at the interaction between local environments and web applications.

14
00:00:40.759 --> 00:00:43.600
<v Speaker 1>To be honest, right, because usually when people talk about webscraping,

15
00:00:43.799 --> 00:00:46.000
<v Speaker 1>the focus is just passive observation.

16
00:00:46.000 --> 00:00:49.600
<v Speaker 2>Exactly, sending get requests, parsing the dom tree, maybe extracting

17
00:00:49.600 --> 00:00:54.200
<v Speaker 2>some text. But today we're focusing on active state manipulation.

18
00:00:54.119 --> 00:00:55.560
<v Speaker 1>Which is a whole different ballgame.

19
00:00:55.679 --> 00:00:58.200
<v Speaker 2>It really is. We aren't just reading the website anymore.

20
00:00:58.200 --> 00:01:01.799
<v Speaker 2>We are injecting local data into it, forcing a server

21
00:01:01.880 --> 00:01:04.079
<v Speaker 2>side reaction. And then capturing the output.

22
00:01:04.359 --> 00:01:06.519
<v Speaker 1>Okay, but to really understand this we have to look

23
00:01:06.519 --> 00:01:10.239
<v Speaker 1>at the deployment strategy first, Like, why build a bot

24
00:01:10.280 --> 00:01:12.319
<v Speaker 1>that uploads files in the first place.

25
00:01:12.280 --> 00:01:14.040
<v Speaker 2>Right, the real world application?

26
00:01:14.400 --> 00:01:16.879
<v Speaker 1>Yeah, I mean, if the end goal is just data extraction,

27
00:01:17.439 --> 00:01:21.640
<v Speaker 1>injecting a local file introduces a massive point of friction,

28
00:01:21.680 --> 00:01:22.280
<v Speaker 1>doesn't it.

29
00:01:22.280 --> 00:01:26.079
<v Speaker 2>It does. But looking at the architecture, the need to

30
00:01:26.359 --> 00:01:31.680
<v Speaker 2>upload files during automation essentially serves two distinct strategic purposes.

31
00:01:31.799 --> 00:01:32.799
<v Speaker 1>Okay, what's the first one?

32
00:01:32.840 --> 00:01:35.879
<v Speaker 2>So the first is generating new content. It makes sense

33
00:01:35.879 --> 00:01:38.599
<v Speaker 2>if we're uploading a data set to like generate a

34
00:01:38.640 --> 00:01:42.079
<v Speaker 2>custom report, we have to feed the machine to actually

35
00:01:42.159 --> 00:01:44.200
<v Speaker 2>get the output we want to scrape.

36
00:01:43.959 --> 00:01:47.480
<v Speaker 1>Oh right, like a specialized scientific portal or something exactly.

37
00:01:47.519 --> 00:01:50.200
<v Speaker 2>You pass it a raw CSV file, the back end

38
00:01:50.239 --> 00:01:53.200
<v Speaker 2>crunches the numbers, and then the server renders a highly

39
00:01:53.200 --> 00:01:56.200
<v Speaker 2>detailed dynamic DOM containing your custom results.

40
00:01:56.400 --> 00:01:59.120
<v Speaker 1>Gotcha. So the scrape is the ultimate goal, but the

41
00:01:59.239 --> 00:02:01.439
<v Speaker 1>upload is the new necessary catalyst to get there.

42
00:02:01.640 --> 00:02:04.920
<v Speaker 2>Yeah, beautifully put. But it's not always about content generation.

43
00:02:05.400 --> 00:02:09.599
<v Speaker 2>The second purpose is purely about access, proceeding deeper into.

44
00:02:09.400 --> 00:02:10.919
<v Speaker 1>A site bypassing gates.

45
00:02:11.159 --> 00:02:14.960
<v Speaker 2>Right, Sometimes you literally cannot move forward on a website

46
00:02:15.000 --> 00:02:16.280
<v Speaker 2>without uploading a file.

47
00:02:16.360 --> 00:02:19.560
<v Speaker 1>I mean like submitting a resume to a heavily gated

48
00:02:19.639 --> 00:02:21.319
<v Speaker 1>job application system maybe.

49
00:02:21.159 --> 00:02:24.800
<v Speaker 2>Yes, or pushing a mandatory display picture into a registration

50
00:02:24.960 --> 00:02:28.879
<v Speaker 2>flow like on a dating site. If your script doesn't

51
00:02:28.919 --> 00:02:32.159
<v Speaker 2>know how to negotiate that requirement, it just gets locked out.

52
00:02:32.360 --> 00:02:35.960
<v Speaker 1>So it's basically like interacting with a building. That's second category,

53
00:02:36.159 --> 00:02:38.560
<v Speaker 1>you know, the resumes and dating picks. That's like showing

54
00:02:38.599 --> 00:02:41.039
<v Speaker 1>an ID to a bouncer just to get inside the club.

55
00:02:41.120 --> 00:02:42.039
<v Speaker 2>That's a great analogy.

56
00:02:42.159 --> 00:02:45.000
<v Speaker 1>Yeah, And the first category the scientific reports. That's like

57
00:02:45.080 --> 00:02:47.879
<v Speaker 1>handing raw ingredients to a chef in the kitchen to

58
00:02:47.919 --> 00:02:49.560
<v Speaker 1>see what dish they bring back out to you.

59
00:02:50.159 --> 00:02:53.680
<v Speaker 2>Exactly. It's either a catalyst for generation or a token

60
00:02:53.759 --> 00:02:57.520
<v Speaker 2>for access. And the specific scenario we're going to unpack

61
00:02:57.560 --> 00:03:01.560
<v Speaker 2>today really illustrates that generation concept. We're going to mentally

62
00:03:01.599 --> 00:03:04.240
<v Speaker 2>walk through the automation of a reverse image search.

63
00:03:04.599 --> 00:03:07.840
<v Speaker 1>Okay, so like uploading an image to find similar or

64
00:03:08.000 --> 00:03:11.199
<v Speaker 1>duplicate images scattered across the Internet. Let's hear we're using

65
00:03:11.240 --> 00:03:12.199
<v Speaker 1>a platform called tenny.

66
00:03:12.319 --> 00:03:15.520
<v Speaker 2>Right in that scenario, we are taking a local image file,

67
00:03:15.719 --> 00:03:19.000
<v Speaker 2>passing it to Tenny's search engine and forcing the server

68
00:03:19.120 --> 00:03:22.400
<v Speaker 2>to return a list of every single domain hosting a

69
00:03:22.520 --> 00:03:23.719
<v Speaker 2>duplicate of that image.

70
00:03:23.759 --> 00:03:25.960
<v Speaker 1>Well, which sounds simple enough, but to actually execute that,

71
00:03:26.080 --> 00:03:28.199
<v Speaker 1>we have to talk about the tools we're using, the

72
00:03:28.240 --> 00:03:29.319
<v Speaker 1>automation toolstack.

73
00:03:29.639 --> 00:03:32.360
<v Speaker 2>Yes, the division of labor here is critical. We're looking

74
00:03:32.400 --> 00:03:37.280
<v Speaker 2>at a specific partnership between two primary technologies, Selenium and

75
00:03:37.439 --> 00:03:38.199
<v Speaker 2>beautiful Soup.

76
00:03:38.360 --> 00:03:41.400
<v Speaker 1>Okay, so Selenium and beautiful Soup, let's break those down. Sure.

77
00:03:41.479 --> 00:03:45.960
<v Speaker 2>So Selenium is functioning as our active webdriver. It utilizes

78
00:03:46.000 --> 00:03:50.120
<v Speaker 2>the W three C webdriver protocol to interface directly with

79
00:03:50.240 --> 00:03:51.960
<v Speaker 2>the browser's rendering.

80
00:03:51.520 --> 00:03:54.560
<v Speaker 1>Engine, basically acting as the driver of the car exactly.

81
00:03:55.039 --> 00:03:58.680
<v Speaker 2>It opens Chrome, maximizes the window, navigates to the website,

82
00:03:58.960 --> 00:04:02.599
<v Speaker 2>handles the JavaScript execution. It mimics the act of human interactions.

83
00:04:02.879 --> 00:04:04.680
<v Speaker 2>It's the engine getting us to the data.

84
00:04:04.840 --> 00:04:06.280
<v Speaker 1>Okay, and beautiful Soup.

85
00:04:06.520 --> 00:04:10.120
<v Speaker 2>Beautiful Soup acts as the extractor. Once Selenium has forced

86
00:04:10.159 --> 00:04:13.120
<v Speaker 2>the server to render the search results, beautiful Soup steps

87
00:04:13.120 --> 00:04:15.400
<v Speaker 2>in to parse the generated dom and pull up the

88
00:04:15.400 --> 00:04:16.120
<v Speaker 2>website names.

89
00:04:16.319 --> 00:04:18.800
<v Speaker 1>Wait, hold on, why do we need two different tools

90
00:04:18.800 --> 00:04:21.279
<v Speaker 1>for that? Yeah, I mean if Selenium is already in

91
00:04:21.319 --> 00:04:25.160
<v Speaker 1>the browser, manipulating the page. Why pass the tot at all.

92
00:04:25.360 --> 00:04:28.519
<v Speaker 1>It's a fair question, Yeah, because doesn't Selenium have built

93
00:04:28.519 --> 00:04:32.720
<v Speaker 1>in methods to locate elements and extract text. Why introduce

94
00:04:32.720 --> 00:04:34.800
<v Speaker 1>a whole secondary library just for parsing.

95
00:04:34.920 --> 00:04:39.279
<v Speaker 2>Well, you're basically trading Selenium's heavy, slow browser context for

96
00:04:39.519 --> 00:04:42.199
<v Speaker 2>Beautiful Soup's lightweight in memory parsing.

97
00:04:42.439 --> 00:04:44.439
<v Speaker 1>Ah, So it's a speed issue exactly.

98
00:04:44.519 --> 00:04:49.160
<v Speaker 2>Selenium is incredibly powerful for interaction, right, but extracting large,

99
00:04:49.319 --> 00:04:53.720
<v Speaker 2>deeply nested dom trees using webdriver commands is computationally really

100
00:04:53.759 --> 00:04:54.800
<v Speaker 2>expensive because.

101
00:04:54.560 --> 00:04:56.639
<v Speaker 1>It has to talk to the browser every single time.

102
00:04:56.839 --> 00:04:59.959
<v Speaker 2>Yes, every time Selenium queries an element, it makes an

103
00:05:00.120 --> 00:05:03.319
<v Speaker 2>HTTP request over the web driving protocol. So if you

104
00:05:03.399 --> 00:05:06.680
<v Speaker 2>are scraping you know, thousands of image source URLs from

105
00:05:06.720 --> 00:05:11.000
<v Speaker 2>a results page, those network requests create a massive bottleneck.

106
00:05:11.079 --> 00:05:13.199
<v Speaker 1>Okay, I get it now. Beautiful Soup is brilliant at

107
00:05:13.240 --> 00:05:17.399
<v Speaker 1>parsing through HTML, but it's totally passive. It can't click or.

108
00:05:17.360 --> 00:05:19.319
<v Speaker 2>Type, right, it can't interact at all.

109
00:05:19.480 --> 00:05:22.560
<v Speaker 1>So once Selenium forces the site to load everything and

110
00:05:22.600 --> 00:05:26.199
<v Speaker 1>generate the final HTML, it just grabs that raw page

111
00:05:26.199 --> 00:05:28.879
<v Speaker 1>source string and hands it directly over to Beautiful soup.

112
00:05:29.199 --> 00:05:33.160
<v Speaker 2>Yep, Beautiful Soup doesn't care about network latency or rendering.

113
00:05:33.680 --> 00:05:37.000
<v Speaker 2>It simply takes that raw string, builds it in memory tree,

114
00:05:37.319 --> 00:05:40.079
<v Speaker 2>and lets you traverse thousands of nodes in fractions of

115
00:05:40.079 --> 00:05:40.560
<v Speaker 2>a second.

116
00:05:40.680 --> 00:05:44.199
<v Speaker 1>So Selenium navigates the physical space and Beautiful Soup digests

117
00:05:44.199 --> 00:05:46.120
<v Speaker 1>the mathematical structure that makes perfect sex.

118
00:05:46.199 --> 00:05:47.920
<v Speaker 2>It's a very elegant division of labor.

119
00:05:48.079 --> 00:05:51.160
<v Speaker 1>Okay, so we have our tools. We've navigated to the

120
00:05:51.199 --> 00:05:55.839
<v Speaker 1>Tenney Reverse Image Search homepage using Selenium. The page is loaded.

121
00:05:56.120 --> 00:05:59.199
<v Speaker 1>Now we need to actually find the upload module. Right.

122
00:05:59.240 --> 00:06:02.360
<v Speaker 2>This is where we hit the absolute biggest technical trap

123
00:06:02.399 --> 00:06:03.639
<v Speaker 2>in web automation.

124
00:06:03.399 --> 00:06:06.240
<v Speaker 1>The OS trap. Let's dig into this because this is fascinating.

125
00:06:06.360 --> 00:06:09.240
<v Speaker 2>So to automate the upload, we first inspect the website's

126
00:06:09.240 --> 00:06:12.680
<v Speaker 2>code to find the upload form. And any element capable

127
00:06:12.720 --> 00:06:15.600
<v Speaker 2>of receiving a file is anchored by a very specific attribute.

128
00:06:15.639 --> 00:06:16.399
<v Speaker 1>What are we looking for?

129
00:06:16.480 --> 00:06:21.000
<v Speaker 2>We're targeting an HTML input tag with the attribute type equals.

130
00:06:20.639 --> 00:06:22.600
<v Speaker 1>File type equals file got it.

131
00:06:22.959 --> 00:06:25.959
<v Speaker 2>That is the universal structural beacon. I mean, regardless of

132
00:06:26.000 --> 00:06:28.360
<v Speaker 2>how much CSS is layered on top to make it

133
00:06:28.399 --> 00:06:31.759
<v Speaker 2>look like, you know, a friendly little dragon drop cloud icon.

134
00:06:32.399 --> 00:06:36.680
<v Speaker 2>The underlying HTML must contain type equals file.

135
00:06:37.199 --> 00:06:40.639
<v Speaker 1>Right, and in this specific tenny scenario we're picturing, let's

136
00:06:40.680 --> 00:06:43.439
<v Speaker 1>say this element also has a name attribute, and the

137
00:06:43.519 --> 00:06:45.759
<v Speaker 1>name is simply image.

138
00:06:45.399 --> 00:06:49.439
<v Speaker 2>Exactly, So we use Selenium's find element by name function.

139
00:06:49.879 --> 00:06:53.199
<v Speaker 2>We pass it the string image, and Selenium locates the

140
00:06:53.279 --> 00:06:54.480
<v Speaker 2>exact node in the DOM.

141
00:06:55.879 --> 00:06:58.079
<v Speaker 1>Okay, awesome, we found the button, so we just tell

142
00:06:58.079 --> 00:06:59.160
<v Speaker 1>Selenium to click it right?

143
00:06:59.279 --> 00:07:02.279
<v Speaker 2>No, right there? Wait, why if you tell the script

144
00:07:02.319 --> 00:07:05.920
<v Speaker 2>to click that button, the whole automation process breaks instantly,

145
00:07:06.079 --> 00:07:06.480
<v Speaker 2>which is.

146
00:07:06.439 --> 00:07:08.120
<v Speaker 1>Exactly what we were talking about at the very beginning

147
00:07:08.120 --> 00:07:08.759
<v Speaker 1>of the deep dive.

148
00:07:08.920 --> 00:07:11.839
<v Speaker 2>The freeze, Yes, the catastrophic freeze.

149
00:07:11.879 --> 00:07:14.639
<v Speaker 1>But why, I mean Selenium click buttons all the time.

150
00:07:14.480 --> 00:07:18.199
<v Speaker 2>Because clicking an upload button launches the operating system's native

151
00:07:18.240 --> 00:07:21.199
<v Speaker 2>file selection dialogue box. You know that familiar pop up

152
00:07:21.240 --> 00:07:22.759
<v Speaker 2>where you browse your computer's folders.

153
00:07:22.800 --> 00:07:26.720
<v Speaker 1>Oh right, the little Windows or macfile explorer window exactly.

154
00:07:27.120 --> 00:07:31.040
<v Speaker 2>And because that file explorer is a native OSGi element,

155
00:07:31.360 --> 00:07:34.720
<v Speaker 2>Selenium has absolutely no hook into it. Oh wow, yeah,

156
00:07:34.800 --> 00:07:38.160
<v Speaker 2>Seleneuman can only interact with elements inside the HTML DOM,

157
00:07:38.240 --> 00:07:41.199
<v Speaker 2>the document object model of the web page. The webdriver

158
00:07:41.279 --> 00:07:45.120
<v Speaker 2>protocol communicates with the browser, not the Windows API or

159
00:07:45.160 --> 00:07:46.759
<v Speaker 2>the macOS window manager.

160
00:07:46.879 --> 00:07:50.480
<v Speaker 1>So the script sends the click command, the browser fires

161
00:07:50.519 --> 00:07:53.480
<v Speaker 1>the event, and then the operating system just violently hijacks

162
00:07:53.480 --> 00:07:54.439
<v Speaker 1>the focus of the machine.

163
00:07:54.519 --> 00:07:58.480
<v Speaker 2>Yes, the OS takes over to render the native file dialogue,

164
00:07:58.720 --> 00:08:01.199
<v Speaker 2>and Selenium is now totally trapped.

165
00:08:00.959 --> 00:08:03.000
<v Speaker 1>Because it's waiting for the browser to say, hey, the.

166
00:08:03.000 --> 00:08:05.879
<v Speaker 2>Click is done, right, But the browser is suspended waiting

167
00:08:05.920 --> 00:08:08.360
<v Speaker 2>for the user to close the OS dialogue box. The

168
00:08:08.439 --> 00:08:10.959
<v Speaker 2>execution context is completely deadlocked.

169
00:08:11.120 --> 00:08:13.759
<v Speaker 1>That is such a brilliant illustration of the boundary layers

170
00:08:13.759 --> 00:08:16.120
<v Speaker 1>and computing. I mean to conceptualize this. Think about it

171
00:08:16.160 --> 00:08:18.279
<v Speaker 1>like a restaurant. The dom of the web page is

172
00:08:18.279 --> 00:08:20.959
<v Speaker 1>the dining room. Okay, I like this, and Selenium is

173
00:08:20.959 --> 00:08:24.439
<v Speaker 1>our waiter. The waiter knows the coordinates of every table,

174
00:08:24.600 --> 00:08:27.800
<v Speaker 1>every chair, every menu item in that specific dining room.

175
00:08:27.800 --> 00:08:29.160
<v Speaker 1>They have total jurisdiction there.

176
00:08:29.319 --> 00:08:33.759
<v Speaker 2>But the operating systems file explore dialogue box, well, that's

177
00:08:33.879 --> 00:08:35.000
<v Speaker 2>the kitchen exactly.

178
00:08:35.200 --> 00:08:38.919
<v Speaker 1>The OS is the kitchen, and our waiter is strictly

179
00:08:38.960 --> 00:08:41.399
<v Speaker 1>front of house. So if we make the waiter push

180
00:08:41.440 --> 00:08:43.960
<v Speaker 1>the button that opens the kitchen doors, the kitchen staff,

181
00:08:44.080 --> 00:08:47.960
<v Speaker 1>the operating system takes over the interaction entirely. Our waiter

182
00:08:48.000 --> 00:08:50.080
<v Speaker 1>is allowed in the kitchen, so they're just left standing

183
00:08:50.159 --> 00:08:53.440
<v Speaker 1>at the swinging doors, totally frozen, waiting for a dish

184
00:08:53.480 --> 00:08:56.120
<v Speaker 1>that they literally cannot reach in and grab themselves.

185
00:08:56.279 --> 00:08:59.879
<v Speaker 2>That is a perfect analogy. It perfectly isolates why visual

186
00:09:00.000 --> 00:09:04.320
<v Speaker 2>automation models fail. You see, visually, a human user sees

187
00:09:04.360 --> 00:09:08.279
<v Speaker 2>the browser and the file explorer as one continuous workflow.

188
00:09:08.399 --> 00:09:11.480
<v Speaker 1>Yeah, you just click and pick your file. It feels seamless.

189
00:09:11.159 --> 00:09:15.519
<v Speaker 2>Exactly, But structurally you are crossing a hard boundary between

190
00:09:15.559 --> 00:09:19.320
<v Speaker 2>an isolated web application and the local machine's native environment.

191
00:09:19.840 --> 00:09:22.039
<v Speaker 2>The script cannot cross that boundary.

192
00:09:22.120 --> 00:09:23.159
<v Speaker 1>It has to circumvent it.

193
00:09:23.159 --> 00:09:24.039
<v Speaker 2>It absolutely must.

194
00:09:24.159 --> 00:09:25.960
<v Speaker 1>Okay, so how do we actually do that? I mean,

195
00:09:25.960 --> 00:09:29.320
<v Speaker 1>how does a developer bypass the OS entirely? If we

196
00:09:29.360 --> 00:09:31.679
<v Speaker 1>can't click the button to trigger the menu, how do

197
00:09:31.720 --> 00:09:34.200
<v Speaker 1>we actually get our local file onto the website?

198
00:09:34.320 --> 00:09:37.679
<v Speaker 2>We exploit a developer bypass. We use the fact that

199
00:09:37.759 --> 00:09:40.360
<v Speaker 2>an input node in the DOM is essentially just a

200
00:09:40.399 --> 00:09:43.320
<v Speaker 2>container for a value. Okay, we don't need the graphical

201
00:09:43.320 --> 00:09:45.600
<v Speaker 2>interface to populate that value. We can use a very

202
00:09:45.600 --> 00:09:48.240
<v Speaker 2>specific webdriver function called send keys.

203
00:09:48.480 --> 00:09:52.320
<v Speaker 1>Wait send keys, but typically isn't send keys just used

204
00:09:52.320 --> 00:09:55.600
<v Speaker 1>for injecting strings into text fields, like typing a word

205
00:09:55.639 --> 00:09:56.399
<v Speaker 1>into a search bar.

206
00:09:56.919 --> 00:10:00.240
<v Speaker 2>Usually yes, but we are co opting it here. Out

207
00:10:00.240 --> 00:10:02.639
<v Speaker 2>of clicking the button to open the visual folder menu,

208
00:10:02.879 --> 00:10:06.519
<v Speaker 2>we use send keys to directly inject the absolute local

209
00:10:06.600 --> 00:10:09.200
<v Speaker 2>file path of our image straight into the website's code.

210
00:10:09.279 --> 00:10:12.080
<v Speaker 1>Oh wow, so we're bypassing the interface entirely.

211
00:10:12.279 --> 00:10:15.960
<v Speaker 2>Entirely, we intercept the dumbnode and directly manipulate its value property.

212
00:10:16.200 --> 00:10:19.399
<v Speaker 1>So, practically speaking, let's say we have an image saved

213
00:10:19.399 --> 00:10:22.120
<v Speaker 1>on our computer, like a plural site logo or something.

214
00:10:22.200 --> 00:10:25.519
<v Speaker 2>Right, we take the absolute local path of that target image,

215
00:10:25.559 --> 00:10:29.440
<v Speaker 2>So say seed drive slash downloads slash plural site logo

216
00:10:29.440 --> 00:10:30.480
<v Speaker 2>dot jpg, and.

217
00:10:30.440 --> 00:10:32.480
<v Speaker 1>We just passed that raw strain directly into the send

218
00:10:32.559 --> 00:10:35.039
<v Speaker 1>keys function targeting that type equals file element.

219
00:10:35.279 --> 00:10:39.240
<v Speaker 2>Yes, the moment that string is injected, the browser's internal

220
00:10:39.279 --> 00:10:43.039
<v Speaker 2>engine validates the path against your local file system.

221
00:10:42.879 --> 00:10:44.159
<v Speaker 1>And if the path is real.

222
00:10:44.120 --> 00:10:47.320
<v Speaker 2>If it resolves, the browser just attaches the binary data

223
00:10:47.360 --> 00:10:50.480
<v Speaker 2>of the file to the form completely bypassing the os

224
00:10:50.519 --> 00:10:54.399
<v Speaker 2>file dialogue. The native pop up literally never even.

225
00:10:54.360 --> 00:10:57.399
<v Speaker 1>Renders, it just silently uploads it in the background.

226
00:10:56.960 --> 00:11:00.879
<v Speaker 2>In milliseconds, we simulate hitting shift plus enter and boom.

227
00:11:00.960 --> 00:11:04.360
<v Speaker 2>The form submits we have successfully pushed a local binary

228
00:11:04.360 --> 00:11:07.200
<v Speaker 2>file into a remote server using nothing but a raw

229
00:11:07.279 --> 00:11:08.080
<v Speaker 2>string injection.

230
00:11:08.320 --> 00:11:11.080
<v Speaker 1>That feels like a magic trick. You're no longer constrained

231
00:11:11.120 --> 00:11:14.399
<v Speaker 1>by the visual interface designed for humans. You're just operating

232
00:11:14.440 --> 00:11:15.919
<v Speaker 1>purely on the underlying.

233
00:11:15.559 --> 00:11:19.080
<v Speaker 2>Architecture exactly, and this triggers the handoff we discussed earlier.

234
00:11:19.399 --> 00:11:22.879
<v Speaker 2>Once the logo is uploaded to tenny, the reverse image search.

235
00:11:22.679 --> 00:11:26.240
<v Speaker 1>Runs right, The processes it and serves back the results page.

236
00:11:26.000 --> 00:11:30.080
<v Speaker 2>And now Selenium's job is done. Its execution context is fulfilled.

237
00:11:30.519 --> 00:11:33.559
<v Speaker 2>It pulls the raw page source of the results, passes

238
00:11:33.600 --> 00:11:37.039
<v Speaker 2>it into Beautiful Soups in memory space, and the parser

239
00:11:37.159 --> 00:11:40.559
<v Speaker 2>extracts all those duplicate website addresses instantly.

240
00:11:40.879 --> 00:11:45.080
<v Speaker 1>The efficiency of that whole pipeline is just remarkable.

241
00:11:44.600 --> 00:11:46.960
<v Speaker 2>It really is. But you know, the core takeaway here

242
00:11:47.039 --> 00:11:50.600
<v Speaker 2>isn't just about combining Selenium and Beautiful Soup. It's about

243
00:11:50.679 --> 00:11:56.320
<v Speaker 2>recognizing system boundaries totally. By understanding why that OS trap occurs,

244
00:11:56.639 --> 00:11:59.879
<v Speaker 2>you develop an instinct for how data actually moves between

245
00:12:00.000 --> 00:12:00.879
<v Speaker 2>different environments.

246
00:12:01.360 --> 00:12:03.840
<v Speaker 1>It really does change how you look at every single

247
00:12:03.840 --> 00:12:06.720
<v Speaker 1>button on a web page. When you see an upload field,

248
00:12:06.720 --> 00:12:08.440
<v Speaker 1>now you shouldn't see a button, you should see an

249
00:12:08.480 --> 00:12:09.799
<v Speaker 1>injection point exactly.

250
00:12:09.879 --> 00:12:11.720
<v Speaker 2>You start thinking like a developer.

251
00:12:11.360 --> 00:12:13.559
<v Speaker 1>Which brings us to a quick review question for you,

252
00:12:13.679 --> 00:12:16.320
<v Speaker 1>the listener, to kind of reinforce what we've covered today.

253
00:12:17.000 --> 00:12:19.639
<v Speaker 1>Next time you are on a website that asks you

254
00:12:19.679 --> 00:12:22.879
<v Speaker 1>to upload a file, I want you to picture the

255
00:12:23.039 --> 00:12:27.600
<v Speaker 1>underlying code right, trace the execution path. Ask yourself what

256
00:12:27.679 --> 00:12:32.399
<v Speaker 1>specific HTML attribute represents that upload button and what specific

257
00:12:32.440 --> 00:12:36.279
<v Speaker 1>function would your automated script use to bypass the operating

258
00:12:36.320 --> 00:12:37.519
<v Speaker 1>system's pop up menu.

259
00:12:37.759 --> 00:12:40.399
<v Speaker 2>I'll give you a hint. It's the difference between a

260
00:12:40.440 --> 00:12:46.320
<v Speaker 2>brittle script that hangs randomly and a robust, headless automation pipeline.

261
00:12:45.840 --> 00:12:50.799
<v Speaker 1>Exactly identifying type equals file and applying send keys. That's

262
00:12:50.840 --> 00:12:51.399
<v Speaker 1>the secret.

263
00:12:51.440 --> 00:12:52.679
<v Speaker 2>It really is the cheat code.

264
00:12:52.799 --> 00:12:56.240
<v Speaker 1>But you know, looking at the sheer speed and invisibility

265
00:12:56.240 --> 00:13:00.000
<v Speaker 1>of that bypass, it leaves us with a pretty profound

266
00:13:00.120 --> 00:13:01.120
<v Speaker 1>architectural question.

267
00:13:01.279 --> 00:13:02.600
<v Speaker 2>Oh absolutely, we just.

268
00:13:02.559 --> 00:13:06.360
<v Speaker 1>Outlined how effortlessly a script can bypass the native OS

269
00:13:06.480 --> 00:13:10.120
<v Speaker 1>dialogue and inject a file path directly into the dom

270
00:13:10.200 --> 00:13:14.039
<v Speaker 1>nodes value property. It requires zero graphical interaction.

271
00:13:14.480 --> 00:13:16.480
<v Speaker 2>It is entirely programmatic and silent.

272
00:13:16.639 --> 00:13:18.600
<v Speaker 1>Right, So, if you are engineering the back end of

273
00:13:18.600 --> 00:13:21.399
<v Speaker 1>a secure portal, how do you defend against that?

274
00:13:21.399 --> 00:13:23.120
<v Speaker 2>That is the million dollar question.

275
00:13:23.279 --> 00:13:26.919
<v Speaker 1>If the native OS dialogue is completely circumvented, how does

276
00:13:26.960 --> 00:13:30.200
<v Speaker 1>the platform actually know if a human painstakingly navigated their

277
00:13:30.240 --> 00:13:33.000
<v Speaker 1>local directory to upload a picture or if a bot

278
00:13:33.039 --> 00:13:35.159
<v Speaker 1>injected it in a fraction of a millisecond.

279
00:13:35.240 --> 00:13:38.120
<v Speaker 2>They often don't. The system just assumes the boundary is secure.

280
00:13:38.279 --> 00:13:41.159
<v Speaker 2>It assumes the browser's graphical interface is the only point

281
00:13:41.159 --> 00:13:41.919
<v Speaker 2>of entry.

282
00:13:42.039 --> 00:13:45.320
<v Speaker 1>And when you strip away that interface, you expose the

283
00:13:45.399 --> 00:13:48.720
<v Speaker 1>raw mechanics of the interaction. It really makes you wonder

284
00:13:48.759 --> 00:13:52.000
<v Speaker 1>how much of modern web security relies on the assumption

285
00:13:52.080 --> 00:13:55.399
<v Speaker 1>of human friction and what happens when bots automate that

286
00:13:55.440 --> 00:13:56.279
<v Speaker 1>friction away.

287
00:13:56.159 --> 00:13:58.399
<v Speaker 2>Entirely something to definitely ponder on your own.

288
00:13:58.720 --> 00:14:01.879
<v Speaker 1>Keep looking closely at the architecture around you till next time.
