Advertisement
Masoko

Trackers Scraping

Dec 23rd, 2017
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.56 KB | None | 0 0
  1. from bs4 import BeautifulSoup as bs
  2. from urllib.request import urlopen
  3. from flask_cache import Cache
  4. import time
  5. import yaml
  6. import os
  7. import requests
  8. import re
  9. import pickle
  10. import sys
  11.  
  12. from flask import Flask, render_template, flash, request, redirect, url_for, session, logging
  13. from wtforms import Form, StringField, TextAreaField, PasswordField, validators
  14.  
  15. from functools import wraps
  16.  
  17. app = Flask(__name__)
  18. cache = Cache(app,config={'CACHE_TYPE': 'simple'})
  19.  
  20. @app.route('/')
  21. def index():
  22.     return render_template('home.html')
  23.  
  24. @app.route('/generate/')
  25. def generate():
  26.     arenabg.save_list()
  27.     zamunda.save_list()
  28.     zelka.save_list()  
  29.     return render_template('home.html')
  30.  
  31. @cache.cached(timeout=50)
  32. @app.route('/poster_gallery/', defaults={'genre': 'All', 'year': 'All'})
  33. @app.route('/poster_gallery/<string:genre>/<string:year>')
  34. def poster_gallery(genre, year):
  35.     movies = arenabg.get_cached_list() + zamunda.get_cached_list() + zelka.get_cached_list()
  36.     filtered_movies, movies_count, serials_count, genres, years = prepare_torrents(movies, genre, year, 'movie')
  37.            
  38.     return render_template('poster_gallery.html',
  39.                             movies = filtered_movies,
  40.                             movies_count = movies_count,
  41.                             genres = genres,
  42.                             years = years,
  43.                             genre = genre,
  44.                             year = year
  45.                             )
  46.  
  47. @cache.cached(timeout=50)
  48. @app.route('/tv_serials/', defaults={'genre': 'All', 'year': 'All'})                           
  49. @app.route('/tv_serials/<string:genre>/<string:year>')
  50. def tv_serials(genre, year):
  51.     serials = arenabg.get_cached_list() + zamunda.get_cached_list() + zelka.get_cached_list()
  52.     filtered_serials, movies_count, serials_count, genres, years = prepare_torrents(serials, genre, year, 'serial')
  53.            
  54.     return render_template('tv_serials.html',
  55.                             movies = filtered_serials,
  56.                             serials_count = serials_count,
  57.                             genres = genres,
  58.                             years = years,
  59.                             genre = genre,
  60.                             year = year
  61.                             )
  62.                            
  63. def prepare_torrents(movies, genre, year, type):
  64.     movies = separate(movies, type)
  65.     movies = remove_dupl(movies)
  66.     movies = sorted(movies, key = getKey, reverse = True)
  67.     genres = get_genres(movies)
  68.    
  69.     filtered_movies = []
  70.     if genre == 'All':
  71.         filtered_movies = movies
  72.     else:
  73.         for movie in movies:
  74.             if genre in str(movie['Genre']):
  75.                 filtered_movies.append(movie)
  76.                
  77.     movies = filtered_movies
  78.    
  79.     filtered_movies = []
  80.     if year == 'All':
  81.         filtered_movies = movies
  82.     else:
  83.         for movie in movies:
  84.             if year in str(movie['Year']):
  85.                 filtered_movies.append(movie)
  86.    
  87.     years = get_years(movies)
  88.    
  89.     #debug vairables
  90.     movies_count = 0
  91.     serials_count = 0
  92.  
  93.     for movie in filtered_movies:
  94.         if movie['Type'] == 'movie':
  95.             movies_count += 1
  96.         else:
  97.             serials_count += 1
  98.    
  99.     return filtered_movies, movies_count, serials_count, genres, years
  100.  
  101. # returns movies or serials only
  102. def separate(movies, type):
  103.     separated = []
  104.     for movie in movies:
  105.         if movie['Type'] == type:
  106.             separated.append(movie)
  107.     return separated
  108.  
  109. # used for soring list of dics                         
  110. def getKey(item):
  111.     return item['imdbRating']
  112.        
  113. # Removes torrents with duplicate IMDB ID
  114. def remove_dupl(movies):
  115.     imdb_ids = []
  116.     unique_movies = []
  117.     for movie in movies:
  118.         if movie['Imdb_id'] in imdb_ids:
  119.             pass
  120.         else:
  121.             imdb_ids.append(movie['Imdb_id'])
  122.             unique_movies.append(movie)
  123.     return unique_movies
  124.    
  125. # build genres list
  126. def get_genres(movies):
  127.     geners = set()
  128.     for movie in movies:
  129.         for genre in movie['Genre']:
  130.             if len(genre) > 0:
  131.                 geners.add(genre.strip())
  132.     geners = list(geners)
  133.     geners.sort()
  134.     return geners
  135.  
  136. # build genres list
  137. def get_years(movies):
  138.     years = set()
  139.     for movie in movies:
  140.         if '–' in str(movie['Year']):
  141.             pass
  142.         else:
  143.             years.add(movie['Year'])
  144.     years = list(years)
  145.     years.sort(reverse=True)
  146.     return years   
  147.    
  148. #load configuratin variables
  149. CONFIG = open('config.yaml')
  150. CONFIG_DATA = yaml.safe_load(CONFIG)
  151.  
  152. FETCH_DELAY = CONFIG_DATA['fetch_delay']
  153. TRACKER_CACHE_FOLDER = CONFIG_DATA['tracker_cache_folder']
  154. IMDB_CACHE_FOLDER = CONFIG_DATA['imdb_cache_folder']
  155. DEBUG = CONFIG_DATA['debug']
  156. PAGES_TO_SCAN = CONFIG_DATA['pages_to_scan']
  157. MISSING_IMDB_POSTER = "/static/images/poster.jpg"
  158.  
  159. #arenabg.com
  160. ARENABG_FORM_DATA = CONFIG_DATA['arenabg_form_data']
  161. ARENABG_LOGIN_URL = CONFIG_DATA['arenabg_login_url']
  162. ARENABG_INTERNAL_URL = CONFIG_DATA['arenabg_internal_url']
  163.  
  164. #zamunda.net
  165. ZAMUNDA_INTERNAL_URL = CONFIG_DATA['zamunda_internal_url']
  166. ZAMUNDA_LOGIN_URL = CONFIG_DATA['zamunda_login_url']
  167. ZAMUNDA_FORM_DATA = CONFIG_DATA['zamunda_form_data']
  168.  
  169. #zelka.org
  170. ZELKA_INTERNAL_URL = CONFIG_DATA['zelka_internal_url']
  171. ZELKA_LOGIN_URL = CONFIG_DATA['zelka_login_url']
  172. ZELKA_FORM_DATA = CONFIG_DATA['zelka_form_data']
  173.  
  174. class Arenabg():
  175.  
  176.     tracker_urls_served = 0
  177.     imdb_urls_served = 0
  178.     total_movies = 0
  179.     def __init__(self, login_url, user_data):      
  180.         self.user_data = user_data
  181.         self.login_url = login_url
  182.         self.tracker_login_session = self.tracker_login()
  183.         self.tracker_name = self.login_url.split('/')[2]
  184.        
  185.     # create and return the torrent site login session 
  186.     def tracker_login(self):
  187.         tracker_login_session = requests.Session()
  188.         tracker_login_session.post(self.login_url, data=self.user_data)
  189.         return tracker_login_session
  190.        
  191.     #returns all torrent details urls
  192.     def get_movies(self):
  193.         subs_url = ARENABG_INTERNAL_URL + 'subtitles:1/page:'
  194.         bg_audio_url = ARENABG_INTERNAL_URL + 'audio:1/page:'
  195.         pageurls = []
  196.         for i in range(1, PAGES_TO_SCAN + 1 , 1):
  197.             pageurls.append(subs_url + str(i))
  198.         for i in range(1, PAGES_TO_SCAN + 1 , 1):
  199.             pageurls.append(bg_audio_url + str(i)) 
  200.            
  201.         urls = set()
  202.         for url in pageurls:
  203.             if DEBUG:
  204.                 print('Processing {} urls - current {}'.format(len(pageurls),url))
  205.                
  206.             self.tracker_urls_served += 1
  207.             response = self.tracker_login_session.get(url)
  208.             html = response.text
  209.             soup = bs(html, 'html.parser')
  210.             for link in soup.findAll('a',attrs={'class': 'torrent-link'}):
  211.                 urls.add('http://arenabg.com' + link['href'])  
  212.             time.sleep(FETCH_DELAY)
  213.            
  214.         self.total_movies = len(urls)
  215.         return urls
  216.        
  217.     #return the imdb-id of arenabg url
  218.     def get_movie_imdb_id(self, url):
  219.         self.tracker_urls_served += 1
  220.         file_name = re.sub('[^A-Za-z0-9]+', '', url)
  221.         try:
  222.             imdb_id = pickle.load(open(self.get_path() + '/arenabg/' + file_name, 'rb'))
  223.             return imdb_id         
  224.         except:
  225.             response = self.tracker_login_session.get(url)
  226.             html = response.text       
  227.             link = []
  228.             soup = bs(html, 'html.parser')
  229.             for link in soup.findAll('a'):
  230.                 if 'www.imdb.com' in str(link):
  231.                     pickle.dump(link['href'].split('/')[4],
  232.                                 open(self.get_path()
  233.                                 + '/arenabg/{}'.format(file_name), "wb"))
  234.                     imdb_id = link['href'].split('/')[4].strip()
  235.                     if imdb_id[:2] == 'tt':
  236.                         if DEBUG:
  237.                             print(imdb_id)
  238.                         return imdb_id
  239.                     else:
  240.                         print("invalid imdbid", imdb_id)
  241.                         return False
  242.        
  243.             pickle.dump( False, open(self.get_path()+ '/arenabg/'+ file_name, 'wb'))
  244.             time.sleep(FETCH_DELAY)
  245.            
  246.         return False
  247.    
  248.     @staticmethod
  249.     #returns script location path
  250.     def get_path():
  251.         return os.path.dirname(os.path.realpath(sys.argv[0]))
  252.  
  253.     #extract movie data from IMDB site
  254.     @staticmethod
  255.     def get_media_imdb(imdbid):
  256.         Arenabg.imdb_urls_served += 1
  257.         try:           
  258.             result = pickle.load(open(Arenabg.get_path()+ '/imdb/'+ imdbid, 'rb'))
  259.             new = False
  260.             return result, new         
  261.         except:
  262.             new = True
  263.             url = 'http://www.imdb.com/title/{}/'.format(imdbid)
  264.             try:
  265.                 soup = bs(urlopen(url), 'html.parser')
  266.                 time.sleep(FETCH_DELAY)
  267.             except:
  268.                 return None, False
  269.             # parse rating
  270.             ss = soup.findAll('span',attrs={'itemprop':'ratingValue'})
  271.             try:
  272.                 rating = str(ss).split(">")[1].split("<")[0]   
  273.             except:
  274.                 rating = 0
  275.             # parse poster
  276.             try:
  277.                 poster = soup.findAll('div',attrs={'class':'poster'})
  278.                 poster = str(poster).split('"')[9]
  279.             except:
  280.                 poster = MISSING_IMDB_POSTER       
  281.             # parse genre
  282.             gen = soup.findAll('div',attrs={'class':'subtext'})
  283.             x = bs(str(gen), "html.parser")
  284.             gen = x.findAll('span',attrs={'class':'itemprop'})
  285.             genre = re.sub('<[^<]+?>', '', str(gen))
  286.             genre = genre.strip('[').strip(']').strip(' ').split(",")
  287.             # parse title
  288.             t = soup.findAll('title')
  289.             title = t[0].get_text().split(' (')[0]
  290.             if len(title) < 1:
  291.                 return None, False
  292.             # parse year   
  293.             try:
  294.                 type = 'movie'
  295.                 title_year = soup.find('span', {'id': 'titleYear'}).find('a').get_text()               
  296.             except:
  297.                 type = 'serial'
  298.                 try:
  299.                     title_year = soup.find('a', {'title': 'See more release dates'})
  300.                     title_year = title_year.get_text().strip().split('(')[1].split(')')[0]
  301.                 except:
  302.                     try:
  303.                         title_year = str(soup.find('span', {'class': 'parentDate'})
  304.                                                     .get_text()
  305.                                                     .strip()
  306.                                                     )
  307.                         title_year = title_year.replace('(', '').replace(')', '')
  308.                     except:
  309.                         title_year = None
  310.                        
  311.             result = {'Imdb_id': imdbid, 'Type': type,
  312.                         'Year': title_year, 'Title': title,
  313.                         'imdbRating': rating, 'Poster': poster,
  314.                         'Genre': genre
  315.                         }
  316.             pickle.dump(result,
  317.                         open('{}/imdb/{}'.format(Arenabg.get_path(), imdbid),
  318.                         'wb' ))        
  319.         return result, new
  320.        
  321.     #returns a lists of movies with their imdb data
  322.     def get_list(self):
  323.         list = []
  324.         imdb_ids_list = []
  325.         for movie in self.get_movies():
  326.                 if DEBUG:
  327.                     print('total urls: {} - procesed urls: {} - imdb urls: {}'
  328.                         .format(self.total_movies,
  329.                                 self.tracker_urls_served,
  330.                                 self.imdb_urls_served))
  331.                 imdb_id = self.get_movie_imdb_id(movie)
  332.                 if imdb_id :
  333.                     if imdb_id in imdb_ids_list:
  334.                         pass
  335.                     else:
  336.                         movie_data, is_movie_new = self.get_media_imdb(imdb_id)
  337.                         if DEBUG:
  338.                             print(movie)
  339.                         if movie_data and imdb_id:
  340.                             movie_data['url'] = movie
  341.                             movie_data['New'] = is_movie_new
  342.                             list.append(movie_data)
  343.                             imdb_ids_list.append(imdb_id)
  344.         return list
  345.        
  346.     def save_list(self):
  347.         def getKey(item):
  348.             return item['imdbRating']
  349.         movies = sorted(self.get_list(), key=getKey, reverse = True)
  350. #       movies = self.get_list()
  351.         pickle.dump(movies, open(self.get_path()
  352.                                     + '/data/' + self.tracker_name, 'wb'))
  353.    
  354.     def get_cached_list(self):
  355.         result = pickle.load(open(Arenabg.get_path()
  356.                                     + '/data/' + self.tracker_name, 'rb'))
  357.         try:           
  358.             result = pickle.load(open(Arenabg.get_path()
  359.                                     + '/data/' + self.tracker_name, 'rb'))
  360.             return result
  361.         except:
  362.             return False
  363.  
  364.            
  365. class Zamunda(Arenabg):
  366.     #get tracker movies urls
  367.     def get_movies(self):
  368.         pageurls = []
  369.         #Builds a list of urls to be scanned - bg subs
  370.         for i in range(0, PAGES_TO_SCAN , 1):
  371.             pageurls.append(ZAMUNDA_INTERNAL_URL + '?field=name&bgsubs=1&page=' + str(i))
  372.         #Builds a list of urls to be scanned -  bg audio
  373.         for i in range(0, PAGES_TO_SCAN , 1):
  374.             pageurls.append(ZAMUNDA_INTERNAL_URL + '?field=name&bgaudio=1&page=' + str(i))
  375.         urls = set()
  376.         for url in pageurls: #gets the links from each url 
  377.             if DEBUG:
  378.                 print('Processing {} urls - current {}'.format(len(pageurls),url))
  379.                
  380.             response = self.tracker_login_session.get(url)
  381.             html = response.text
  382.             soup = bs(html, 'html5lib')
  383.             for link in soup.findAll('a',href=True):
  384.  
  385.                 if 'banan?id=' in link['href'] and 'javascript' not in link['href']:
  386.                     if not link['href'].startswith('/'):
  387.                         try:
  388.                             urls.add('http://zamunda.net/' + link['href'].split('&')[0])
  389.                         except:
  390.                             urls.add('http://zamunda.net/' + link['href'])
  391.             time.sleep(FETCH_DELAY)
  392.         self.total_movies = len(urls)  
  393.         return urls
  394.  
  395.  
  396. class Zelka(Arenabg):
  397.     #get tracker movies urls
  398.     def get_movies(self):
  399.         pageurls = []
  400.         for i in range(1, PAGES_TO_SCAN + 1, 1):
  401.             pageurls.append(ZELKA_INTERNAL_URL
  402.                             + '?page='
  403.                             + str(i)
  404.                             + '&sort=12&type=desc'
  405.                             )
  406.            
  407.         urls = set()
  408.         for url in pageurls:
  409.             if DEBUG:
  410.                 print('Processing {} urls - current {}'.format(len(pageurls),url))
  411.                
  412.             response = self.tracker_login_session.get(url)
  413.             html = response.text
  414.             soup = bs(html, 'html5lib')
  415.             # get all torrent details urls on the current page
  416.             for link in soup.findAll('a', href = True):
  417.                 if 'details.php?id=' in link['href'] and 'hit' not in link['href']:
  418.                     if 'userdetails' not in link['href']:
  419.                         urls.add('http://zelka.org/' + link['href'])   
  420.                        
  421.             time.sleep(FETCH_DELAY)
  422.         self.total_movies = len(urls)
  423.         return urls
  424.    
  425.    
  426. if __name__ == '__main__':
  427.    
  428.     arenabg = Arenabg(ARENABG_LOGIN_URL, ARENABG_FORM_DATA)
  429.     zamunda = Zamunda(ZAMUNDA_LOGIN_URL, ZAMUNDA_FORM_DATA)
  430.     zelka = Zelka(ZELKA_LOGIN_URL, ZELKA_FORM_DATA)
  431.     app.secret_key='secret123'
  432.     app.run(debug=True,host='0.0.0.0')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement