I have tried and tried. What could work- is if I could get a scrape of this page and all of the columns you can toggle on: Network-wide->Clients One of the columns is "Connected To." I have been able to get decent data with this code below (also posted at Merakicode/ClientScrape at main · jadexing/Merakicode (github.com)) I also was able to pull a really nice client scrape (also on GitHub)- but none of that data shows which AP a client is connected. The goal is to choose a network, then an AP, and see the active connected clients. HELP! (& thank you). #This is an attempt at scraping the Meraki page Network-wide--> Clients #This does not capture all columns, yet. This is WIP - but is solid, "As-Is." # https://jamiegprice.substack.com/ import requests import pandas as pd from datetime import datetime import time def get_api_key(): return input("Please enter your Meraki API key: ") def get_organizations(api_key): url = "https://api.meraki.com/api/v1/organizations" headers = {"X-Cisco-Meraki-API-Key": api_key} response = requests.get(url, headers=headers) response.raise_for_status() return response.json() def get_networks(api_key, org_id): url = f"https://api.meraki.com/api/v1/organizations/{org_id}/networks" headers = {"X-Cisco-Meraki-API-Key": api_key} response = requests.get(url, headers=headers) response.raise_for_status() networks = response.json() sorted_networks = sorted(networks, key=lambda x: x['name']) # Sort networks alphabetically by name return sorted_networks def get_network_clients(api_key, network_id): url = f"https://api.meraki.com/api/v1/networks/{network_id}/clients" headers = {"X-Cisco-Meraki-API-Key": api_key} response = requests.get(url, headers=headers) response.raise_for_status() return response.json() if __name__ == "__main__": start_time = time.time() try: api_key = get_api_key() organizations = get_organizations(api_key) print("Numbered list of organizations:") for idx, org in enumerate(organizations, 1): print(f"{idx}. {org['name']}") org_choice = int(input("Please enter the number of the organization you want to choose: ")) selected_org_id = organizations[org_choice - 1]['id'] networks = get_networks(api_key, selected_org_id) print("Numbered list of networks:") for idx, network in enumerate(networks, 1): print(f"{idx}. {network['name']}") network_choice = int(input("Please enter the number of the network you want to check clients for: ")) selected_network_id = networks[network_choice - 1]['id'] print("Fetching online wireless clients...") network_clients = get_network_clients(api_key, selected_network_id) print("List of online wireless clients:") all_clients_data = [] for client in network_clients: client_data = { 'Client Name': client.get('description', 'None'), 'MAC Address': client.get('mac', 'None'), 'IP Address': client.get('ip', 'None'), 'Status': client.get('status', 'None'), 'Manufacturer': client.get('manufacturer', 'None'), 'OS': client.get('os', 'None'), 'Usage (MB)': client['usage']['sent'] + client['usage']['recv'] if 'usage' in client else 'None', 'First Seen': client.get('firstSeen', 'None'), # No need to convert to timestamp here 'Last Seen': client.get('lastSeen', 'None'), 'SSID': client.get('ssid', 'None'), 'VLAN': client.get('vlan', 'None'), 'Hostname': client.get('dhcpHostname', 'None'), 'Access Point': client.get('apMac', 'None'), 'Switch Port': client.get('switchport', 'None'), 'User': client.get('user', 'None') } all_clients_data.append(client_data) # Save data to a CSV file with today's date and time in the filename now = datetime.now() date_time = now.strftime("%Y-%m-%d_%H-%M-%S") csv_filename = f"online_wireless_clients_{date_time}.csv" df = pd.DataFrame(all_clients_data).fillna("None") df.to_csv(csv_filename, index=False) print(f"Online wireless client data has been saved to {csv_filename}.") end_time = time.time() runtime_minutes = (end_time - start_time) // 60 runtime_seconds = (end_time - start_time) % 60 print(f"Runtime: {int(runtime_minutes)} minutes {int(runtime_seconds)} seconds") except requests.exceptions.HTTPError as errh: print("Http Error:", errh) except requests.exceptions.ConnectionError as errc: print("Error Connecting:", errc) except requests.exceptions.Timeout as errt: print("Timeout Error:", errt) except requests.exceptions.RequestException as err: print("Oops: Something Else", err)
... View more