Files
gpu-detect/server/generate_intel_ids.py

116 lines
4.2 KiB
Python

#!/usr/bin/env python3
import os
import re
import sys
import requests
from bs4 import BeautifulSoup
# The target URLs. You can freely add any new Intel GPU driver documentation links here.
URLS = [
"https://dgpu-docs.intel.com/overview/supported-hardware/xe-driver-gpus.html"
]
def get_filename_from_url(url):
"""
Derives a clean .ids filename from the URL slug.
Examples:
.../legacy-gpus.html -> legacy.ids
.../i915-driver-gpus.html -> i915.ids
.../xe2-driver-gpus.html -> xe2.ids (for future updates)
"""
slug = url.split('/')[-1].replace('.html', '')
for suffix in ['-driver-gpus', '-gpus', '-driver']:
if slug.endswith(suffix):
return slug[:-len(suffix)] + '.ids'
return slug + '.ids'
def extract_pci_ids(url):
"""
Scrapes the URL, dynamically locates the PCI ID column, and extracts
unique, clean 4-digit hexadecimal PCI IDs.
"""
print(f"Scraping: {url}")
headers = {
'User-Agent': 'Mozilla/5.0 (NixOS Intel-detect Tool)'
}
try:
response = requests.get(url, headers=headers, timeout=15)
response.raise_for_status()
except requests.RequestException as e:
print(f"Error fetching {url}: {e}", file=sys.stderr)
return []
soup = BeautifulSoup(response.text, 'html.parser')
pci_ids = set()
tables = soup.find_all('table')
if not tables:
print(f"Warning: No data tables found on {url}", file=sys.stderr)
return []
for table in tables:
# 1. Inspect headers to locate the exact index of the PCI/Device ID column
thead = table.find('thead')
if thead:
headers_text = [th.get_text(strip=True).lower() for th in thead.find_all('th')]
else:
first_tr = table.find('tr')
headers_text = [th.get_text(strip=True).lower() for th in first_tr.find_all(['th', 'td'])] if first_tr else []
pci_col_idx = -1
for idx, text in enumerate(headers_text):
if any(kwd in text for kwd in ['pci', 'device id', 'dev id', 'did']):
pci_col_idx = idx
break
# Soft fallback: check if header just contains 'id'
if pci_col_idx == -1:
for idx, text in enumerate(headers_text):
if 'id' in text:
pci_col_idx = idx
break
# 2. Iterate through rows and pull data
tbody = table.find('tbody')
rows = tbody.find_all('tr') if tbody else table.find_all('tr')
for row in rows:
cells = row.find_all('td')
if not cells:
continue
# Extract strictly from the matching column if found
if pci_col_idx != -1 and pci_col_idx < len(cells):
cell_text = cells[pci_col_idx].get_text(strip=True)
# Matches standalone 4-char hex strings, ignoring optional '0x' prefix
matches = re.findall(r'\b(?:0x)?([0-9a-fA-F]{4})\b', cell_text)
for match in matches:
pci_ids.add(match.lower())
else:
# Absolute fallback: Scan all cells but guard heavily against false-positive string matches
for cell in cells:
cell_text = cell.get_text(strip=True)
matches = re.findall(r'\b(?:0x)?([0-9a-fA-F]{4})\b', cell_text)
for match in matches:
# Only accept if the cell text is short (an ID cell) or explicitly contains 0x
if len(cell_text) < 15 or '0x' in cell_text.lower():
pci_ids.add(match.lower())
return sorted(list(pci_ids))
def main():
for url in URLS:
filename = get_filename_from_url(url)
ids = extract_pci_ids(url)
if ids:
with open(filename, 'w', encoding='utf-8') as f:
for pci_id in ids:
f.write(f"{pci_id}\n")
print(f"-> Successfully saved {len(ids)} IDs to {filename}\n")
else:
print(f"-> No IDs extracted for {url}. Skipping file write.\n")
if __name__ == "__main__":
main()