blob: d9ed4efb64546e35fc1682c3bc2321d95eadedb3 [file]
import os
import re
from urllib.request import urlopen, Request
from urllib.error import URLError
from bs4 import BeautifulSoup
SPEC_DIR = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"specifications",
)
ROOT_URL = "https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/"
# Targets to download
TARGETS = ['BAP', 'CAP', 'TMAP', 'HAP', 'PBP', 'MCP', 'CCP', 'MICP', 'VCP', 'ASCS', 'PACS', 'CSIS', 'CSIP', 'BASS', 'AICS']
def get_all_index_links():
print(f"Fetching directory listing from {ROOT_URL}...")
headers = {'User-Agent': 'Mozilla/5.0'}
try:
req = Request(ROOT_URL, headers=headers)
with urlopen(req, timeout=30) as response:
html_content = response.read()
soup = BeautifulSoup(html_content, 'html.parser')
links = []
for a in soup.find_all('a'):
href = a.get('href', '')
if "index-en.html" in href:
links.append(href)
return links
except URLError as e:
print(f"Error fetching root directory: {e}")
return []
def match_target(path, acronym):
pattern = re.compile(rf"(?:^|/|_|-)({acronym})(?:[._-]|html5)", re.IGNORECASE)
return bool(pattern.search(path))
def parse_version(path, acronym):
pattern = re.compile(rf"{acronym}_v(\d+(?:[.-]\d+)*)", re.IGNORECASE)
match = pattern.search(path)
if match:
return match.group(1).replace('-', '.')
return "0.0"
def get_latest_link(links, acronym):
target_links = [l for l in links if match_target(l, acronym)]
if not target_links:
return None
timestamp_pattern = re.compile(r"_(\d{10})/")
def sort_key(path):
version_str = parse_version(path, acronym)
version_parts = []
for x in version_str.split('.'):
try:
version_parts.append(int(x))
except ValueError:
version_parts.append(0)
timestamp_match = timestamp_pattern.search(path)
timestamp = int(timestamp_match.group(1)) if timestamp_match else 0
return (version_parts, timestamp)
sorted_links = sorted(target_links, key=sort_key, reverse=True)
return sorted_links[0]
def download_spec(name, relative_url):
url = ROOT_URL + relative_url
print(f"Downloading {name} from {url}...")
headers = {'User-Agent': 'Mozilla/5.0'}
try:
req = Request(url, headers=headers)
with urlopen(req, timeout=30) as response:
html_content = response.read()
# Create spec dir if not exists
os.makedirs(SPEC_DIR, exist_ok=True)
# Save HTML
html_path = os.path.join(SPEC_DIR, f"{name}.html")
with open(html_path, 'wb') as f:
f.write(html_content)
print(f"Saved HTML to {html_path}")
# Save Text/Markdown for searching
soup = BeautifulSoup(html_content, 'html.parser')
text_content = soup.get_text(separator='\n', strip=True)
md_path = os.path.join(SPEC_DIR, f"{name}.md")
with open(md_path, 'w', encoding='utf-8') as f:
f.write(text_content)
print(f"Saved Markdown to {md_path}")
except URLError as e:
print(f"Error downloading {name}: {e}")
except Exception as e:
print(f"An error occurred: {e}")
def main():
links = get_all_index_links()
if not links:
print("No links found.")
return
for target in TARGETS:
latest_link = get_latest_link(links, target)
if latest_link:
version = parse_version(latest_link, target)
name = f"{target}_v{version}" if version != "0.0" else target
if version == "0.0":
match = re.search(rf"(\d+)-{target}-html5", latest_link, re.IGNORECASE)
if match:
name = f"{target}_ID_{match.group(1)}"
download_spec(name, latest_link)
else:
print(f"No link found for {target}")
if __name__ == "__main__":
main()