You do not have permission to view the full content of this post. Log in or register now.
#EXTM3U
# Part 3 of 7 (streams 401 to 600)
#EXTINF:-1 group-title="DLHD 24/7",Astro Cricket
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D370&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Antena 3 Spain
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D531&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arena Sports Tenis Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D612&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",ACC Network USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D664&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",ãdül† Swim
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D295&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",A Sport PK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D269&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",AXN Movies Portugal
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D717&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arte DE
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D725&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",AXS TV USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D742&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",ABC NY USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D766&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Azteca 7 MX
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D844&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Altitude Sports
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D923&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Azteca Uno MX
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D934&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 5 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D940&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 6 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D941&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 7 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D942&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 8 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D943&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 9 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D944&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arena Sport 10 Serbia
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D945&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Arte France
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D958&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Automoto La chaîne
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D961&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Barca TV Spain
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D522&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Benfica TV PT
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D380&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Boomerang
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D648&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BNT 1 Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D476&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BNT 2 Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D477&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BNT 3 Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D478&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BR Fernsehen DE
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D737&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",bTV Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D479&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",bTV Action Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D481&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",bTV Lady Bulgaria
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D484&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BBC America (BBCA)
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D305&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BET USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D306&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Bravo USA
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D307&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BBC News Channel HD
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D349&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BBC One UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D356&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BBC Two UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D357&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BBC Three UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D358&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BBC Four UK
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D359&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BIG TEN Network (BTN USA)
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D397&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",BFM TV France
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D957&redirect_stream=true
#EXTINF:-1 group-title="DLHD 24/7",Bandsports Brasil
http://127.0.0.1:7860/extractor/video.m3u8?host=dlstreams&d=https%3A%2F%2Fdlhd.pk%2Fwatch.php%3Fid%3D275&redirect_stream=true
#!/usr/bin/env python3
"""
convert_m3u8.py
Converts an M3U8 playlist from DaddyLiveHD to the local extractor format.
Usage:
python convert_m3u8.py [input_file_or_url] [output_file]
If no input is given, reads from stdin.
If no output is given, prints to stdout.
"""
import sys
import re
import urllib.parse
from urllib.request import urlopen
from urllib.error import URLError
PROXY_BASE = "http://127.0.0.1:7860/extractor/video.m3u8"
HOST = "dlstreams"
REDIRECT = "true"
def convert_url(original_url):
"""Convert a dlhd.pk watch URL to the local proxy URL."""
# URL-encode the original URL for the 'd' parameter
encoded_d = urllib.parse.quote(original_url, safe='')
return f"{PROXY_BASE}?host={HOST}&d={encoded_d}&redirect_stream={REDIRECT}"
def process_m3u8(content):
"""Process each line of the M3U8 content."""
lines = content.splitlines()
out_lines = []
# Pattern to match the original stream URLs exactly
# We'll look for lines that are only the URL (no extra text)
# Typically in M3U8, URLs appear on their own line, but sometimes they might have whitespace.
# We'll match lines that start with http:// or https:// and contain dlhd.pk/watch.php
url_pattern = re.compile(r'^https?://dlhd\.pk/watch\.php\?id=\d+$')
for line in lines:
stripped = line.strip()
if url_pattern.match(stripped):
# Replace with the converted URL
out_lines.append(convert_url(stripped))
else:
out_lines.append(line)
return "\n".join(out_lines)
def read_input(source):
"""Read content from a file path, URL, or stdin."""
if source is None:
# Read from stdin
return sys.stdin.read()
# Check if it's a URL (starts with http:// or https://)
if source.startswith(('http://', 'https://')):
try:
with urlopen(source) as response:
return response.read().decode('utf-8')
except URLError as e:
sys.stderr.write(f"Error fetching URL: {e}\n")
sys.exit(1)
else:
# Treat as local file
try:
with open(source, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError as e:
sys.stderr.write(f"File not found: {e}\n")
sys.exit(1)
def main():
input_source = None
output_file = None
# Parse command line arguments
args = sys.argv[1:]
if len(args) >= 1:
input_source = args[0]
if len(args) >= 2:
output_file = args[1]
content = read_input(input_source)
converted = process_m3u8(content)
if output_file:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(converted)
else:
sys.stdout.write(converted)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
create_dlhd_playlist.py - Scrape dlhd.pk channels with rate-limit protection.
"""
import re
import sys
import time
import random
import requests
from datetime import datetime
from urllib.parse import urljoin, urlparse, parse_qs
# ---------- CONFIGURATION ----------
BASE_URL = "https://dlhd.pk"
MAX_CHANNELS = None # Set to integer to limit, e.g., 50
REQUEST_DELAY_MIN = 4.0 # Minimum seconds between requests
REQUEST_DELAY_MAX = 8.0 # Maximum seconds between requests
MAX_RETRIES = 5 # Retry attempts for a single URL
BACKOFF_FACTOR = 2 # Exponential backoff multiplier
# -----------------------------------
# Rotating user agents
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
]
def get_headers():
"""Return headers with a random User-Agent."""
return {
"User-Agent": random.choice(USER_AGENTS),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
}
def fetch_with_retries(session, url, retries=MAX_RETRIES, delay=1):
"""
Fetch a URL with exponential backoff and jitter.
Returns HTML string or None on persistent failure.
"""
headers = get_headers()
for attempt in range(1, retries + 1):
try:
resp = session.get(url, headers=headers, timeout=15)
resp.raise_for_status()
return resp.text
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
if attempt == retries:
print(f" [!] Failed after {retries} attempts: {e}")
return None
# Exponential backoff with jitter
sleep_time = (delay * (BACKOFF_FACTOR ** (attempt - 1))) + random.uniform(0, 1)
print(f" [Retry {attempt}/{retries}] Connection issue, waiting {sleep_time:.1f}s...")
time.sleep(sleep_time)
except requests.exceptions.RequestException as e:
# Non-retryable error (e.g., 404)
print(f" [!] Request error: {e}")
return None
return None
def extract_watch_links(html, base_url):
"""
Extract all watch.php?id=... links from HTML.
Returns a list of (channel_id, channel_name, full_url) tuples.
"""
links = set()
pattern = r'href\s*=\s*["\']([^"\']*watch\.php[^"\']*)["\']'
for match in re.finditer(pattern, html, re.IGNORECASE):
raw_url = match.group(1)
full_url = urljoin(base_url, raw_url)
parsed = urlparse(full_url)
params = parse_qs(parsed.query)
if 'id' in params:
cid = params['id'][0]
links.add((cid, f"Channel {cid}", full_url))
return list(links)
def get_channel_name(html, default_id):
"""Extract channel name from <title> tag."""
match = re.search(r'<title>(.*?)</title>', html, re.IGNORECASE | re.DOTALL)
if match:
title = match.group(1).strip()
title = re.sub(r'\s*[-|]\s*dlhd\..*$', '', title, flags=re.IGNORECASE)
title = re.sub(r'\s*[-|]\s*Watch\s*.*$', '', title, flags=re.IGNORECASE)
if title:
return title
return f"Channel_{default_id}"
def build_m3u8_playlist(channel_data):
"""Build M3U8 content from list of (name, url) tuples."""
lines = ["#EXTM3U"]
for name, url in channel_data:
clean_name = re.sub(r'\s+', ' ', name).strip()
lines.append(f'#EXTINF:-1,{clean_name}')
lines.append(url)
return "\n".join(lines)
def main():
print("=" * 60)
print("dlhd.pk - Generate M3U8 Playlist (Rate-Limit Protected)")
print("=" * 60)
# Use a session for connection reuse
session = requests.Session()
session.headers.update(get_headers())
# Step 1: Fetch main page
print(f"\n[1] Fetching main page: {BASE_URL}")
main_html = fetch_with_retries(session, BASE_URL)
if not main_html:
print("Failed to fetch main page. Exiting.")
sys.exit(1)
# Step 2: Extract watch.php links
print("[2] Extracting watch.php?id= links...")
channels = extract_watch_links(main_html, BASE_URL)
# Try alternative paths if needed
if not channels:
for path in ["/channels.php", "/index.php", "/home"]:
alt_url = urljoin(BASE_URL, path)
alt_html = fetch_with_retries(session, alt_url)
if alt_html:
channels = extract_watch_links(alt_html, alt_url)
if channels:
break
if not channels:
print("No watch.php links found. Site structure may have changed.")
sys.exit(1)
# Remove duplicates by id
seen = set()
unique = []
for cid, name, url in channels:
if cid not in seen:
seen.add(cid)
unique.append((cid, name, url))
print(f"[+] Found {len(unique)} unique channel(s).")
if MAX_CHANNELS and len(unique) > MAX_CHANNELS:
print(f"[!] Limiting to first {MAX_CHANNELS}.")
unique = unique[:MAX_CHANNELS]
# Step 3: Fetch each channel page for the title
print("\n[3] Fetching channel titles (with delays to avoid rate-limit)...")
channel_data = [] # (name, watch_url)
total = len(unique)
for idx, (cid, _, url) in enumerate(unique, 1):
print(f" [{idx}/{total}] ID {cid} ... ", end="", flush=True)
# Add random delay before each request (except maybe first)
if idx > 1:
delay = random.uniform(REQUEST_DELAY_MIN, REQUEST_DELAY_MAX)
time.sleep(delay)
page_html = fetch_with_retries(session, url)
if page_html:
name = get_channel_name(page_html, cid)
channel_data.append((name, url))
print("OK")
else:
# Fallback to generic name
channel_data.append((f"Channel_{cid}", url))
print("FAIL (using default name)")
# Step 4: Build and save playlist
print("\n[4] Building M3U8 playlist...")
playlist = build_m3u8_playlist(channel_data)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"dlhd_playlist_{timestamp}.m3u8"
with open(filename, "w", encoding="utf-8") as f:
f.write(playlist)
print(f"\n[+] Playlist saved to: {filename}")
print(f" Total entries: {len(channel_data)}")
print("\nDone.")
if __name__ == "__main__":
main()
You are welcome, Here is a script, which will fetch the events and 7/24 channels with proper names
#!/usr/bin/env python3
"""
dlhd_combined.py - Scrape dlhd.st (events) + dlhd.st/24-7-channels.php (permanent channels)
and generate a combined M3U8 playlist.
"""
import re
import sys
import time
import random
import requests
from datetime import datetime
from urllib.parse import urljoin, urlparse, parse_qs
try:
from bs4 import BeautifulSoup
except ImportError:
print("Install beautifulsoup4: pip install beautifulsoup4")
sys.exit(1)
# ---------- CONFIG ----------
MAIN_URL = "https://dlhd.st" # main page with events
CHANNELS_247_URL = "https://dlhd.st/24-7-channels.php" # 24/7 channels
MAX_CHANNELS = None # set to e.g., 100 to limit total entries
REQUEST_DELAY = 1.0 # seconds between page-title fetches (if used)
MAX_RETRIES = 3
# ---------------------------
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
]
def get_headers():
return {"User-Agent": random.choice(USER_AGENTS),
"Accept": "text/html,application/xhtml+xml",
"Accept-Language": "en-US,en;q=0.5"}
def fetch_url(session, url, retries=MAX_RETRIES):
for attempt in range(1, retries+1):
try:
resp = session.get(url, headers=get_headers(), timeout=15)
resp.raise_for_status()
return resp.text
except:
if attempt == retries:
return None
time.sleep(2 ** attempt + random.uniform(0,1))
return None
def is_generic(name):
"""Return True if name is likely generic (e.g., 'Tennis Stream')"""
name_lower = name.lower().strip()
generic_terms = {"tennis stream", "football stream", "basketball stream", "cricket stream",
"live stream", "watch", "stream", "channel", "sport", "event"}
for term in generic_terms:
if term in name_lower:
return True
if ' vs ' in name_lower or ':' in name or any(ord(c) > 0x1F000 for c in name):
return False
if len(name) < 8:
return True
return False
def extract_event_name_from_schedule_event(container, channel_name):
"""Extract event name from schedule__event container (used on main page)."""
header = container.find('div', class_=re.compile(r'schedule__eventHeader', re.I))
if header:
data_title = header.get('data-title')
if data_title:
cleaned = re.sub(r'^\d{1,2}:\d{2}\s*', '', data_title)
cleaned = re.sub(r'\s*' + re.escape(channel_name) + r'\s*$', '', cleaned, flags=re.I)
return cleaned.strip()
header_text = header.get_text(separator=' ', strip=True)
header_text = re.sub(r'^\d{1,2}:\d{2}\s*', '', header_text)
header_text = re.sub(r'\s*' + re.escape(channel_name) + r'\s*$', '', header_text, flags=re.I)
return header_text.strip()
full_text = container.get_text(separator=' ', strip=True)
full_text = re.sub(r'\s*' + re.escape(channel_name) + r'\s*', '', full_text, flags=re.I)
full_text = re.sub(r'\b\d{1,2}:\d{2}\b\s*', '', full_text)
return full_text.strip()
def extract_channels_from_page(html, base_url, is_247=False):
"""
Extract all watch.php links with best possible names.
If is_247=True, we assume the page is the 24/7 channels page,
where the names are likely the anchor text or title attribute.
"""
soup = BeautifulSoup(html, 'html.parser')
channels = []
for a in soup.find_all('a', href=True):
href = a['href']
if 'watch.php' not in href:
continue
full_url = urljoin(base_url, href)
parsed = urlparse(full_url)
params = parse_qs(parsed.query)
if 'id' not in params:
continue
cid = params['id'][0]
# For 24/7 page, just take the anchor text or title
if is_247:
name = a.get('title')
if not name:
name = a.get_text(strip=True)
if not name:
name = f"Channel {cid}"
channels.append((cid, name, full_url))
continue
# Otherwise, use the event-extraction logic (for main page)
# Try to find a schedule__event ancestor
container = a
found_event = False
for _ in range(6):
if container and container.name == 'div' and container.get('class') and 'schedule__event' in container.get('class'):
found_event = True
break
container = container.parent
if found_event:
channel_name = a.get_text(strip=True) or f"Channel {cid}"
event_name = extract_event_name_from_schedule_event(container, channel_name)
if not event_name:
event_name = channel_name
else:
# Fallback: use title or text
title_attr = a.get('title')
if title_attr:
event_name = title_attr.strip()
else:
event_name = a.get_text(strip=True)
if not event_name:
event_name = f"Channel {cid}"
channels.append((cid, event_name, full_url))
return channels
def get_page_title(session, url):
"""Fallback: fetch page title if needed (not used in this combined version)."""
# We'll keep it for completeness, but we won't call it by default.
pass
def main():
print("=" * 60)
print("dlhd.st - Combined: Events + 24/7 Channels")
print("=" * 60)
session = requests.Session()
session.headers.update(get_headers())
# 1. Scrape main page (events)
print(f"\n[1] Fetching main page: {MAIN_URL}")
main_html = fetch_url(session, MAIN_URL)
channels = []
if main_html:
print("[2] Extracting event channels...")
channels += extract_channels_from_page(main_html, MAIN_URL, is_247=False)
else:
print("Warning: Could not fetch main page.")
# 2. Scrape 24/7 channels page
print(f"\n[3] Fetching 24/7 channels page: {CHANNELS_247_URL}")
channels_247_html = fetch_url(session, CHANNELS_247_URL)
if channels_247_html:
print("[4] Extracting 24/7 channels...")
channels += extract_channels_from_page(channels_247_html, CHANNELS_247_URL, is_247=True)
else:
print("Warning: Could not fetch 24/7 channels page.")
if not channels:
print("No channels found from either source. Exiting.")
sys.exit(1)
# Deduplicate by id (keep first occurrence, which usually has better name)
seen = set()
unique = []
for cid, name, url in channels:
if cid not in seen:
seen.add(cid)
unique.append((cid, name, url))
print(f"[+] Found {len(unique)} unique channels (after merging).")
if MAX_CHANNELS and len(unique) > MAX_CHANNELS:
unique = unique[:MAX_CHANNELS]
print(f"[!] Limiting to {MAX_CHANNELS}.")
# (Optional) Refine generic names by fetching page titles – disabled for speed.
# If you want to enable, uncomment the loop below.
refined = []
for cid, name, url in unique:
# Simple cleanup
clean_name = re.sub(r'\s+', ' ', name).strip()
refined.append((clean_name, url))
# Build playlist
print("\n[5] Generating M3U8 playlist...")
m3u = ["#EXTM3U"]
for name, url in refined:
m3u.append(f'#EXTINF:-1,{name}')
m3u.append(url)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"dlhd_combined_{timestamp}.m3u8"
with open(filename, "w", encoding="utf-8") as f:
f.write("\n".join(m3u))
print(f"\n[+] Playlist saved to: {filename}")
print(f" Total entries: {len(refined)}")
print("Done.")
if __name__ == "__main__":
main()
If you can automate it in the repo, it would be great, maybe with huggingface or github actions, dlhd_combined.py now fetches all events and 7/24 streams together.Thanks for the info! Now I have to update the channels.
pwede ba sya sa ott?If you can automate it in the repo, it would be great, maybe with huggingface or github actions, dlhd_combined.py now fetches all events and 7/24 streams together.
This is an example playlist which includes everything for EasyProxy format. You do not have permission to view the full content of this post. Log in or register now.