Load additional extractor module .py files placed in ~/.config/youtube-dl/modules, $XDG_CACHE_HOME/youtube-dl/modules, or a directory specified with --module-dir
Modules can simply be placed in the directory without editing an __init__.py Modules are written as normal extractor modules and require no changes, (ie from .common import InfoExtractor, etc) as they're loaded into the youtube_dl.extractor. namespace
This commit is contained in:
parent
41c0d2f8cb
commit
ad02f392ff
@ -40,7 +40,7 @@ from .update import update_self
|
|||||||
from .downloader import (
|
from .downloader import (
|
||||||
FileDownloader,
|
FileDownloader,
|
||||||
)
|
)
|
||||||
from .extractor import gen_extractors, list_extractors
|
from .extractor import gen_extractors, list_extractors, add_extractors
|
||||||
from .YoutubeDL import YoutubeDL
|
from .YoutubeDL import YoutubeDL
|
||||||
|
|
||||||
|
|
||||||
@ -56,6 +56,10 @@ def _real_main(argv=None):
|
|||||||
|
|
||||||
parser, opts, args = parseOpts(argv)
|
parser, opts, args = parseOpts(argv)
|
||||||
|
|
||||||
|
|
||||||
|
from .autoload import load_dynamic_extractors
|
||||||
|
add_extractors( load_dynamic_extractors(opts.module_dir) )
|
||||||
|
|
||||||
# Set user agent
|
# Set user agent
|
||||||
if opts.user_agent is not None:
|
if opts.user_agent is not None:
|
||||||
std_headers['User-Agent'] = opts.user_agent
|
std_headers['User-Agent'] = opts.user_agent
|
||||||
@ -372,6 +376,7 @@ def _real_main(argv=None):
|
|||||||
'external_downloader_args': external_downloader_args,
|
'external_downloader_args': external_downloader_args,
|
||||||
'postprocessor_args': postprocessor_args,
|
'postprocessor_args': postprocessor_args,
|
||||||
'cn_verification_proxy': opts.cn_verification_proxy,
|
'cn_verification_proxy': opts.cn_verification_proxy,
|
||||||
|
'custommeta': opts.custommeta,
|
||||||
}
|
}
|
||||||
|
|
||||||
with YoutubeDL(ydl_opts) as ydl:
|
with YoutubeDL(ydl_opts) as ydl:
|
||||||
|
42
youtube_dl/autoload.py
Normal file
42
youtube_dl/autoload.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import os
|
||||||
|
import glob
|
||||||
|
import imp
|
||||||
|
from .compat import (
|
||||||
|
compat_expanduser,
|
||||||
|
compat_getenv,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
mdirs = [ os.path.dirname(__file__)+'/auto' ]
|
||||||
|
|
||||||
|
def confdirs():
|
||||||
|
cfg_home = compat_getenv('XDG_CONFIG_HOME') or compat_getenv('appdata') or os.path.join(compat_expanduser('~'), '.config')
|
||||||
|
|
||||||
|
if cfg_home:
|
||||||
|
cfg_dir = os.path.join(cfg_home, 'youtube-dl','modules')
|
||||||
|
if os.path.isdir(cfg_dir):
|
||||||
|
return [cfg_dir]
|
||||||
|
return []
|
||||||
|
|
||||||
|
def load_dynamic_extractors(module_dir=None):
|
||||||
|
mdirs.extend(confdirs())
|
||||||
|
if module_dir != None:
|
||||||
|
if not os.path.isdir(module_dir):
|
||||||
|
raise OSError('No such directory: '+module_dir)
|
||||||
|
mdirs.append(module_dir)
|
||||||
|
|
||||||
|
ret = {}
|
||||||
|
for mdir in mdirs:
|
||||||
|
files = glob.glob(mdir+"/*.py")
|
||||||
|
for f in [ os.path.basename(f)[:-3] for f in files]:
|
||||||
|
# force extractor namespace upon /any/path.py
|
||||||
|
fh, filename, desc = imp.find_module(f, [mdir])
|
||||||
|
module = imp.load_module('youtube_dl.extractor.'+f, fh, filename, desc)
|
||||||
|
|
||||||
|
for name in dir(module):
|
||||||
|
if name.endswith('IE') and name != 'GenericIE':
|
||||||
|
ci = getattr(module,name)
|
||||||
|
#globals()[name] = ci
|
||||||
|
ret[name] = ci
|
||||||
|
print('[autoload]: '+mdir+' '+f+': '+name)
|
||||||
|
return ret
|
@ -38,7 +38,7 @@ from .azubu import AzubuIE
|
|||||||
from .baidu import BaiduVideoIE
|
from .baidu import BaiduVideoIE
|
||||||
from .bambuser import BambuserIE, BambuserChannelIE
|
from .bambuser import BambuserIE, BambuserChannelIE
|
||||||
from .bandcamp import BandcampIE, BandcampAlbumIE
|
from .bandcamp import BandcampIE, BandcampAlbumIE
|
||||||
from .bbccouk import BBCCoUkIE
|
from .bbc import BBCCoUkIE, BBCNewsIE
|
||||||
from .beeg import BeegIE
|
from .beeg import BeegIE
|
||||||
from .behindkink import BehindKinkIE
|
from .behindkink import BehindKinkIE
|
||||||
from .beatportpro import BeatportProIE
|
from .beatportpro import BeatportProIE
|
||||||
@ -112,6 +112,7 @@ from .daum import DaumIE
|
|||||||
from .dbtv import DBTVIE
|
from .dbtv import DBTVIE
|
||||||
from .dctp import DctpTvIE
|
from .dctp import DctpTvIE
|
||||||
from .deezer import DeezerPlaylistIE
|
from .deezer import DeezerPlaylistIE
|
||||||
|
from .democracynow import DemocracynowIE
|
||||||
from .dfb import DFBIE
|
from .dfb import DFBIE
|
||||||
from .dhm import DHMIE
|
from .dhm import DHMIE
|
||||||
from .dotsub import DotsubIE
|
from .dotsub import DotsubIE
|
||||||
@ -256,6 +257,12 @@ from .karrierevideos import KarriereVideosIE
|
|||||||
from .keezmovies import KeezMoviesIE
|
from .keezmovies import KeezMoviesIE
|
||||||
from .khanacademy import KhanAcademyIE
|
from .khanacademy import KhanAcademyIE
|
||||||
from .kickstarter import KickStarterIE
|
from .kickstarter import KickStarterIE
|
||||||
|
from .kissanime import (
|
||||||
|
KissAnimeIE,
|
||||||
|
KissCartoonIE,
|
||||||
|
KissAnimePlaylistIE,
|
||||||
|
KissCartoonPlaylistIE,
|
||||||
|
)
|
||||||
from .keek import KeekIE
|
from .keek import KeekIE
|
||||||
from .kontrtube import KontrTubeIE
|
from .kontrtube import KontrTubeIE
|
||||||
from .krasview import KrasViewIE
|
from .krasview import KrasViewIE
|
||||||
@ -299,6 +306,7 @@ from .malemotion import MalemotionIE
|
|||||||
from .mdr import MDRIE
|
from .mdr import MDRIE
|
||||||
from .megavideoz import MegaVideozIE
|
from .megavideoz import MegaVideozIE
|
||||||
from .metacafe import MetacafeIE
|
from .metacafe import MetacafeIE
|
||||||
|
from .memri import MemriIE
|
||||||
from .metacritic import MetacriticIE
|
from .metacritic import MetacriticIE
|
||||||
from .mgoon import MgoonIE
|
from .mgoon import MgoonIE
|
||||||
from .minhateca import MinhatecaIE
|
from .minhateca import MinhatecaIE
|
||||||
@ -757,6 +765,7 @@ from .yandexmusic import (
|
|||||||
from .yesjapan import YesJapanIE
|
from .yesjapan import YesJapanIE
|
||||||
from .yinyuetai import YinYueTaiIE
|
from .yinyuetai import YinYueTaiIE
|
||||||
from .ynet import YnetIE
|
from .ynet import YnetIE
|
||||||
|
from .yospace import YospaceIE, ReutersIE
|
||||||
from .youjizz import YouJizzIE
|
from .youjizz import YouJizzIE
|
||||||
from .youku import YoukuIE
|
from .youku import YoukuIE
|
||||||
from .youporn import YouPornIE
|
from .youporn import YouPornIE
|
||||||
@ -814,3 +823,9 @@ def list_extractors(age_limit):
|
|||||||
def get_info_extractor(ie_name):
|
def get_info_extractor(ie_name):
|
||||||
"""Returns the info extractor class with the given ie_name"""
|
"""Returns the info extractor class with the given ie_name"""
|
||||||
return globals()[ie_name + 'IE']
|
return globals()[ie_name + 'IE']
|
||||||
|
|
||||||
|
|
||||||
|
def add_extractors(extractors):
|
||||||
|
for k, c in extractors.items():
|
||||||
|
globals()[k] = c
|
||||||
|
_ALL_CLASSES[:0] = [c]
|
||||||
|
@ -142,6 +142,10 @@ def parseOpts(overrideArguments=None):
|
|||||||
'--dump-user-agent',
|
'--dump-user-agent',
|
||||||
action='store_true', dest='dump_user_agent', default=False,
|
action='store_true', dest='dump_user_agent', default=False,
|
||||||
help='Display the current browser identification')
|
help='Display the current browser identification')
|
||||||
|
general.add_option(
|
||||||
|
'--module-dir',
|
||||||
|
dest='module_dir', default=None, metavar='DIR',
|
||||||
|
help='Load additional extractor modules from DIR. Modules are also loaded from $XDG_CACHE_HOME/youtube-dl/modules or ~/.config/youtube-dl/modules.')
|
||||||
general.add_option(
|
general.add_option(
|
||||||
'--list-extractors',
|
'--list-extractors',
|
||||||
action='store_true', dest='list_extractors', default=False,
|
action='store_true', dest='list_extractors', default=False,
|
||||||
@ -716,6 +720,16 @@ def parseOpts(overrideArguments=None):
|
|||||||
'--add-metadata',
|
'--add-metadata',
|
||||||
action='store_true', dest='addmetadata', default=False,
|
action='store_true', dest='addmetadata', default=False,
|
||||||
help='Write metadata to the video file')
|
help='Write metadata to the video file')
|
||||||
|
postproc.add_option(
|
||||||
|
'--custom-meta',
|
||||||
|
action='append', dest='custommeta', default=[], metavar='TAG=FORMAT',
|
||||||
|
help='Write specific information to a metadata tag.'
|
||||||
|
'Syntax: "tagname=string to add with %(format)s" '
|
||||||
|
'The formatting syntax is the same as output. '
|
||||||
|
'Example: --custom-meta "comment=%(webpage_url)s\\n%(description)s" will '
|
||||||
|
'add a line with the url, then the description in the "comment" tag. '
|
||||||
|
'Tags are format-specific, common ones include: artist, comment, title, copyright, uploader. '
|
||||||
|
'This can be invoked multiple times for different tags.')
|
||||||
postproc.add_option(
|
postproc.add_option(
|
||||||
'--metadata-from-title',
|
'--metadata-from-title',
|
||||||
metavar='FORMAT', dest='metafromtitle',
|
metavar='FORMAT', dest='metafromtitle',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user