4 if sys.version_info[0] < 3:
5 from HTMLParser import HTMLParser
6 from urllib import urlopen, urlretrieve, urlencode
7 def get_encoding(info):
8 return info.getparam('charset')
11 from html.parser import HTMLParser
12 from urllib.request import urlopen, urlretrieve
13 from urllib.parse import urlencode
14 def get_encoding(info):
15 return info.get_content_charset('ascii')
20 def __init__(self, to_search, page_number):
21 self.host = "www.subdivx.com"
22 self.page = "/index.php"
23 self.down_page = "/bajar.php"
34 return 'http://%s%s?%s' % (self.host, self.page,
35 urlencode(self.query))
38 return self.page + '?' + urlencode(self.query)
41 return 'http://' + self.host + self.down_page
44 class SubDivXHTMLParser(HTMLParser):
49 def __init__(self, down_uri):
50 HTMLParser.__init__(self)
51 self.down_uri = down_uri
58 self.in_script_style = False
60 def handle_starttag(self, tag, attrs):
62 if tag == 'div' and attrs.get('id') == 'menu_detalle_buscador':
64 self.subs.append(self.cur)
68 if tag == 'script' or tag == 'style':
69 self.in_script_style = True
72 if attrs.get('id') == 'buscador_detalle':
74 elif attrs.get('id') == 'buscador_detalle_sub':
76 self.attr_depth = self.depth + 1
77 self.cur[self.attr] = ''
79 if attrs.get('class') == 'titulo_menu_izq':
81 self.attr_depth = self.depth + 1
82 self.cur[self.attr] = ''
83 elif attrs.get('href', '').startswith(self.down_uri):
84 self.cur['url'] = attrs['href']
85 # br are usually not closed, so ignore them in depth calculation
86 if self.parsing and tag != 'br':
89 def handle_endtag(self, tag):
91 if tag == 'script' or tag == 'style':
92 self.in_script_style = False
94 if self.depth == self.attr_depth:
97 # see comment in handle_starttag()
103 def handle_data(self, data):
107 # Hack to handle comments in <script> <style> which don't end
108 # up in handle_comment(), so we just ignore the whole tags
109 if self.in_script_style:
111 if self.attr is not None and data:
112 self.cur[self.attr] += ' ' + data
113 if self.attr_depth == 0:
114 self.cur[self.attr] = self.cur[self.attr].strip()
117 elif data in ('Downloads:', 'Cds:', 'Comentarios:', 'Formato:'):
118 self.attr = data[:-1].lower()
120 self.cur[self.attr] = ''
121 elif data == 'Subido por:':
124 self.cur[self.attr] = ''
128 self.cur[self.attr] = ''
131 def filter_subtitles(subs, filters):
132 def is_good(sub, filter):
133 def is_any_good(sub, filter):
134 for value in sub.values():
135 if value.lower().find(filter) >= 0:
139 if len(filter) > 2 and filter[1] == ':':
142 filter = filter.lower()
145 return is_any_good(sub, filter)
163 # Not a recognizer field identifier, use the raw filter
164 return is_any_good(sub, field + ':' + filter)
166 return sub[key].lower().find(filter) >= 0
173 for filter in filters:
174 if not is_good(sub, filter):
181 def subdivx_get_subs(query_str):
185 query = SubDivXQuery(query_str, page_number)
186 url = urlopen(query.url)
187 parser = SubDivXHTMLParser(query.down_uri)
190 encoding = get_encoding(url.info())
195 parser.feed(line.decode(encoding))
202 subs.extend(parser.subs)
205 return sorted(subs, key=lambda s: int(s['downloads']), reverse=True)
208 def get_subs(query_str, filters):
209 sub_exts = ('.srt', '.sub')
210 zip_exts = ('application/zip',)
211 rar_exts = ('application/rar', 'application/x-rar-compressed')
213 subs = subdivx_get_subs(query_str)
214 subs = filter_subtitles(subs, filters)
218 - %(titulo)s (%(autor)s - %(fecha)s - %(downloads)s - %(comentarios)s)
223 fname, headers = urlretrieve(sub['url'])
224 if 'Content-Type' in headers:
225 if headers['Content-Type'] in zip_exts:
226 z = zipfile.ZipFile(fname, 'r')
228 for fn in z.namelist():
229 if fn.endswith(sub_exts):
230 if '..' in fn or fn.startswith('/'):
231 print('Dangerous file name:', fn)
233 print('Extracting', fn, '...')
235 elif headers['Content-Type'] in rar_exts:
236 if subprocess.call(['rar', 'x', fname]) != 0:
237 print('Error unraring file %s' % fname)
239 print('Unrecognized file type:', headers['Content-Type'])
241 print('No Content-Type!')
244 get_subs(sys.argv[1], sys.argv[2:])