# VERSION: 1.1 # AUTHORS: BurningMop (burning.mop@yandex.com) # LICENSING INFORMATION # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import math import re from html.parser import HTMLParser from helpers import download_file, retrieve_url from novaprinter import prettyPrinter, anySizeToBytes class bitsearch(object): url = 'https://bitsearch.to' name = 'Bit Search' supported_categories = { 'all': 'all' } results_regex = r'\d+<\/b>' class MyHtmlParser(HTMLParser): def error(self, message): pass LI, DIV, H5, A = ('li', 'div', 'h5', 'a') def __init__(self, url): HTMLParser.__init__(self) self.magnet_regex = r'href=["\']magnet:.+?["\']' self.url = url self.row = {} self.column = 0 self.insideSearchResult = False self.insideInfoDiv = False self.insideName = False self.shouldGetName = False self.insideStatsDiv = False self.insideStatsColumn = False self.insideLinksDiv = False self.isValidInfo = False def handle_starttag(self, tag, attrs): params = dict(attrs) cssClasses = params.get('class', '') if tag == self.LI and 'search-result' in cssClasses: self.insideSearchResult = True return if self.insideSearchResult and tag == self.DIV and self.is_search_result(cssClasses): self.insideInfoDiv = True self.isValidInfo = True return if self.isValidInfo: if self.insideInfoDiv and tag == self.H5: self.insideName = True return if self.insideName and tag == self.A: self.shouldGetName = True href = params.get('href') link = f'{self.url}{href}' self.row['desc_link'] = link return if self.insideSearchResult and tag == self.DIV and 'stats' in cssClasses: self.insideStatsDiv = True return if self.insideStatsDiv and tag == self.DIV: self.insideStatsColumn = True self.column += 1 return if self.insideSearchResult and tag == self.DIV and 'links' in cssClasses: self.insideLinksDiv = True return if self.insideLinksDiv and tag == self.A and 'dl-magnet' in cssClasses: href = params.get('href') self.row['link'] = href self.insideLinksDiv = False return def handle_data(self, data): if self.shouldGetName: self.row['name'] = data.strip() self.shouldGetName = False return if self.insideStatsDiv: if not data.rstrip() == '': if self.column == 2: self.row['size'] = data.replace(' ', '') if self.column == 3: self.row['seeds'] = data if self.column == 4: self.row['leech'] = data return def handle_endtag(self, tag): if tag == self.H5 and self.insideName: self.insideName = False return if self.insideStatsDiv and not self.insideStatsColumn: self.insideStatsDiv = False self.insideInfoDiv = False return if self.insideStatsColumn and tag == self.DIV: self.insideStatsColumn = False return if tag == self.LI and self.insideSearchResult: self.row['engine_url'] = self.url if self.isValidInfo: prettyPrinter(self.row) self.insideSearchResult = False self.column = 0 return def is_search_result(self, classes): return 'info' in classes and 'px-3' in classes def download_torrent(self, info): print(download_file(info)) def search(self, what, cat='all'): parser = self.MyHtmlParser(self.url) what = what.replace('%20', '+') what = what.replace(' ', '+') page = 1 page_url = f'{self.url}/search?q={what}&page={page}' retrievedHtml = retrieve_url(page_url) results_matches = re.finditer(self.results_regex, retrievedHtml, re.MULTILINE) results_array = [x.group() for x in results_matches] if len(results_array) > 0: results = int(results_array[0].replace('', '').replace('', '')) pages = math.ceil(results / 20) else: pages = 0 page += 1 if pages > 0: parser.feed(retrievedHtml) while page <= pages: page_url = f'{self.url}/search?q={what}&page={page}' retrievedHtml = retrieve_url(page_url) parser.feed(retrievedHtml) page += 1 parser.close()