master #1
@@ -0,0 +1,72 @@
|
|||||||
|
import asyncio
|
||||||
|
from playwright.async_api import async_playwright
|
||||||
|
|
||||||
|
UU_EMAIL = "email@gmail.com"
|
||||||
|
UU_PASSWORD = "password"
|
||||||
|
|
||||||
|
async def download_uu_bill_live():
|
||||||
|
async with async_playwright() as p:
|
||||||
|
# Opens visible browser with 1.5 second step delay
|
||||||
|
browser = await p.chromium.launch(headless=False, slow_mo=1500)
|
||||||
|
page = await browser.new_page()
|
||||||
|
|
||||||
|
print("Opening United Utilities homepage...")
|
||||||
|
await page.goto("https://unitedutilities.com")
|
||||||
|
|
||||||
|
# Handle cookie banner (confirmed working)
|
||||||
|
try:
|
||||||
|
await page.click("button:has-text('Accept All')", timeout=5000)
|
||||||
|
print("Cookies accepted.")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# NEW STEP: Click the header login button based on your HTML code
|
||||||
|
print("Clicking 'LOG IN / REGISTER' button in the header...")
|
||||||
|
await page.click("a.c-navigation__actions-btn:has-text('LOG IN / REGISTER')")
|
||||||
|
|
||||||
|
# Wait for the login portal page to fully transition and load
|
||||||
|
print("Waiting for login portal page to load...")
|
||||||
|
await page.wait_for_url("https://myaccount.unitedutilities.com/**", timeout=15000)
|
||||||
|
|
||||||
|
print("Typing credentials live...")
|
||||||
|
# Targets the unique ID 'login-email' from your HTML snippet
|
||||||
|
await page.fill("#login-email", UU_EMAIL)
|
||||||
|
|
||||||
|
# Targets the likely matching password ID structure
|
||||||
|
await page.fill("#PasswordMasking", UU_PASSWORD)
|
||||||
|
|
||||||
|
|
||||||
|
print("Clicking submit login form...")
|
||||||
|
await page.click("#login-btn")
|
||||||
|
|
||||||
|
|
||||||
|
print("Waiting for dashboard to load...")
|
||||||
|
await page.wait_for_url("https://myaccount.unitedutilities.com/Secure/Dashboard", timeout=30000)
|
||||||
|
|
||||||
|
|
||||||
|
print("Navigating to billing section...")
|
||||||
|
await page.click("text=View bills and payments")
|
||||||
|
|
||||||
|
print("Clicking 'View statement' button...")
|
||||||
|
await page.click("a[href*='type=viewStatement']")
|
||||||
|
|
||||||
|
# NEW STEP: Wait for the dynamic bills table to finish loading
|
||||||
|
print("Waiting for bills table to load...")
|
||||||
|
await page.wait_for_selector("table#viewBill tbody tr")
|
||||||
|
|
||||||
|
# Trigger and catch the file download pipeline
|
||||||
|
async with page.expect_download() as download_info:
|
||||||
|
print("Clicking the newest bill download link in the table...")
|
||||||
|
# Targets the very first row's download link inside the table body
|
||||||
|
await page.locator("table#viewBill tbody tr").first.locator("a[href*='DownloadBill.aspx']").click()
|
||||||
|
|
||||||
|
download = await download_info.value
|
||||||
|
save_path = "./united_utilities_bill.pdf"
|
||||||
|
await download.save_as(save_path)
|
||||||
|
print(f"Success! Newest bill saved to {save_path}")
|
||||||
|
|
||||||
|
print("Finishing up, closing browser in 5 seconds...")
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
await browser.close()
|
||||||
|
|
||||||
|
asyncio.run(download_uu_bill_live())
|
||||||
Reference in New Issue
Block a user