feat: customize similarity ratio
This commit is contained in:
parent
05b60ee779
commit
7a5a60defa
@ -15,7 +15,7 @@ This may **NOT** be 100% accurate.
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
```bash
|
```bash
|
||||||
python3 <path-to-script> -u "<logos URL>" -m "<m3u URL/path>"
|
python3 <path-to-script> -u "<logos URL>" -m "<m3u URL/path>" (-r <ratio>)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Supported logo providers
|
### Supported logo providers
|
||||||
@ -30,10 +30,11 @@ When everything is done, playlist file is **OVERWRITTEN**!
|
|||||||
|
|
||||||
### Example usage
|
### Example usage
|
||||||
```bash
|
```bash
|
||||||
python3 <path-to-script> -u "http://epg.ovh/logo" -m "m3u_list.m3u"
|
python3 <path-to-script> -u "http://epg.ovh/logo" -m "m3u_list.m3u" -r 0.7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Available parameters
|
### Available parameters
|
||||||
- -u/--url - logos source URL
|
- -u/--url - logos source URL
|
||||||
- -m/--m3u - URL/absolute path to m3u
|
- -m/--m3u - URL/absolute path to m3u
|
||||||
- -v/--verbose - enable verbose mode
|
- -v/--verbose - enable verbose mode
|
||||||
|
- -r/--ratio - customize similarity ratio
|
52
__main__.py
52
__main__.py
@ -15,11 +15,15 @@ def debug(message: str):
|
|||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print("[M3U-LOGO-MATCHER:DEBUG] " + message)
|
print("[M3U-LOGO-MATCHER:DEBUG] " + message)
|
||||||
|
|
||||||
|
def cutoff_extension(path: str):
|
||||||
|
return path[:path.rfind(".")]
|
||||||
|
|
||||||
def parse_arguments():
|
def parse_arguments():
|
||||||
parser = ArgumentParser()
|
parser = ArgumentParser()
|
||||||
parser.add_argument("-u", "--url", dest="url", help="URL to logos", required=True)
|
parser.add_argument("-u", "--url", dest="url", help="URL to logos", required=True)
|
||||||
parser.add_argument("-m", "--m3u", dest="m3u", help="Path to m3u file", required=True, type=Path)
|
parser.add_argument("-m", "--m3u", dest="m3u", help="Path to m3u file", required=True, type=Path)
|
||||||
|
parser.add_argument("-r", "--ratio", dest="ratio", help="Similarity ratio", default=0.6, type=float)
|
||||||
parser.add_argument("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true")
|
parser.add_argument("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true")
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
@ -33,7 +37,7 @@ def fetch_logos(base_logo_url: str):
|
|||||||
# Get logo names
|
# Get logo names
|
||||||
for logo in re.findall(r'<a href="(.+\..+)">(.*\..+)</a>', data):
|
for logo in re.findall(r'<a href="(.+\..+)">(.*\..+)</a>', data):
|
||||||
logo_url, channel_name = logo
|
logo_url, channel_name = logo
|
||||||
yield f"{base_logo_url}/{logo_url}", channel_name
|
yield f"{base_logo_url}/{logo_url}", cutoff_extension(channel_name)
|
||||||
|
|
||||||
def process(arguments):
|
def process(arguments):
|
||||||
debug("Processing...")
|
debug("Processing...")
|
||||||
@ -43,12 +47,21 @@ def process(arguments):
|
|||||||
print("No logos found! Ensure that the URL is correct and it returns a list of logo resources.")
|
print("No logos found! Ensure that the URL is correct and it returns a list of logo resources.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if arguments.ratio > 1 or arguments.ratio < 0:
|
||||||
|
print("Ratio must be between 0 and 1.")
|
||||||
|
return
|
||||||
|
|
||||||
# Get m3u data
|
# Get m3u data
|
||||||
debug(f"Loading m3u file {arguments.m3u}...")
|
debug(f"Loading m3u file {arguments.m3u}...")
|
||||||
playlist = tv_playlist.loadf(str(arguments.m3u))
|
playlist = tv_playlist.loadf(str(arguments.m3u))
|
||||||
debug(f"Loaded {playlist.length()} channels")
|
debug(f"Loaded {playlist.length()} channels")
|
||||||
|
|
||||||
matched_logos = list(match_similar_logos(logos, get_channels(playlist)))
|
matched_logos = list(match_similar_logos(
|
||||||
|
logos = logos,
|
||||||
|
channels = get_channels(playlist),
|
||||||
|
ratio = arguments.ratio
|
||||||
|
))
|
||||||
|
|
||||||
debug(f"Matched {len(matched_logos)}/{playlist.length()} logos.")
|
debug(f"Matched {len(matched_logos)}/{playlist.length()} logos.")
|
||||||
debug(f"Missing logos: {playlist.length() - len(matched_logos)}")
|
debug(f"Missing logos: {playlist.length() - len(matched_logos)}")
|
||||||
|
|
||||||
@ -93,33 +106,32 @@ def save_result(
|
|||||||
print("File overwritten.")
|
print("File overwritten.")
|
||||||
print("Thank you for using this script!")
|
print("Thank you for using this script!")
|
||||||
|
|
||||||
def match_similar_logos(logos: list[tuple[str, str]], channels: list[str]):
|
def match_similar_logos(
|
||||||
|
logos: list[tuple[str, str]],
|
||||||
|
channels: list[str],
|
||||||
|
ratio: float = 0.6
|
||||||
|
):
|
||||||
debug("Matching logos...")
|
debug("Matching logos...")
|
||||||
|
|
||||||
|
best_score = {}
|
||||||
|
best_match = {}
|
||||||
|
|
||||||
for channel in channels:
|
for channel in channels:
|
||||||
debug(f"Matching channel {channel}...")
|
debug(f"Matching channel {channel}...")
|
||||||
|
|
||||||
matched = False
|
|
||||||
match_score = 0
|
|
||||||
|
|
||||||
for logo in logos:
|
for logo in logos:
|
||||||
if matched:
|
debug(f"Trying logo {logo[0]}...")
|
||||||
break
|
|
||||||
|
|
||||||
logo_url, channel_name = logo
|
logo_url, channel_name = logo
|
||||||
score = get_similarity_ratio(channel, channel_name)
|
score = get_similarity_ratio(channel, channel_name)
|
||||||
|
|
||||||
if score > match_score:
|
if score > best_score.get(channel, 0) and score > ratio:
|
||||||
match_score = score
|
best_score[channel] = score
|
||||||
|
best_match[channel] = logo_url
|
||||||
if match_score > 0.5:
|
else:
|
||||||
debug(f"Matched {channel} with {logo_url} (ratio: {match_score})")
|
for channel, logo_url in best_match.items():
|
||||||
matched = True
|
debug(f"Matched {channel} with {logo_url} (ratio: {best_score[channel]})")
|
||||||
yield (channel, logo_url)
|
yield (channel, logo_url)
|
||||||
|
|
||||||
if not matched:
|
|
||||||
debug(f"No match for {channel}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
def get_channels(playlist: tv_playlist.M3UPlaylist):
|
def get_channels(playlist: tv_playlist.M3UPlaylist):
|
||||||
for channel in playlist:
|
for channel in playlist:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user