8000 Added browser automation lecture notes. · Zaidtech/complete-python-course@c5ce141 · GitHub
[go: up one dir, main page]

Skip to content

Commit c5ce141

Browse files
committed
Added browser automation lecture notes.
1 parent 40d97af commit c5ce141

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+806
-15
lines changed

course_contents/12_browser_automation_selenium/code/pages/quotes_page.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,50 @@ def __init__(self, browser):
1212

1313
@property
1414
def quotes(self) -> List[QuoteParser]:
15-
return [QuoteParser(e) for e in self.browser.find_elements_by_css_selector(QuotesPageLocators.QUOTE)]
16-
15+
return [
16+
QuoteParser(e)
17+
for e in self.browser.find_elements_by_css_selector(
18+
QuotesPageLocators.QUOTE
19+
)
20+
]
21+
1722
@property
1823
def author_dropdown(self) -> Select:
19-
element = self.browser.find_element_by_css_selector(QuotesPageLocators.AUTHOR_DROPDOWN)
24+
element = self.browser.find_element_by_css_selector(
25+
QuotesPageLocators.AUTHOR_DROPDOWN
26+
)
2027
return Select(element)
21-
28+
2229
@property
2330
def tags_dropdown(self):
24-
element = self.browser.find_element_by_css_selector(QuotesPageLocators.TAG_DROPDOWN)
31+
element = self.browser.find_element_by_css_selector(
32+
QuotesPageLocators.TAG_DROPDOWN
33+
)
2534
return Select(element)
26-
35+
2736
@property
2837
def search_button(self):
29-
return self.browser.find_element_by_css_selector(QuotesPageLocators.SEARCH_BUTTON)
30-
38+
return self.browser.find_element_by_css_selector(
39+
QuotesPageLocators.SEARCH_BUTTON
40+
)
41+
3142
def select_author(self, author_name: str):
3243
self.author_dropdown.select_by_visible_text(author_name)
33-
44+
3445
def get_available_tags(self) -> List[str]:
35-
return [option.text for option in self.tags_dropdown.options]
36-
46+
return [option.text.strip() for option in self.tags_dropdown.options]
47+
3748
def select_tag(self, tag_name: str):
3849
self.tags_dropdown.select_by_visible_text(tag_name)
39-
50+
4051
def search_for_quotes(self, author_name: str, tag_name: str) -> List[QuoteParser]:
4152
self.select_author(author_name)
4253
try:
4354
self.select_tag(tag_name)
4455
except NoSuchElementException:
45-
raise InvalidTagForAuthorError(f"Author '{author_name}' does not have any quotes tagged with '{tag_name}'.")
56+
raise InvalidTagForAuthorError(
57+
f"Author '{author_name}' does not have any quotes tagged with '{tag_name}'."
58+
)
4659
self.search_button.click()
4760
return self.quotes
4861

course_contents/12_browser_automation_selenium/code/parsers/quote.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def __init__(self, parent):
66
self.parent = parent
77

88
def __repr__(self):
9-
return f'<Quote {self.content}, by {self.author}>'
9+
return f"<Quote {self.content}, by {self.author}>"
1010

1111
@property
1212
def content(self):
@@ -19,6 +19,6 @@ def author(self):
1919
return self.parent.find_element_by_css_selector(locator).text
2020

2121
@property
22-
def tags(self):
22+
def tag(self):
2323
locator = QuoteLocators.TAGS_LOCATOR
2424
return self.parent.find_element_by_css_selector(locator)
Lines changed: 18 additions & 0 deletions
Original file line numberDif 10000 f line numberDiff line change
@@ -0,0 +1,18 @@
1+
from selenium import webdriver
2+
from pages.quotes_page import QuotesPage, InvalidTagForAuthorError
3+
4+
5+
try:
6+
author = input("Enter the author you'd like quotes from: ")
7+
tag = input("Enter your tag: ")
8+
9+
chrome = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver")
10+
chrome.get("http://quotes.toscrape.com/search.aspx")
11+
page = QuotesPage(chrome)
12+
13+
print(page.search_for_quotes(author, tag))
14+
except InvalidTagForAuthorError as e:
15+
print(e)
16+
except Exception as e:
17+
print(e)
18+
print("An unknown error occurred. Please try again.")

course_contents/12_browser_automation_selenium/lectures/11_adding_waits_to_our_code/locators/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class QuoteLocators:
2+
CONTENT_LOCATOR = "span.content"
3+
AUTHOR_LOCATOR = "span.author"
4+
TAGS_LOCATOR = "span.tag"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class QuotesPageLocators:
2+
QUOTE = "div.quote"
3+
AUTHOR_DROPDOWN = "select#author"
4+
TAG_DROPDOWN = "select#tag"
5+
TAG_DROPDOWN_VALUE_OPTION = "select#tag option[value]"
6+
SEARCH_BUTTON = 'input[name="submit_button"]'

course_contents/12_browser_automation_selenium/lectures/11_adding_waits_to_our_code/pages/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from typing import List
2+
from selenium.webdriver.common.by import By
3+
from selenium.webdriver.support import expected_conditions
4+
from selenium.webdriver.support.ui import Select
5+
from selenium.webdriver.support.wait import WebDriverWait
6+
7+
from locators.quotes_page_locators import QuotesPageLocators
8+
from parsers.quote import QuoteParser
9+
10+
11+
class QuotesPage:
12+
def __init__(self, browser):
13+
self.browser = browser
14+
15+
@property
16+
def quotes(self) -> List[QuoteParser]:
17+
return [
18+
QuoteParser(e)
19+
for e in self.browser.find_elements_by_css_selector(
20+
QuotesPageLocators.QUOTE
21+
)
22+
]
23+
24+
@property
25+
def author_dropdown(self) -> Select:
26+
element = self.browser.find_element_by_css_selector(
27+
QuotesPageLocators.AUTHOR_DROPDOWN
28+
)
29+
return Select(element)
30+
31+
@property
32+
def tags_dropdown(self):
33+
element = self.browser.find_element_by_css_selector(
34+
QuotesPageLocators.TAG_DROPDOWN
35+
)
36+
return Select(element)
37+
38+
@property
39+
def search_button(self):
40+
return self.browser.find_element_by_css_selector(
41+
QuotesPageLocators.SEARCH_BUTTON
42+
)
43+
44+
def select_author(self, author_name: str):
45+
self.author_dropdown.select_by_visible_text(author_name)
46+
47+
def get_available_tags(self) -> List[str]:
48+
return [option.text.strip() for option in self.tags_dropdown.options]
49+
50+
def select_tag(self, tag_name: str):
51+
self.tags_dropdown.select_by_visible_text(tag_name)
52+
53+
def search_for_quotes(self, author_name: str, tag_name: str) -> List[QuoteParser]:
54+
self.select_author(author_name)
55+
56+
# https://selenium-python.readthedocs.io/waits.html
57+
WebDriverWait(self.browser, 10).until(
58+
expected_conditions.presence_of_element_located(
59+
(By.CSS_SELECTOR, QuotesPageLocators.TAG_DROPDOWN_VALUE_OPTION)
60+
)
61+
)
62+
63+
# Alternatively, implicit wait
64+
self.browser.implicitly_wait(10)
65+
66+
try:
67+
self.select_tag(tag_name)
68+
except NoSuchElementException:
69+
raise InvalidTagForAuthorError(
70+
f"Author '{author_name}' does not have any quotes tagged with '{tag_name}'."
71+
)
72+
self.search_button.click()
73+
return self.quotes
74+
75+
76+
class InvalidTagForAuthorError(ValueError):
77+
pass

course_contents/12_browser_automation_selenium/lectures/11_adding_waits_to_our_code/parsers/__init__.py

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from locators.quote_locators import QuoteLocators
2+
3+
4+
class QuoteParser:
5+
def __init__(self, parent):
6+
self.parent = parent
7+
8+
def __repr__(self):
9+
return f"<Quote {self.content}, by {self.author}>"
10+
11+
@property
12+
def content(self):
13+
locator = QuoteLocators.CONTENT_LOCATOR
14+
return self.parent.find_element_by_css_selector(locator).text
15+
16+
@property
17+
def author(self):
18+
locator = QuoteLocators.AUTHOR_LOCATOR
19+
return self.parent.find_element_by_css_selector(locator).text
20+
21+
@property
22+
def tags(self):
23+
locator = QuoteLocators.TAGS_LOCATOR
24+
return self.parent.find_elements_by_css_selector(locator)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import requests
2+
3+
from pages.quotes_page import QuotesPage
4+
5+
page_content = requests.get('http://quotes.toscrape.com').content
6+
page = QuotesPage(page_content)
7+
8+
for quote in page.quotes:
9+
print(quote)

course_contents/12_browser_automation_selenium/lectures/1_our_scraping_code/locators/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class QuoteLocators:
2+
CONTENT_LOCATOR = 'span.text'
3+
AUTHOR_LOCATOR = 'small.author'
4+
TAGS_LOCATOR = 'div.tags a.tag'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class QuotesPageLocators:
2+
QUOTE = "div.quote"
3+
AUTHOR_DROPDOWN = "select#author"
4+
TAG_DROPDOWN = "select#tag"
5+
SEARCH_BUTTON = 'input[name="submit_button"]'

course_contents/12_browser_automation_selenium/lectures/1_our_scraping_code/pages/__init__.py

Whitespace-only changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from bs4 import BeautifulSoup
2+
3+
from locators.quotes_page_locators import QuotesPageLocators
4+
from parsers.quote import QuoteParser
5+
6+
7+
class QuotesPage:
8+
def __init__(self, page):
9+
self.soup = BeautifulSoup(page, 'html.parser')
10+
11+
@property
12+
def quotes(self):
13+
return [QuoteParser(e) for e in self.soup.select(QuotesPageLocators.QUOTE)]

course_contents/12_browser_automation_selenium/lectures/1_our_scraping_code/parsers/__init__.py

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from locators.quote_locators import QuoteLocators
2+
3+
4+
class QuoteParser:
5+
def __init__(self, parent):
6+
self.parent = parent
7+
8+
def __repr__(self):
9+
return f'<Quote {self.content}, by {self.author}>'
10+
11+
@property
12+
def content(self):
13+
locator = QuoteLocators.CONTENT_LOCATOR
14+
return self.parent.select_one(locator).string
15+
16+
@property
17+
def author(self):
18+
locator = QuoteLocators.AUTHOR_LOCATOR
19+
return self.parent.select_one(locator).string
20+
21+
@property
22+
def tags(self):
23+
locator = QuoteLocators.TAGS_LOCATOR
24+
return self.parent.select(locator)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from selenium import webdriver
2+
3+
from pages.quotes_page import QuotesPage
4+
5+
chrome = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver")
6+
chrome.get("http://quotes.toscrape.com")
7+
page = QuotesPage(chrome)
8+
9+
for quote in page.quotes:
10+
print(quote)

course_contents/12_browser_automation_selenium/lectures/3_using_chrome_in_scraping_code/locators/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class QuoteLocators:
2+
CONTENT_LOCATOR = 'span.text'
3+
AUTHOR_LOCATOR = 'small.author'
4+
TAGS_LOCATOR = 'div.tags a.tag'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class QuotesPageLocators:
2+
QUOTE = 'div.quote'

course_contents/12_browser_automation_selenium/lectures/3_using_chrome_in_scraping_code/pages/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from locators.quotes_page_locators import QuotesPageLocators
2+
from parsers.quote import QuoteParser
3+
4+
5+
class QuotesPage:
6+
def __init__(self, browser):
7+
self.browser = browser
8+
9+
@property
10+
def quotes(self):
11+
return [
12+
QuoteParser(e)
13+
for e in self.browser.find_elements_by_css_selector(
14+
QuotesPageLocators.QUOTE
15+
)
16+
]

course_contents/12_browser_automation_selenium/lectures/3_using_chrome_in_scraping_code/parsers/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from locators.quote_locators import QuoteLocators
2+
3+
4+
class QuoteParser:
5+
def __init__(self, parent):
6+
self.parent = parent
7+
8+
def __repr__(self):
9+
return f"<Quote {self.content}, by {self.author}>"
10+
11+
@property
12+
def content(self):
13+
locator = QuoteLocators.CONTENT_LOCATOR
14+
return self.parent.find_element_by_css_selector(locator).text
15+
16+
@property
17+
def author(self):
18+
locator = QuoteLocators.AUTHOR_LOCATOR
19+
return self.parent.find_element_by_css_selector(locator).text
20+
21+
@property
22+
def tags(self):
23+
locator = QuoteLocators.TAGS_LOCATOR
24+
return self.parent.find_elements_by_css_selector(locator)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from selenium import webdriver
2+
3+
from pages.quotes_page import QuotesPage
4+
5+
chrome = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver")
6+
chrome.get("http://quotes.toscrape.com")
7+
page = QuotesPage(chrome)
8+
9+
for quote in page.quotes:
10+
print(quote)

course_contents/12_browser_automation_selenium/lectures/4_our_new_page_locators/locators/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class QuoteLocators:
2+
CONTENT_LOCATOR = "span.content"
3+
AUTHOR_LOCATOR = "span.author"
4+
TAGS_LOCATOR = "span.tag"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class QuotesPageLocators:
2+
QUOTE = "div.quote"
3+
AUTHOR_DROPDOWN = "select#author"
4+
TAG_DROPDOWN = "select#tag"
5+
SEARCH_BUTTON = 'input[name="submit_button"]'

course_contents/12_browser_automation_selenium/lectures/4_our_new_page_locators/pages/__init__.py

Whitespace-only changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from locators.quotes_page_locators import QuotesPageLocators
2+
from parsers.quote import QuoteParser
3+
4+
5+
class QuotesPage:
6+
def __init__(self, browser):
7+
self.browser = browser
8+
9+
@property
10+
def quotes(self):
11+
return [
12+
QuoteParser(e)
13+
for e in self.browser.find_elements_by_css_selector(
14+
QuotesPageLocators.QUOTE
15+
)
16+
]

course_contents/12_browser_automation_selenium/lectures/4_our_new_page_locators/parsers/__init__.py

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
< 9A96 td data-grid-cell-id="diff-fd3ffaf904fae9d0731d231f54c0b78277d615e82ce3e1c52d3720a0720a40de-empty-7-1" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionNum-bgColor, var(--diffBlob-addition-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from locators.quote_locators import QuoteLocators
2+
3+
4+
class QuoteParser:
5+
def __init__(self, parent):
6+
self.parent = parent
+
8+
def __repr__(self):
9+
return f"<Quote {self.content}, by {self.author}>"
10+
11+
@property
12+
def content(self):
13+
locator = QuoteLocators.CONTENT_LOCATOR
14+
return self.parent.find_element_by_css_selector(locator).text
15+
16+
@property
17+
def author(self):
18+
locator = QuoteLocators.AUTHOR_LOCATOR
19+
return self.parent.find_element_by_css_selector(locator).text
20+
21+
@property
22+
def tags(self):
23+
locator = QuoteLocators.TAGS_LOCATOR
24+
return self.parent.find_elements_by_css_selector(locator)

0 commit comments

Comments
 (0)
0