Spaces:
Runtime error
Runtime error
Update shoalhaven_da_scraper.py
Browse files- shoalhaven_da_scraper.py +16 -6
shoalhaven_da_scraper.py
CHANGED
|
@@ -55,9 +55,10 @@ def scrape():
|
|
| 55 |
page.click("text=DA Tracking")
|
| 56 |
time.sleep(4)
|
| 57 |
|
| 58 |
-
# Step 3: Advanced Search (robust
|
| 59 |
-
page.
|
| 60 |
-
|
|
|
|
| 61 |
|
| 62 |
# Step 4: Date range
|
| 63 |
page.fill("input[name='ctl00$ContentPlaceHolder1$txtFromDate']", "01/10/2025")
|
|
@@ -65,11 +66,13 @@ def scrape():
|
|
| 65 |
page.click("text=Search")
|
| 66 |
time.sleep(4)
|
| 67 |
|
| 68 |
-
# Show results
|
| 69 |
page.click("text=Show")
|
| 70 |
time.sleep(4)
|
| 71 |
|
|
|
|
| 72 |
while True:
|
|
|
|
| 73 |
rows = page.query_selector_all("table tr")[1:]
|
| 74 |
|
| 75 |
for row in rows:
|
|
@@ -82,9 +85,13 @@ def scrape():
|
|
| 82 |
continue
|
| 83 |
seen_da.add(da_number)
|
| 84 |
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
| 86 |
detail_url = f"https://www3.shoalhaven.nsw.gov.au{link}"
|
| 87 |
|
|
|
|
| 88 |
detail_page = context.new_page()
|
| 89 |
detail_page.goto(detail_url, timeout=60000)
|
| 90 |
time.sleep(3)
|
|
@@ -92,6 +99,8 @@ def scrape():
|
|
| 92 |
def get_value(label):
|
| 93 |
try:
|
| 94 |
el = detail_page.query_selector(f"text={label}")
|
|
|
|
|
|
|
| 95 |
return el.evaluate(
|
| 96 |
"node => node.parentElement.nextElementSibling.innerText"
|
| 97 |
).strip()
|
|
@@ -116,7 +125,7 @@ def scrape():
|
|
| 116 |
records.append(record)
|
| 117 |
detail_page.close()
|
| 118 |
|
| 119 |
-
# Pagination
|
| 120 |
next_btn = page.query_selector("text=Next")
|
| 121 |
if next_btn and next_btn.is_enabled():
|
| 122 |
next_btn.click()
|
|
@@ -126,6 +135,7 @@ def scrape():
|
|
| 126 |
|
| 127 |
browser.close()
|
| 128 |
|
|
|
|
| 129 |
df = pd.DataFrame(records, columns=HEADERS)
|
| 130 |
df.to_csv(OUTPUT_FILE, index=False)
|
| 131 |
print(f"Saved {len(records)} records to {OUTPUT_FILE}")
|
|
|
|
| 55 |
page.click("text=DA Tracking")
|
| 56 |
time.sleep(4)
|
| 57 |
|
| 58 |
+
# Step 3: Advanced Search (robust ASP.NET tab click)
|
| 59 |
+
page.wait_for_selector("ul[role='tablist']")
|
| 60 |
+
page.locator("ul[role='tablist'] >> li").nth(1).click()
|
| 61 |
+
page.wait_for_timeout(2000)
|
| 62 |
|
| 63 |
# Step 4: Date range
|
| 64 |
page.fill("input[name='ctl00$ContentPlaceHolder1$txtFromDate']", "01/10/2025")
|
|
|
|
| 66 |
page.click("text=Search")
|
| 67 |
time.sleep(4)
|
| 68 |
|
| 69 |
+
# Step 5: Show results
|
| 70 |
page.click("text=Show")
|
| 71 |
time.sleep(4)
|
| 72 |
|
| 73 |
+
# Step 6: Loop through result pages
|
| 74 |
while True:
|
| 75 |
+
# Get all rows except header
|
| 76 |
rows = page.query_selector_all("table tr")[1:]
|
| 77 |
|
| 78 |
for row in rows:
|
|
|
|
| 85 |
continue
|
| 86 |
seen_da.add(da_number)
|
| 87 |
|
| 88 |
+
link_tag = cols[0].query_selector("a")
|
| 89 |
+
if not link_tag:
|
| 90 |
+
continue
|
| 91 |
+
link = link_tag.get_attribute("href")
|
| 92 |
detail_url = f"https://www3.shoalhaven.nsw.gov.au{link}"
|
| 93 |
|
| 94 |
+
# Open detail page
|
| 95 |
detail_page = context.new_page()
|
| 96 |
detail_page.goto(detail_url, timeout=60000)
|
| 97 |
time.sleep(3)
|
|
|
|
| 99 |
def get_value(label):
|
| 100 |
try:
|
| 101 |
el = detail_page.query_selector(f"text={label}")
|
| 102 |
+
if not el:
|
| 103 |
+
return ""
|
| 104 |
return el.evaluate(
|
| 105 |
"node => node.parentElement.nextElementSibling.innerText"
|
| 106 |
).strip()
|
|
|
|
| 125 |
records.append(record)
|
| 126 |
detail_page.close()
|
| 127 |
|
| 128 |
+
# Pagination: check if "Next" button exists
|
| 129 |
next_btn = page.query_selector("text=Next")
|
| 130 |
if next_btn and next_btn.is_enabled():
|
| 131 |
next_btn.click()
|
|
|
|
| 135 |
|
| 136 |
browser.close()
|
| 137 |
|
| 138 |
+
# Step 7: Save CSV
|
| 139 |
df = pd.DataFrame(records, columns=HEADERS)
|
| 140 |
df.to_csv(OUTPUT_FILE, index=False)
|
| 141 |
print(f"Saved {len(records)} records to {OUTPUT_FILE}")
|