-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscraper.py
More file actions
149 lines (120 loc) · 4.58 KB
/
Copy pathscraper.py
File metadata and controls
149 lines (120 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python3
import csv
import time
import requests
import pandas as pd
from bs4 import BeautifulSoup
# Configuration
INPUT_CSV = 'collected_thumbnails.csv'
OUTPUT_CSV = 'extracted_tables.csv'
REQUEST_TIMEOUT = 30 # seconds
REQUEST_DELAY = 1 # seconds between requests to be respectful
# Headers for requests
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
}
def read_urls_from_csv(file_path):
"""Read URLs from CSV file."""
try:
df = pd.read_csv(file_path)
column_name = df.columns[0] # Assuming the URL column is the first one
urls = df[column_name].tolist()
print(f"Found {len(urls)} URLs in {file_path}")
return urls
except Exception as e:
print(f"Error reading CSV file: {e}")
return []
def fetch_html(url):
"""Fetch HTML content from URL."""
try:
response = requests.get(url, headers=HEADERS, timeout=REQUEST_TIMEOUT)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
print(f"Error fetching {url}: {e}")
return None
def parse_dimension_table(html, url):
"""Parse dimension table from HTML."""
if not html:
return None
try:
soup = BeautifulSoup(html, 'html.parser')
table = soup.select_one('table.dimension-tbl')
if not table:
print(f"No dimension table found at {url}")
return None
# Extract headers
headers = []
header_row = table.select_one('thead tr')
if header_row:
headers = [th.get_text(strip=True) for th in header_row.select('th')]
# Create data object
table_data = {'URL': url}
# Store headers
table_data['HEADERS'] = '|'.join(headers)
# Extract rows
for row in table.select('tbody tr'):
cells = row.select('td')
if len(cells) > 1:
row_label = cells[0].get_text(strip=True)
# Store row label
table_data[f'ROW_LABEL_{row_label}'] = row_label
# Process each cell (skip first one which is the row label)
for i in range(1, len(cells)):
if i < len(headers):
header = headers[i]
cell_text = cells[i].get_text(strip=True)
# Create composite key for each cell
key = f'{row_label}_{header}'
table_data[key] = cell_text
return table_data
except Exception as e:
print(f"Error parsing table at {url}: {e}")
return None
def main():
"""Main function."""
print("Starting web scraper")
# Read URLs from CSV
urls = read_urls_from_csv(INPUT_CSV)
if not urls:
print("No URLs found. Exiting.")
return
# Process URLs
results = []
successful = 0
for i, url in enumerate(urls):
print(f"Processing ({i+1}/{len(urls)}): {url}")
# Fetch HTML
html = fetch_html(url)
# Parse table
if html:
table_data = parse_dimension_table(html, url)
if table_data:
results.append(table_data)
successful += 1
print(f"✓ Successfully extracted table from {url}")
# Add delay to be respectful to the server
time.sleep(REQUEST_DELAY)
print(f"Processed {successful} URLs successfully out of {len(urls)}")
# Get all unique keys across all results
if results:
all_keys = set()
for result in results:
all_keys.update(result.keys())
# Sort keys for consistent column order
sorted_keys = sorted(all_keys)
# Write to CSV
with open(OUTPUT_CSV, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=sorted_keys)
writer.writeheader()
for result in results:
writer.writerow(result)
print(f"Successfully wrote {len(results)} rows to {OUTPUT_CSV}")
print("Scraping completed successfully")
else:
print("No results to write to CSV")
print("Scraping completed with errors")
if __name__ == "__main__":
main()