mirror of
https://github.com/Viren070/MediaFusion.git
synced 2025-12-01 23:21:11 +01:00
209 lines
8.1 KiB
Python
209 lines
8.1 KiB
Python
import logging
|
|
import re
|
|
|
|
import scrapy
|
|
|
|
from utils.config import config_manager
|
|
from db.redis_database import REDIS_SYNC_CLIENT
|
|
|
|
|
|
class CommonTamilSpider(scrapy.Spider):
|
|
name = None
|
|
source = None
|
|
|
|
custom_settings = {
|
|
"ITEM_PIPELINES": {
|
|
"mediafusion_scrapy.pipelines.TorrentDownloadAndParsePipeline": 100,
|
|
"mediafusion_scrapy.pipelines.CatalogParsePipeline": 150,
|
|
"mediafusion_scrapy.pipelines.MovieStorePipeline": 200,
|
|
"mediafusion_scrapy.pipelines.SeriesStorePipeline": 300,
|
|
"mediafusion_scrapy.pipelines.RedisCacheURLPipeline": 400,
|
|
},
|
|
}
|
|
|
|
def __init__(
|
|
self,
|
|
pages: int = 1,
|
|
start_page: int = 1,
|
|
search_keyword: str = None,
|
|
scrap_catalog_id: str = "all",
|
|
*args,
|
|
**kwargs,
|
|
):
|
|
super(CommonTamilSpider, self).__init__(*args, **kwargs)
|
|
self.pages = pages
|
|
self.start_page = start_page
|
|
self.search_keyword = search_keyword
|
|
if scrap_catalog_id != "all" and "_" not in scrap_catalog_id:
|
|
self.logger.error(
|
|
f"Invalid catalog ID: {scrap_catalog_id}. Expected format: <language>_<video_type>"
|
|
)
|
|
return
|
|
self.scrap_catalog_id = scrap_catalog_id
|
|
logging.info(f"Scraping catalog ID: {self.scrap_catalog_id}")
|
|
self.redis = REDIS_SYNC_CLIENT
|
|
self.scraped_urls_key = f"{self.name}_scraped_urls"
|
|
self.catalogs = config_manager.get_scraper_config(self.name, "catalogs")
|
|
self.homepage = config_manager.get_scraper_config(self.name, "homepage")
|
|
self.supported_search_forums = config_manager.get_scraper_config(
|
|
self.name, "supported_search_forums"
|
|
)
|
|
|
|
def __del__(self):
|
|
self.redis.close()
|
|
|
|
def generate_forum_data(self):
|
|
data = []
|
|
link_prefix = f"{self.homepage}/index.php?/forums/forum/"
|
|
for language, catalog in self.catalogs.items():
|
|
for video_type, forum_ids in catalog.items():
|
|
scrap_links = (
|
|
[link_prefix + str(forum_id) for forum_id in forum_ids]
|
|
if isinstance(forum_ids, list)
|
|
else [link_prefix + str(forum_ids)]
|
|
)
|
|
for link in scrap_links:
|
|
for page in range(self.start_page, self.start_page + self.pages):
|
|
paginated_link = f"{link}/page/{page}/"
|
|
data.append((paginated_link, language, video_type))
|
|
return data
|
|
|
|
def start_requests(self):
|
|
if self.search_keyword:
|
|
# Construct the search URL and initiate search
|
|
search_url = f"{self.homepage}/index.php?/search/&q={self.search_keyword}&type=forums_topic&search_and_or=or&search_in=titles&sortby=relevancy"
|
|
yield scrapy.Request(search_url, self.parse_search_results)
|
|
else:
|
|
if self.scrap_catalog_id == "all":
|
|
for url, language, video_type in self.generate_forum_data():
|
|
yield scrapy.Request(
|
|
url,
|
|
self.parse_page_results,
|
|
meta={
|
|
"item": {
|
|
"language": language,
|
|
"video_type": video_type,
|
|
"source": self.source,
|
|
"expected_sources": [
|
|
self.source,
|
|
"Contribution Stream",
|
|
],
|
|
}
|
|
},
|
|
)
|
|
else:
|
|
language, video_type = self.scrap_catalog_id.split("_")
|
|
forum_ids = self.catalogs.get(language, {}).get(video_type)
|
|
if not forum_ids:
|
|
self.logger.error(f"Invalid catalog ID: {self.scrap_catalog_id}")
|
|
return
|
|
|
|
forum_links = (
|
|
[
|
|
f"{self.homepage}/index.php?/forums/forum/{forum_id}"
|
|
for forum_id in forum_ids
|
|
]
|
|
if isinstance(forum_ids, list)
|
|
else [f"{self.homepage}/index.php?/forums/forum/{forum_ids}"]
|
|
)
|
|
|
|
for forum_link in forum_links:
|
|
yield scrapy.Request(
|
|
forum_link,
|
|
self.parse_page_results,
|
|
meta={
|
|
"item": {
|
|
"language": language,
|
|
"video_type": video_type,
|
|
"source": self.source,
|
|
}
|
|
},
|
|
)
|
|
|
|
def parse_search_results(self, response):
|
|
movies = response.css("li[data-role='activityItem']")
|
|
for movie in movies:
|
|
movie_page_link = movie.css("a[data-linktype='link']::attr(href)").get()
|
|
if not movie_page_link:
|
|
continue
|
|
|
|
if not self.check_scraped_urls(movie_page_link):
|
|
yield response.follow(
|
|
movie_page_link,
|
|
self.parse_movie_page,
|
|
meta={
|
|
"item": {
|
|
"source": self.source,
|
|
"webpage_url": movie_page_link,
|
|
}
|
|
},
|
|
)
|
|
|
|
# Handling pagination
|
|
next_page_link = response.css("a[rel='next']::attr(href)").get()
|
|
if next_page_link:
|
|
yield response.follow(next_page_link, self.parse_search_results)
|
|
|
|
def parse_page_results(self, response):
|
|
movies = response.css("li[data-rowid]")
|
|
for movie in movies:
|
|
movie_page_link = movie.css("a[data-ipshover-target]::attr(href)").get()
|
|
if not movie_page_link:
|
|
continue
|
|
|
|
if not self.check_scraped_urls(movie_page_link):
|
|
item = response.meta["item"].copy()
|
|
item["webpage_url"] = movie_page_link
|
|
yield response.follow(
|
|
movie_page_link, self.parse_movie_page, meta={"item": item}
|
|
)
|
|
|
|
def check_scraped_urls(self, page_link):
|
|
if self.redis.sismember(self.scraped_urls_key, page_link):
|
|
self.logger.info(f"Skipping already scraped URL: {page_link}")
|
|
return True
|
|
return False
|
|
|
|
def parse_movie_page(self, response):
|
|
item = response.meta["item"].copy()
|
|
poster = response.css(
|
|
"div[data-commenttype='forums'] img::attr(data-src), div[data-commenttype='forums'] img::attr(src)"
|
|
).get()
|
|
created_at = response.css("time::attr(datetime)").get()
|
|
torrent_links = response.css("a[data-fileext='torrent']::attr(href)").getall()
|
|
|
|
if self.search_keyword:
|
|
forum_link = response.css("a[href*='forums/forum/']::attr(href)").get()
|
|
if not forum_link:
|
|
return
|
|
forum_id = re.search(r"forums/forum/([^/]+)/", forum_link).group(1)
|
|
language, video_type = self.supported_search_forums.get(
|
|
forum_id, {"language": None, "video_type": None}
|
|
).values()
|
|
if not language:
|
|
self.logger.error(f"Unsupported forum {forum_id}")
|
|
return
|
|
item.update({"language": language, "video_type": video_type})
|
|
|
|
if not torrent_links:
|
|
self.logger.warning(f"No torrents found for {response.url}")
|
|
self.redis.sadd(self.scraped_urls_key, response.url)
|
|
return
|
|
|
|
for torrent_link in torrent_links:
|
|
torrent_item = item.copy()
|
|
torrent_item.update(
|
|
{
|
|
"type": (
|
|
"series" if torrent_item["video_type"] == "series" else "movie"
|
|
),
|
|
"poster": poster,
|
|
"created_at": created_at,
|
|
"language": torrent_item["language"].title(),
|
|
"torrent_link": torrent_link,
|
|
"scraped_url_key": self.scraped_urls_key,
|
|
}
|
|
)
|
|
|
|
yield torrent_item
|