import requests
import urllib3
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
import csv
import os
import re

from urllib3 import HTTPSConnectionPool

from .配置 import 当前时间_时分, 项目_目录
from .数据连接 import 缓存数据库


class 爬虫常用配置:
    def __init__(self, 请求方式="get", 传入数据=None, 网页编码=None, 网页标题=True, 网页内容=False, 爬虫原数据=False,
                 数据保存=False, 特征识别=()):
        self.请求头 = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4029.0 Safari/537.36',
        }
        self.传入数据 = 传入数据
        self.请求方式 = 请求方式
        self.网页编码 = 网页编码
        self.网页标题 = 网页标题
        self.网页内容 = 网页内容
        self.爬虫原数据 = 爬虫原数据
        self.数据保存 = 数据保存
        self.特征识别 = 特征识别

    def 进行_特征识别(self, 页面数据):
        是否保留, 特征信息 = self.特征识别
        try:
            数据 = str(页面数据.encode("utf-8"))
        except:
            数据 = str(页面数据.encode("gbk"))
        特征 = re.search(特征信息, 数据)
        if 是否保留:
            return False if 特征 else True
        return False if not 特征 else True

    def 运行(self, 测试地址, 证书验证=True, 重试次数=3):
        返回内容 = {'测试地址': 测试地址}
        # 先使用head访问下排除一些报错
        重试_数据 = requests.Session()
        # 添加重试
        重试_数据.mount('http://', HTTPAdapter(max_retries=重试次数))
        重试_数据.mount('https://', HTTPAdapter(max_retries=重试次数))
        try:
            数据 = 重试_数据.head(测试地址, data=self.传入数据, headers=self.请求头)
            返回内容['状态码'] = 数据.status_code
        # 证书报错
        except requests.exceptions.SSLError:
            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
            返回内容["备注"] = "[注意]此网站证书可能异常"
            证书验证 = False
        if self.请求方式 == "get":
            数据 = 重试_数据.get(测试地址, headers=self.请求头, verify=证书验证)
        elif self.请求方式 == "post":
            数据 = 重试_数据.post(测试地址, data=self.传入数据, headers=self.请求头, verify=证书验证)
        elif self.请求方式 == "head":
            return 返回内容
        else:
            返回内容["备注"] = "当前仅支持get、post和head请求"
            return 返回内容
        返回内容['状态码'] = 数据.status_code
        数据.encoding = self.网页编码
        格式化数据 = BeautifulSoup(数据.text, 'lxml')
        if self.特征识别 != ():
            if self.进行_特征识别(格式化数据):
                return False
        if self.网页标题:
            if 格式化数据.title and 格式化数据.title.string:
                返回内容["网页标题"] = 格式化数据.title.string.replace('\n', '').replace('\r', '').replace('\t', '')
            else:
                返回内容["网页标题"] = "[无网页标题!此是脚本生成的填位符]"
        if 数据.url != 测试地址:
            返回内容["状态码"] = f"{数据.status_code}, 原:{[i.status_code for i in 数据.history]}"
            # 返回内容["测试地址"] = f"{数据.url}, {[i.url for i in 数据.history]}"
            返回内容["测试地址"] = 数据.url
        if self.网页内容:
            if 数据.text:
                返回内容["网页内容"] = 数据.text
            else:
                返回内容["网页内容"] = "[无网页内容!此是脚本生成的填位符]"
        if self.爬虫原数据:
            返回内容["爬虫原数据"] = 数据
        if self.数据保存:
            文件名 = "{}爬虫模板保存数据({}).csv".format(self.请求方式, 当前时间_时分)
            保存位置 = os.path.join(项目_目录, f"脚本生成数据\\{文件名}")
            保存内容 = 返回内容.copy()
            if self.爬虫原数据:
                保存内容.pop("爬虫原数据")
            if not os.path.exists(保存位置):
                with open(保存位置, "a+") as 写入:
                    写入csv = csv.writer(写入)
                    写入csv.writerow(list(保存内容.keys()))
            with open(保存位置, "a+") as 写入:
                if self.网页内容:
                    if 返回内容["状态码"] != 200:
                        保存内容["网页内容"] = "[为了更好地显示效果!状态码为200时才会显示]"
                    elif len(保存内容["网页内容"]) >= 500:
                        保存内容["网页内容"] = "[为了更好地显示效果!内容长度较少时才会显示]"
                    else:
                        保存内容["网页内容"] = 数据.text.replace('\n', '').replace('\r', '').replace('\t', '')
                        if not 保存内容["网页内容"]:
                            返回内容["网页内容"] = "[无网页内容!此是脚本生成的填位符]"
                写入csv = csv.writer(写入)
                写入csv.writerow(list(保存内容.values()))
        return 返回内容


if __name__ == '__main__':
    # get形式的参数
    # get参数 = urllib.parse.urlencode({"id": 2, "method": "system.listMethods", "params": ["2"]})
    # post传参测试
    # post参数 = '{"id": 2, "method": "system.listMethods", "params": ["2"]}'
    # 测试 = 爬虫常用配置("post", post参数, 网页内容=True).运行("http://www.wsyu.edu.cn/JSON-RPC")
    # 常规测试
    测试 = 爬虫常用配置(网页内容=True, 数据保存=True, 特征识别=(True, 'src="/images/fof.jpg"')).运行("http://bhi.edu.cn/admin")
    # print(测试)
    pass
