import asyncio import aiohttp import aiomysql import json import csv import sys from urllib.parse import urljoin async def check_url(session, url, semaphore, timeout_seconds=10): async with semaphore: try: async with session.head(url, allow_redirects=True, timeout=timeout_seconds) as response: if response.status == 405: async with session.get(url, allow_redirects=True, timeout=timeout_seconds) as get_response: status_msg = "Available" if get_response.status == 200 else ("Not Found" if get_response.status == 404 else "Error") return get_response.status, status_msg status_msg = "Available" if response.status == 200 else ("Not Found" if response.status == 404 else "Error") return response.status, status_msg except asyncio.TimeoutError: return None, "Timeout" except Exception as e: return None, f"Error: {type(e).__name__}" async def process_database(db_name, config, summary_data): print(f"\n--- Processing database: {db_name} ---") host = config['host'] port = config.get('port', 3306) user = config['user'] password = config['password'] table = config['table'] image_column = config['image_column'] pk_column = config['primary_key'] base_url = config['base_url'] concurrency_limit = config.get('concurrency_limit', 50) timeout_seconds = config.get('request_timeout_seconds', 10) output_filename = f"{db_name}_image_report.csv" try: pool = await aiomysql.create_pool( host=host, port=port, user=user, password=password, db=db_name, autocommit=True ) except Exception as e: print(f"Failed to connect to database {db_name}: {e}") summary_data.append([db_name, "Connection Failed", 0, 0, 0, 0]) return try: async with pool.acquire() as conn: async with conn.cursor(aiomysql.DictCursor) as cur: try: await cur.execute(f"SELECT {pk_column}, {image_column} FROM {table} WHERE {image_column} IS NOT NULL AND {image_column} != ''") rows = await cur.fetchall() except Exception as e: print(f"Failed to query table {table} in {db_name}: {e}") summary_data.append([db_name, "Table/Query Error", 0, 0, 0, 0]) return total_rows = len(rows) print(f"Found {total_rows} rows to process in {db_name}.{table}.") if total_rows == 0: print("No rows to process. Skipping.") summary_data.append([db_name, "Success", 0, 0, 0, 0]) return semaphore = asyncio.Semaphore(concurrency_limit) connector = aiohttp.TCPConnector(limit=concurrency_limit) async with aiohttp.ClientSession(connector=connector) as session: tasks = [] for row in rows: img_path = row[image_column] if isinstance(img_path, str) and img_path.startswith('/'): img_path = img_path[1:] if not base_url.endswith('/'): base_url += '/' url = urljoin(base_url, img_path) task = asyncio.create_task(process_row(session, row, url, pk_column, image_column, semaphore, timeout_seconds)) tasks.append(task) results = [] completed = 0 available = 0 not_found = 0 error = 0 for f in asyncio.as_completed(tasks): res = await f results.append(res) status_msg = res[3] if status_msg == "Available": available += 1 elif status_msg == "Not Found": not_found += 1 else: error += 1 completed += 1 if completed % 500 == 0 or completed == total_rows: print(f"Processed {completed}/{total_rows} URLs in {db_name}...") with open(output_filename, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['Row Identifier', 'Original Column Value', 'Full URL', 'Status', 'HTTP Status Code']) for res in results: writer.writerow(res) print(f"Report generated: {output_filename}") # Add to summary summary_data.append([db_name, "Success", total_rows, available, not_found, error]) finally: pool.close() await pool.wait_closed() async def process_row(session, row, url, pk_column, image_column, semaphore, timeout_seconds): status_code, status_msg = await check_url(session, url, semaphore, timeout_seconds) return [row[pk_column], row[image_column], url, status_msg, status_code] async def main(): try: with open('config.json', 'r') as f: config = json.load(f) except FileNotFoundError: print("Error: config.json not found.") sys.exit(1) databases = config.get('databases', []) if not databases: print("No databases to check in config.json.") return summary_data = [] for db_name in databases: await process_database(db_name, config, summary_data) # Write summary report summary_filename = "FINAL_SUMMARY_REPORT.csv" with open(summary_filename, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['Database Name', 'Query Status', 'Total Rows with Image', 'Images Available (200)', 'Images Not Found (404)', 'Errors/Timeouts']) for row in summary_data: writer.writerow(row) print(f"\n=====================================") print(f"ALL DONE! Final summary report generated: {summary_filename}") print(f"=====================================") if __name__ == '__main__': if sys.platform == 'win32': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(main())