#coding=utf-8 #!/usr/bin/python import sys sys.path.append('..') import json import re from base.spider import Spider class Spider(Spider): def getName(self): return "91Porn" def init(self, extend): self.baseUrl = "https://91porn.com" self.header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept-Language": "zh-CN,zh;q=0.9", "Referer": self.baseUrl + "/index.php" } self.cookies = {} # ✨ 核心改造:动态从 config.json 的 ext 参数中读取配置 self.username = "" self.password = "" self.email = "" try: if extend: extendDict = json.loads(extend) if isinstance(extend, str) else extend self.username = str(extendDict.get('username', '')).strip() self.password = str(extendDict.get('password', '')).strip() self.email = str(extendDict.get('email', '')).strip() except Exception: pass self.is_ready = False def safe_bypass_and_verify(self): if self.is_ready: return True try: rsp = self.fetch(self.baseUrl + "/email_verify.php", headers=self.header, timeout=5) self.cookies.update(rsp.cookies.get_dict()) self.cookies['language'] = 'cn_CN' self.cookies['CNAM'] = '1' # 如果外部没有配置邮箱,则直接作为普通游客会话放行 if not self.email: self.is_ready = True return True post_data = {"email": self.email, "recover": "Submit", "submit": "true"} v_hd = self.header.copy() v_hd["Content-Type"] = "application/x-www-form-urlencoded" v_hd["Referer"] = self.baseUrl + "/email_verify.php" rsp_v = self.post(self.baseUrl + "/email_verify.php", data=post_data, headers=v_hd, cookies=self.cookies, timeout=5) self.cookies.update(rsp_v.cookies.get_dict()) self.is_ready = True return True except Exception: self.is_ready = True return False def homeContent(self, filter): result = {} classList = [ {"type_name": "今日排行", "type_id": "hot"}, {"type_name": "最近更新", "type_id": "rp"}, {"type_name": "本月最热", "type_id": "md"} ] result['class'] = classList return result def homeVideoContent(self): return {'list': []} def categoryContent(self, cid, page, filter, ext): self.safe_bypass_and_verify() result = {'page': int(page), 'pagecount': 1, 'limit': 0, 'total': 0, 'list': []} page = int(page) url = self.baseUrl + "/v.php?category=" + cid + "&page=" + str(page) if cid == "hot": url = self.baseUrl + "/index.php" elif cid == "rp": url = self.baseUrl + "/v.php?next=watch&page=" + str(page) try: rsp = self.fetch(url, headers=self.header, cookies=self.cookies, timeout=5) html = self.html(rsp.text) items = html.xpath("//div[contains(@class, 'well')]") videos = [] for item in items: try: a_tag = item.xpath(".//a[contains(@href, 'view_video.php')]") if not a_tag: continue href = a_tag[0].get('href', '') v_match = re.search(r'viewkey=([a-zA-Z0-9]+)', href) if not v_match: continue vod_id = v_match.group(1) name_nodes = item.xpath(".//span[contains(@class, 'video-title')]/text()") vod_name = name_nodes[0].strip() if name_nodes else "精彩视频" img_nodes = item.xpath(".//img[contains(@class, 'img-responsive')]/@src") vod_pic = img_nodes[0].strip() if img_nodes else "" if vod_pic.startswith('//'): vod_pic = "https:" + vod_pic remark_nodes = item.xpath(".//span[@class='duration']/text()") vod_remarks = remark_nodes[0].strip() if remark_nodes else "完整版" videos.append({"vod_id": vod_id, "vod_name": self.cleanText(self.removeHtmlTags(vod_name)), "vod_pic": vod_pic, "vod_remarks": vod_remarks}) except: continue result['list'] = videos result['limit'] = len(videos) result['pagecount'] = page + 1 if len(videos) >= 10 else page except Exception: pass return result def detailContent(self, did): self.safe_bypass_and_verify() tid = did[0] url = self.baseUrl + "/view_video.php?viewkey=" + tid try: rsp = self.fetch(url, headers=self.header, cookies=self.cookies, timeout=5) html_text = rsp.text.replace('&', '&') root = self.html(html_text) title_nodes = root.xpath("//h4[contains(@class, 'login_register_header')]/text() | //title/text()") title = title_nodes[0].strip().replace(" - 91porn", "").strip() if title_nodes else "精彩视频" cover_nodes = root.xpath("//video/@poster") cover_pic = cover_nodes[0] if cover_nodes else "" real_video_url = "" strencode_match = re.search(r'strencode2\([\"\']([^\"\'\)]+)[\"\']\)', html_text) if strencode_match: ciphertext = strencode_match.group(1) try: from urllib.parse import unquote decrypted_html = unquote(ciphertext) except: import urllib decrypted_html = urllib.unquote(ciphertext) src_match = re.search(r"src=['\"]([^'\"]+)['\"]", decrypted_html) if src_match: real_video_url = src_match.group(1) if not real_video_url: src_nodes = root.xpath("//video/source/@src | //video/@src") if src_nodes: real_video_url = src_nodes[0] if not real_video_url: real_video_url = url vod = {"vod_id": tid, "vod_name": self.cleanText(self.removeHtmlTags(title)), "vod_pic": cover_pic, "type_name": "在线视频", "vod_content": "资源解析就绪", "vod_play_from": "91Porn秒解流", "vod_play_url": "直连资源源$" + real_video_url} return {'list': [vod]} except Exception: pass return {'list': []} def playerContent(self, flag, pid, vipFlags): need_parse = 1 if "view_video.php" in pid else 0 return {"url": pid, "header": self.header, "parse": need_parse} def searchContent(self, key, quick): return {'list': []} def searchContentPage(self, key, quick, page): return {'list': []} def isVideoFormat(self, url): pass def manualVideoCheck(self): pass def localProxy(self, params): return None def destroy(self): pass