SeleniumBase/examples/presenter/uc_presentation_3.py

784 lines
35 KiB
Python

# https://www.youtube.com/watch?v=-EpZlhGWo9k
import sys
from contextlib import suppress
from seleniumbase import BaseCase
from seleniumbase import SB
BaseCase.main(__name__, __file__)
class UCPresentationClass(BaseCase):
def test_presentation_3(self):
self.open("data:,")
self.set_window_position(4, 40)
self._output_file_saves = False
self.open("https://seleniumbase.io/other/uc3_title.jpg")
self.create_presentation(theme="serif", transition="fade")
self.add_slide(
'<img src="https://seleniumbase.io/other/uc3_title.jpg"'
' width="100%">'
)
self.begin_presentation(filename="uc_presentation.html")
self.open("https://seleniumbase.io/other/uc3_title.jpg")
self.sleep(2.5)
self.create_presentation(theme="serif", transition="fade")
self.add_slide(
'<img src="https://seleniumbase.io/other/uc3_title.jpg"'
' width="100%">'
'<br /><h4><b>(with SeleniumBase UC Mode)</b></h4>'
)
self.add_slide(
"<h4>This is the follow-up to my previous video:</h4>"
'<img src="https://seleniumbase.io/other/uc2_title.jpg"'
' width="80%">'
)
self.add_slide(
'<img src="https://seleniumbase.io/other/uc_vid1_ss9.jpg"'
' width="100%">'
)
self.add_slide(
"<h4>Which was the follow-up to an earlier video:</h4>"
'<img src="https://seleniumbase.io/other/uc_automation.jpg"'
' width="80%">'
)
self.add_slide(
'<img src="https://seleniumbase.io/other/uc_vid1_ss8.jpg"'
' width="100%">'
)
self.add_slide(
"<h5>There, you learned the basics of bypassing CAPTCHAs:</h5>"
'<img src="https://seleniumbase.io/other/check_if_secure.png"'
' width="85%">'
)
self.add_slide(
"<h2><mk-0>Here's a LIVE DEMO of bypassing a CAPTCHA:</mk-0></h2>"
)
self.begin_presentation(filename="uc_presentation.html")
with suppress(Exception):
with SB(uc=True) as sb:
url = "https://gitlab.com/users/sign_in"
sb.uc_open_with_reconnect(url, 4)
sb.assert_text("Username", '[for="user_login"]', timeout=3)
sb.assert_element('[for="user_login"]')
sb.highlight('button:contains("Sign in")')
sb.highlight('h1:contains("GitLab.com")')
sb.post_message("SeleniumBase wasn't detected", duration=4)
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<p><mk-0><b>The code for the previous live demo:</b></mk-0></p>"
"<hr /><br />",
code=(
"<mk-1>from seleniumbase import SB</mk-1>\n\n"
"<mk-2>with SB(uc=True) as sb:</mk-2>\n"
'<mk-3> url = "https://gitlab.com/users/sign_in"</mk-3>\n'
"<mk-4> sb.uc_open_with_reconnect(url, 4)</mk-4>\n\n"
"<mk-5> ...</mk-5>\n"
),
)
self.add_slide(
"<p><b>The code for the previous live demo:</b></p>"
"<hr /><br />",
code=(
"from seleniumbase import SB\n\n"
"with SB(uc=True) as sb:\n"
' url = "https://gitlab.com/users/sign_in"\n'
" sb.uc_open_with_reconnect(url, 4)\n\n"
'<mk-1> sb.assert_text("Username", \'[for="user_login"]\','
' timeout=3)</mk-1>\n'
'<mk-2> sb.assert_element(\'[for="user_login"]\')</mk-2>\n'
'<mk-3> sb.highlight(\'button:contains("Sign in")\')'
'</mk-3>\n'
'<mk-4> sb.highlight(\'h1:contains("GitLab.com")\')'
'</mk-4>\n'
'<mk-5> sb.post_message("SeleniumBase wasn\'t detected",'
' duration=4)</mk-5>\n'
),
)
self.add_slide(
"<h3><mk-0>Even if using UC Mode, you may still need to"
" click the CAPTCHA checkbox in order to bypass it.</mk-0></h3>"
"<br />"
"<h4><mk-1>(That's not a problem because there are special<br />"
"UC Mode methods for handling that situation.)</mk-1>"
)
self.add_slide(
"<p><mk-0>Special <b>UC Mode</b> methods for clicking CAPTCHAs:"
"</mk-0></p><hr /><div></div>"
"<ul><br />\n"
"<li><mk-1><code><b>sb.uc_gui_handle_captcha()</b></code></mk-1>"
"</li>\n"
"PyAutoGUI uses the TAB key with SPACEBAR.<br /><br />\n\n"
"<li><mk-2><code><b>sb.uc_gui_click_captcha()</b></code></mk-2>"
"</li>\n\n"
"PyAutoGUI clicks CAPTCHA with the mouse.<br />\n"
"(Note that you'll need to use this one on Linux!)\n"
"</ul>\n\n\n\n"
"<p></p><br />"
)
self.add_slide(
"<p><b><mk-0>When is clicking the CAPTCHA checkbox required?"
"</mk-0></b></p><hr /><h5>&nbsp</h5>"
"<h4><li><mk-1>They've seen your IP Address too many times."
"</mk-1></li><br />"
"<li><mk-2>They don't accept your User-Agent string.</mk-2>"
"<br />(UC Mode gives you a good one by default)</li>"
"<br />"
"<li><mk-3>You're using Linux. (Likely a server)</mk-3></li>"
"<br />"
"<li><mk-4>You're using a VPN. (If detected)</mk-4></li>"
"<br />"
)
self.add_slide(
"<h3><mk-0>For testing purposes...</mk-0></h3><br />"
"<mk-1>I'll use a bad User-Agent for some Live Demos...</mk-1>"
"<br /><br />"
"<mk-2>This will force me to click the CAPTCHA to bypass it."
"</mk-2>"
)
self.add_slide(
"<h3><mk-0>On the topic of live demos,</mk-0></h3>"
"<h3><mk-0>I'll run some of them now:</mk-0></h3>"
"<br /><br />"
"<h4><mk-1>Get ready for a live demo of:</mk-1></h4>"
"<h4><mk-1>Bypassing Cloudflare with TAB + SPACEBAR...</mk-1></h4>"
)
self.begin_presentation(filename="uc_presentation.html")
agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0.0.0"
if "linux" in sys.platform or "win32" in sys.platform:
agent = None # Use the default UserAgent
with suppress(Exception):
with SB(uc=True, test=True, agent=agent) as sb:
url = "https://gitlab.com/users/sign_in"
sb.uc_open_with_reconnect(url, 4)
sb.uc_gui_handle_captcha() # Only if needed
sb.assert_element('label[for="user_login"]')
sb.set_messenger_theme(location="bottom_center")
sb.post_message("SeleniumBase wasn't detected!")
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<p><mk-0><b>The code for the previous live demo:</b></mk-0></p>"
"<hr /><br />",
code=(
"<mk-1>from seleniumbase import SB</mk-1>\n\n"
"<mk-2>with SB(uc=True) as sb:</mk-2>\n"
'<mk-3> url = "https://gitlab.com/users/sign_in"</mk-3>\n'
"<mk-4> sb.uc_open_with_reconnect(url, 4)</mk-4>\n"
"<mk-5> sb.uc_gui_handle_captcha()</mk-5>\n\n"
"<mk-6> ...</mk-6>\n\n\n\n\n\n"
),
)
self.add_slide(
"<p><b>The code for the previous live demo:</b></p>"
"<hr /><br />",
code=(
"from seleniumbase import SB\n\n"
"with SB(uc=True) as sb:\n"
' url = "https://gitlab.com/users/sign_in"\n'
" sb.uc_open_with_reconnect(url, 4)\n"
" sb.uc_gui_handle_captcha()\n\n"
'<mk-1> sb.assert_text("Username", \'[for="user_login"]\','
' timeout=3)</mk-1>\n'
'<mk-2> sb.assert_element(\'[for="user_login"]\')</mk-2>\n'
'<mk-3> sb.set_messenger_theme(location="bottom_center")'
'</mk-3>\n'
'<mk-4> sb.post_message("SeleniumBase wasn\'t detected!")'
'</mk-4>'
),
)
self.add_slide(
"<h3><mk-0>Live demos, continued...</mk-0></h3>"
"<br /><br />"
"<h4><mk-1>Get ready for a live demo of:</mk-1></h4>"
"<h4><mk-1>Bypassing Cloudflare with a mouse click...</mk-1></h4>"
)
self.begin_presentation(filename="uc_presentation.html")
with suppress(Exception):
with SB(uc=True, test=True, agent=agent) as sb:
url = "https://gitlab.com/users/sign_in"
sb.uc_open_with_reconnect(url, 4)
sb.uc_gui_click_captcha() # Only if needed
sb.assert_element('label[for="user_login"]')
sb.set_messenger_theme(location="bottom_center")
sb.post_message("SeleniumBase wasn't detected!")
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<p><mk-0><b>The code for the previous live demo:</b></mk-0></p>"
"<hr /><br />",
code=(
"<mk-1>from seleniumbase import SB</mk-1>\n\n"
"<mk-2>with SB(uc=True) as sb:</mk-2>\n"
'<mk-3> url = "https://gitlab.com/users/sign_in"</mk-3>\n'
"<mk-4> sb.uc_open_with_reconnect(url, 4)</mk-4>\n"
"<mk-5> sb.uc_gui_click_captcha()</mk-5>\n\n"
"<mk-6> ...</mk-6>\n\n\n\n\n"
),
)
self.add_slide(
"<p><b>The code for the previous live demo:</b></p>"
"<hr /><br />",
code=(
"from seleniumbase import SB\n\n"
"with SB(uc=True) as sb:\n"
' url = "https://gitlab.com/users/sign_in"\n'
" sb.uc_open_with_reconnect(url, 4)\n"
" sb.uc_gui_click_captcha()\n\n"
'<mk-1> sb.assert_text("Username", \'[for="user_login"]\','
' timeout=3)</mk-1>\n'
'<mk-2> sb.assert_element(\'[for="user_login"]\')</mk-2>\n'
'<mk-3> sb.set_messenger_theme(location="bottom_center")'
'</mk-3>\n'
'<mk-4> sb.post_message("SeleniumBase wasn\'t detected!")'
'</mk-4>\n'
),
)
self.add_slide(
"<p><mk-0><b>Quick recap of what you just learned:</b>"
"</mk-0></p><hr /><div></div>"
"<ul>\n"
"<li><mk-1>Activate UC Mode with <code><b>SB(uc=True)</b></code>"
"</mk-1></li><br />\n"
"<li><mk-2>Navigate with stealth by calling "
"<code><b>sb.uc_open_with_reconnect(url)</b></code>"
"</mk-2></li><br />\n"
"<li><mk-3>Use <code><b>sb.uc_gui_handle_captcha()</b></code>"
" or <code><b>sb.uc_gui_click_captcha()</b></code>"
" to bypass CAPTCHAs as needed.</mk-3></li>\n"
"</ul>\n"
"<p><br /><mk-4>(It's that easy!)</mk-4></p><br />\n"
)
self.add_slide(
"<p><mk-0><b>Things can get more complicated</b></mk-0></p>"
"<hr /><div></div><br />"
"<ul>\n"
"<li><mk-1>Previous tutorials mentioned this method:<br />"
"<code><b>sb.uc_click(selector)</b></code>"
"</mk-1></li><br />\n"
"<mk-2>Although this method can no longer click a<br />"
"CAPTCHA directly, it should be used when<br />"
"clicking on something else that causes a<br />"
"CAPTCHA to appear after that.</mk-2>\n"
"<br /><br />"
"<li><mk-3>Here's a live demo of that...</mk-3></li><br />\n"
"</ul>\n"
"<p><br /></p><br />\n"
)
self.begin_presentation(filename="uc_presentation.html")
with suppress(Exception):
with SB(uc=True, incognito=True, locale="en") as sb:
url = "https://ahrefs.com/website-authority-checker"
input_field = 'input[placeholder="Enter domain"]'
submit_button = 'span:contains("Check Authority")'
sb.uc_open_with_reconnect(url) # The bot-check is later
sb.type(input_field, "github.com/seleniumbase/SeleniumBase")
sb.reconnect(0.1)
sb.uc_click(submit_button, reconnect_time=4)
sb.uc_gui_click_captcha()
sb.wait_for_text_not_visible("Checking", timeout=10)
sb.highlight('p:contains(".com/seleniumbase/SeleniumBase")')
sb.highlight('a:contains("Top 100 backlinks")')
sb.set_messenger_theme(location="bottom_center")
sb.post_message("SeleniumBase wasn't detected!")
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<p><mk-0>The code for the previous live demo can be<br />"
"found in the SeleniumBase GitHub repo:<br /><br />"
"<code>github.com/seleniumbase/SeleniumBase</code></mk-0>"
"<br /><br /><br /><br />"
'<mk-1>(See the "examples" folder for all examples)</mk-1></p>\n'
)
self.add_slide(
"<h3><mk-0>Live demos, continued...</mk-0></h3>"
"<br /><br />"
"<h4><mk-1>Get ready for another live demo of"
" using the <code>uc_click(selector)</code> method"
" to bypass a Cloudflare CAPTCHA on"
" <code>steamdb.info</code> ...</mk-1></h4>"
)
self.begin_presentation(filename="uc_presentation.html")
with suppress(Exception):
with SB(uc=True, test=True, disable_csp=True) as sb:
url = "https://steamdb.info/"
sb.uc_open_with_reconnect(url, 3)
sb.uc_click("a.header-login span", 3)
sb.uc_gui_click_captcha()
sb.assert_text("Sign in", "button#js-sign-in", timeout=3)
sb.uc_click("button#js-sign-in", 2)
sb.highlight("div.page_content form")
sb.highlight('button:contains("Sign in")', scroll=False)
sb.set_messenger_theme(location="top_center")
sb.post_message("SeleniumBase wasn't detected", duration=4)
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<p><mk-0><b>The code for the previous live demo:</b></mk-0></p>"
"<hr /><br />",
code=(
"<mk-1>from seleniumbase import SB</mk-1>\n\n"
"<mk-2>with SB(uc=True, disable_csp=True) as sb:</mk-2>\n"
'<mk-3> url = "https://steamdb.info/"</mk-3>\n'
"<mk-4> sb.uc_open_with_reconnect(url, 3)</mk-4>\n"
'<mk-5> sb.uc_click("a.header-login span", 3)</mk-5>\n\n'
"<mk-6> ...</mk-6>\n\n\n\n\n\n\n\n"
),
)
self.add_slide(
"<p><b>The code for the previous live demo:</b></p>"
"<hr /><br />",
code=(
"from seleniumbase import SB\n\n"
"with SB(uc=True) as sb:\n"
' url = "https://steamdb.info/"\n'
" sb.uc_open_with_reconnect(url, 3)\n"
' sb.uc_click("a.header-login span", 3)\n\n'
"<mk-0> sb.uc_gui_click_captcha()</mk-0>\n"
'<mk-1> sb.assert_text("Sign in", "button#js-sign-in",'
' timeout=3)</mk-1>\n'
'<mk-2> sb.uc_click("button#js-sign-in", 2)</mk-2>\n'
'<mk-3> sb.highlight("div.page_content form")</mk-3>\n'
'<mk-4> sb.highlight(\'button:contains("Sign in")\','
' scroll=False)</mk-4>\n'
'<mk-5> sb.set_messenger_theme(location="top_center")'
'</mk-5>\n'
'<mk-6> sb.post_message("SeleniumBase wasn\'t detected!")'
'</mk-6>\n'
),
)
self.add_slide(
"<p>👤 <mk-0><b>Important information</b></mk-0> 👤</p>"
"<hr /><div></div>"
"<ul>\n"
"<li><mk-1>UC Mode now requires <code>PyAutoGUI</code> for all"
" features to work.</mk-1></li><p></p>\n"
"<li><mk-2>PyAutoGUI may require enabling admin-level permissions"
" for controlling the mouse and the keyboard.</mk-2></li><p></p>\n"
"<p></p>"
"<li><mk-3><code>PyAutoGUI</code> doesn't support Headless Mode."
"</mk-3></li>\n<p></p>"
"<li><mk-4>UC Mode now includes a special virtual display"
" on Linux so that you no longer need to use Headless Mode"
" in GUI-less environments.</mk-4></li>\n"
"</ul>\n"
"<p></p>\n"
)
self.add_slide(
"<p>👤 <mk-0><b>General information</b></mk-0> 👤</p>"
"<hr /><br />"
"<p><mk-1>Don't assume that all CAPTCHA services"
" are secure, even if they say they are...</mk-1></p>"
"<br /><br /><br /><br />"
)
self.add_slide(
"<p>👤 <b>General information</b> 👤</p>"
"<hr /><br />"
"<p>Don't assume that all CAPTCHA services"
" are secure, even if they say they are...</p><br />"
"<p><mk-0>(Looking at you, Cloudflare!)</mk-0></p><br />"
"<div /><p></p>\n"
)
self.add_slide(
"<p>👤 <mk-0><b>General information</b></mk-0> 👤</p>"
"<hr /><br />"
"<p><mk-1>"
"On the other hand,<br />"
"some CAPTCHA services are quite good..."
"</mk-1></p>"
"<br /><br /><br /><br />"
)
self.begin_presentation(filename="uc_presentation.html")
with suppress(Exception):
with SB(uc=True, test=True) as sb:
url = "https://seleniumbase.io/apps/recaptcha"
sb.uc_open_with_reconnect(url)
sb.uc_gui_click_captcha() # Try with PyAutoGUI Click
sb.assert_element("img#captcha-success", timeout=3)
sb.set_messenger_theme(location="top_left")
sb.post_message("SeleniumBase wasn't detected")
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<p>👤 <b>General information</b> 👤</p>"
"<hr /><br />"
"<p>On the other hand,<br />"
"some CAPTCHA services are quite good..."
"</p><br />"
"<p><mk-0>(Well done, Google reCAPTCHA!)</mk-0></p><br />"
"<div /><p></p>\n"
)
self.add_slide(
"<p>👤 <mk-0><b>General information</b></mk-0> 👤</p>"
"<hr /><br />"
"<p><mk-1>"
"However, the real reason UC Mode is popular,"
" which you saw earlier,"
" is because of the Cloudflare-bypass capabilities."
" That's where the reputation comes from..."
"</mk-1></p>"
"<br /><br /><br /><br />"
)
self.add_slide(
"<p>👤 <mk-0><b>Catching up</b></mk-0> 👤</p>"
"<hr /><br />"
"<p><mk-1>"
"If this is your first tutorial on UC Mode or SeleniumBase,"
" then here are some important<br />things to know to"
" understand things better..."
"</mk-1></p>"
"<br /><br /><br /><br />"
)
self.add_slide(
"<p>👤 <mk-0><b>What is SeleniumBase?</b></mk-0> 👤</p>"
"<hr /><br />"
"<p><mk-1>"
"SeleniumBase is a complete framework for web automation"
" and testing with Python and Selenium."
"</mk-1><br /><br /><mk-2>"
"Although there are many different features,<br />"
"the most popular one today is UC Mode,<br />"
"which enables Selenium browsers to appear<br />"
"as human-controlled browsers to websites."
"</mk-2></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0><b>Structuring Scripts / Tests</b></mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"There are different ways of stucturing SeleniumBase scripts."
' (Internally called: "The 25 Syntax Formats")'
"</mk-1><br /><br /><mk-2>"
'Most examples use Syntax Format 1: "BaseCase direct class'
' inheritance", which uses the "pytest" test runner.'
"</mk-2><br /><br /><mk-3>"
'The next one in popularity is Syntax Format 21: "SeleniumBase SB"'
' (Python context manager)",<br />which is ideal and recommended'
" for UC Mode."
"</mk-3></p>"
"<br />"
)
self.add_slide(
'<img src="https://seleniumbase.io/other/sb_sf_01.jpg"'
' width="100%">'
)
self.add_slide(
'<img src="https://seleniumbase.io/other/sb_sf_21.jpg"'
' width="100%">'
)
self.add_slide(
"<div>📊 <b>The SeleniumBase GitHub Page</b> 📊</div>"
'<img src="https://seleniumbase.io/other/sb_github.jpg"'
' width="100%">'
)
self.add_slide(
"<p><b>About me: (Michael Mintz)</b></p>\n"
"<ul>\n"
"<li><mk-0>I created the <b>SeleniumBase</b> framework."
"</mk-0></li>\n"
"<li><mk-1>I lead the Automation Team at <b>iboss</b>."
"</mk-1></li>\n"
"</ul>",
image="https://seleniumbase.io/other/iboss_booth.png",
)
self.add_slide(
"<p><b>About me: (Michael Mintz)</b></p>\n"
"<ul>\n"
"<li><mk-0>I've reached over 2 million developers<br />"
" on Stack Overflow.</mk-0></li>\n"
"</ul>"
'<img src="https://seleniumbase.io/other/me_st_o_reached.jpg"'
' width="88%">'
)
self.add_slide(
"<p>👤 <mk-0><b>The Great CAPTCHA Duel:</b></mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"Throughout the past few years, Cloudflare has pushed a lot"
" of changes to their Turnstile CAPTCHA."
"</mk-1><br /><br /><mk-2>"
"In order to keep UC Mode working, I had to push a lot of"
" updates to counter those changes."
"</mk-2><br /><br /><mk-3>"
"It has been an epic duel..."
"</mk-3></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0><b>The Great CAPTCHA Duel:</b></mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"Sometimes Cloudflare pushed multiple<br />"
"changes at the same time..."
"</mk-1><br /><br /><mk-2>"
"That's when I had to make multiple<br />"
"UC Mode updates to counter those changes..."
"</mk-2><br /><br /><mk-3>"
"Sometimes I received a little assistance from GitHub..."
"</mk-3></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Timeline of major Cloudflare updates</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"<b>March 20, 2024</b>: Cloudflare pushed a major update"
" where they could detect UC Mode Selenium clicks."
"</mk-1><br /><br /><mk-2>"
"Outcome: UC Mode's <code>uc_click(selector)</code> method"
" was updated to click on CAPTCHAs<br />via JavaScript using"
" <code>window.setTimeout()</code>."
"</mk-2><br /><br /></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Timeline of major Cloudflare updates</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"<b>May 10, 2024</b>: Cloudflare pushed a major update"
" where CSS Selectors of CAPTCHAs were updated."
"</mk-1><br /><br /><mk-2>"
"Outcome: I had to update all the UC Mode<br />"
'examples to change "span.mark" to just "span".'
"</mk-2><br /><br /></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Timeline of major Cloudflare updates</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"<b>June 7, 2024</b>: Cloudflare pushed an update where CAPTCHAs"
" could detect JavaScript clicks.<br />(This was a major setback!)"
"</mk-1><br /><br /><mk-2>"
"Outcome: I had to add new UC Mode methods for clicking on"
" CAPTCHAs with <code>PyAutoGUI</code>."
"</mk-2><br /><br /></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Timeline of major Cloudflare updates</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"<b>July 8, 2024</b>: Cloudflare made an update where CAPTCHAs"
" were hidden behind Shadow-DOM.<br />"
"(They went for a killing blow!)"
"</mk-1><br /><br /><mk-2>"
"Outcome: I updated existing UC Mode methods so they could"
" determine the CAPTCHA coordinates<br />for"
" <code>PyAutoGUI</code>."
" (Same-day delivery, thanks to an advanced warning"
" on Discord a few days earlier.)"
"</mk-2><br /><br /></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Timeline of major Cloudflare updates</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"<b>July 25, 2024</b>: Cloudflare made updates to the<br />"
"CSS Selectors that come before Shadow-DOM."
"</mk-1><br /><br /><mk-2>"
"Outcome: I updated existing UC Mode methods."
"</mk-2><br /><br /><mk-3>"
'Note: You can use "uc_gui_handle_captcha()" or<br />'
'"uc_gui_click_captcha()" for any CAPTCHA now.<br />'
'(On Linux, only "uc_gui_click_captcha" works.)'
"</mk-3></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Timeline of major Cloudflare updates</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"Only minor changes from Cloudflare<br />"
"have been shipped since then so far..."
"</mk-1><br /><br /><mk-2>"
"Remember: Give me space to work<br />"
"on UC Mode updates as needed..."
"</mk-2><br /><br /><mk-3>"
"...because you never know when they'll strike next..."
"</mk-3></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Theories on how Cloudflare detects JS</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"A month before Cloudflare added JS-detection,<br />"
"a GitHub repo named Brotector was released."
"</mk-1><br /><br /><mk-2>"
"Brotector is capable of detecting both Selenium & JS."
"</mk-2><br /><br /><mk-3>"
"Based on experiements, Brotector's detection mechanisms"
" appear to get the same results as Cloudflare's detection"
" mechanisms.<br />(It appears that Cloudflare learned from them.)"
"</mk-3></p>"
"<br />"
)
self.add_slide(
"<div><b>Brotector info</b></div>"
'<img src="https://seleniumbase.io/other/brotector_gh1.jpg"'
' width="100%">'
)
self.add_slide(
"<div><b>Brotector info</b></div>"
'<img src="https://seleniumbase.io/other/brotector_gh2.jpg"'
' width="100%">'
)
self.add_slide(
"<p>👤 <mk-0>Using Brotector to make UC Mode better</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"In order to make UC Mode better, I decided to build my own"
" open-source CAPTCHA using Brotector:<br />"
'"The Brotector CAPTCHA"'
"</mk-1><br /><br /><mk-2>"
"Unlike Cloudflare's detection system, which only scans for"
" bots on page loads and CAPTCHA-clicks, the Brotector CAPTCHA"
" continuously scans for bots."
"</mk-2><br /><br /><mk-3>"
"This makes it a more powerful anti-bot system."
"</mk-3></p>"
"<br />"
)
self.add_slide(
'<img src="https://seleniumbase.io/other/brotector_c1.png"'
' width="70%">'
)
self.add_slide(
'<img src="https://seleniumbase.io/other/brotector_c2.png"'
' width="84%">'
)
self.add_slide(
"<h2><mk-0>Here's a LIVE DEMO of Brotector CAPTCHA:</mk-0></h2>"
)
self.begin_presentation(filename="uc_presentation.html")
with suppress(Exception):
with SB(test=True) as sb:
url = "https://seleniumbase.io/hobbit/login"
sb.open(url)
sb.click_if_visible("button")
sb.assert_text("Gandalf blocked you!", "h1")
sb.click("img")
sb.highlight("h1")
sb.sleep(3) # Gandalf: "You Shall Not Pass!"
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<h3><mk-0>Here's a LIVE DEMO of UC Mode bypassing"
" Brotector CAPTCHA:</mk-0></h3>"
)
self.begin_presentation(filename="uc_presentation.html")
with suppress(Exception):
with SB(uc=True, test=True) as sb:
url = "https://seleniumbase.io/hobbit/login"
sb.uc_open_with_disconnect(url, 2.2)
sb.uc_gui_press_keys("\t ")
sb.reconnect(1.5)
sb.assert_text("Welcome to Middle Earth!", "h1")
sb.set_messenger_theme(location="bottom_center")
sb.post_message("SeleniumBase wasn't detected!")
sb.click("img")
sb.sleep(5.888) # Cool animation happening now!
self.create_presentation(theme="serif", transition="none")
self.add_slide(
"<p>👤 <mk-0>What happens when Cloudflare adds real-time<br />"
"bot-detection, like Brotector already has?</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"Currently, UC Mode uses Selenium to locate the CAPTCHA checkbox"
" before the <code>PyAutoGUI</code> click.<br />(This is fine"
" for now because CF only scans<br />"
"during page loads and CAPTCHA clicks.)"
"</mk-1><br /><br /><mk-2>"
"There's already a plan in place for the day<br />"
"Cloudflare adds real-time bot-scanning..."
"</mk-2><br /></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>The plan to handle real-time bot-scanning</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p>"
'<pre><code>sb.uc_gui_click_captcha(frame="iframe", retry=False,'
' <mk-1>blind=True</mk-1>)</code></pre><br /><mk-1>'
'Set the third arg, `blind`, to `True` to force a retry'
' (if the first click failed) by clicking at the last known'
' coordinates of the CAPTCHA checkbox without confirming first'
' with Selenium that a CAPTCHA is still on the page.'
' (The page will need to reload first.)'
"</mk-1><br /><br /></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0>Field trip to the UC Mode help docs</mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"Let's take a look at the UC Mode docs<br />"
"from the SeleniumBase GitHub repo..."
"</mk-1></p>"
'<a href="https://github.com/seleniumbase/SeleniumBase/blob/'
'master/help_docs/uc_mode.md" target="_blank">'
'<img src="https://seleniumbase.io/other/sb_github.jpg"'
' width="50%"></a>'
)
self.add_slide(
"<p>👤 <mk-0><b>Study, study, study!</b></mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"There's lots of important information in the UC Mode docs,"
" so study well to avoid falling into traps..."
"</mk-1><br /><br /><mk-2>"
"Sometimes you might still be able to<br />"
"get out of a trap you fell into..."
"</mk-2><br /><br /><mk-3>"
"Once you bypass a CAPTCHA, be ready for anything!"
"</mk-3></p>"
"<br />"
)
self.add_slide(
"<p>👤 <mk-0><b>There's more to come</b></mk-0> 👤</p>"
"<hr /><h6><br /></h6>"
"<p><mk-1>"
"As usual, export more UC Mode updates,<br />"
"but new projects are classified until released."
"</mk-1></p>"
"<br />"
)
self.add_slide(
"<h3>❓ <mk-0>Questions?</mk-0> ❓</h3><h5><mk-0>"
"https://github.com/seleniumbase/SeleniumBase/discussions"
"</mk-0></h5><br />"
"<br /><h3>📌 <mk-1>Found a bug?</mk-1> 🐞</h3><h5><mk-1>"
"https://github.com/seleniumbase/SeleniumBase/issues"
"</mk-0></h5>"
)
self.add_slide(
"<h3>📊 <mk-0>Final remarks</mk-0> 📣</h3><hr /><br />"
"<h3>"
"🛠️ <mk-1>SeleniumBase gives you</mk-1> 🛠️<br />"
"<mk-1>the tools you need to succeed!"
"</mk-1></h3>"
"<h3><mk-2><br />"
"And tools to build lots of bots..."
"</mk-2></h3><br />"
)
self.add_slide(
"<div>🏁 <b>The End</b> 🏁</div>"
'<img src="https://seleniumbase.io/other/sb_github.jpg"'
' width="100%">'
)
self.begin_presentation(filename="uc_presentation.html")