Proxies 随机提取MongoDB中的代理服务器字典

from random import choice,randint
from fake_useragent import UserAgent
from pymongo import MongoClient
from bson.binary import Binary
from datetime import datetime
import lxml.html
import requests
import time
import pickle


class MongoCache_Proxies(object):
    """
    数据库缓存
    """
    def __init__(self,client=None):
        """
        初始化函数
        :param client: 数据库链接
        """

        self.client = MongoClient('localhost',27017)
        self.db = self.client.IP_Proxies
        ip_proxies_ = self.db.Proxies
        self.db.Proxies.create_index('time')
        if self.db.Proxies.find().count() == 0:
            record = {"result": Binary(pickle.dumps({'http': 'http://localhost:80'})), 'time': datetime.now()}
            self.db.Proxies.update({'_id': 1}, {'$set': record}, upsert=True)


    def __setitem__(self, key, value):
        """
        向数据库中添加数据
        :param key: 缓存关键字
        :param value: 缓存内容
        :return:
        """
        # 将proxies 数据序列化,并转化为mongodb能够存储的格式存储起来
        record = {"result":Binary(pickle.dumps(value)),'time':datetime.now()}
        self.db.Proxies.update({'_id':key},{'$set':record},upsert=True)
    def __getitem__(self, item):
        """
        将缓存数据按照item作为key取出
        :param item:
        :return:
        """
        record = self.db.Proxies.find_one({'_id':item})
        if record:
            return pickle.loads(record['result'])
        else:
            raise KeyError(str(item) + 'does not exist')


    def __contains__(self, item):
        """
        当调用in,not in 会调用该方法判断对应网址是否在数据库的缓存中
        :param item: 下载的url链接
        :return:
        """
        try:
            self[item]
        except KeyError:
            return False
        else:
            return True

    def clear(self):
        self.db.Proxies.drop()

    def count_all(self):
        return self.db.Proxies.find().count()






class Random_Proxies(object):
    """
    从指定代理网址下载代理ip
    """

    def __init__(self):
        """
        初始化下载
        """
        _au = UserAgent()
        # 需要下载的代理网址的网址格式化处理,
        # 如果有特殊的规律需要自行添加占位符,方便后续处理
        self.url_base = 'https://www.xxxx/xxxxx/{}/'
        self.headers = {'UserAgent':_au.random}
        self.db = MongoCache_Proxies()

    def url_lists(self):
        """
        下载列表
        """
        # 处理格式化的网址,并返回列表
        return [self.url_base.format(i) for i in range(2,35)]

    def download_html(self,url_str):
        """
        下载页面
        :param url_str:
        :return:
        """
        result = requests.get(url_str,headers=self.headers,proxies=self.random_proxies())
        return result.content.decode('utf-8')
        # 有些网址获取后不能是使用utf-8解码,需要使用不同的解码格式或者不解码
        # return result.content.decode('gbk')

    def parse_lxml(self,html_str):
        """
        提取ip并拼接为指定格式
        :param html_str:
        :return:
        """
        ip_list = []
        html = lxml.html.fromstring(html_str)
        # ip和prot的xpath路径 
        # // 代表的是当前的位置,可以随意指定
        # table 表示标签
        # 下级标签用 / 隔开
        # td[@data-title="IP"]  表示 td标签中 属性名为data-title 值为"IP"的标签  用于筛选指定的标签下的内容
        # /text()  表示提取标签中的文档内容
        # 可以根据实际需要修改路径
        ip_data = html.xpath('//table/tbody/tr/td[@data-title="IP"]/text()')
        port_data = html.xpath('//table/tbody/tr/td[@data-title="PORT"]/text()')
        if not ip_data or not port_data:
            raise KeyError('ip list or port list is None!')

        for i in range(len(ip_data)-1):
            ip_str = ip_data[i] + ':' + port_data[i]
            ip_list.append(ip_str)
        return ip_list

    def save_ip_str(self,ip_list):
        """
        保存数据
        :return:
        """
        id_ = self.db.count_all()
        for i in ip_list:
            id_ += 1
            dict_ = {"http":"http://" + i}
            self.db[id_] = dict_

    def download(self):
        url_lists = self.url_lists()
        for i in url_lists:
            print('开始存储::::::', i)
            time.sleep(randint(2,5))
            html_str = self.download_html(i)
            ip_list = self.parse_lxml(html_str)
            self.save_ip_str(ip_list)
        print('下载完成')

    def random_proxies(self):
        """
        随机取出存储的proxies
        """
        return self.db[randint(1,self.db.count_all())]

def random_proxies():
    """
    生成随机的proxies
    :return: 随机的proxies 字典格式
    """
    self = Random_Proxies()
    return self.db[randint(1,self.db.count_all())]


# 测试
if __name__ == '__main__':
    cc = Random_Proxies()

    # 清空数据表中的内容
    # cc.db.clear()

    # 下载内容到数据表中
    # cc.download()

    # 随机生成5个数据,并查看类型
    for i in range(5):
        print(cc.random_proxies())
        print(type(cc.random_proxies()))

使用条件:安装了python MongoDB
文件保存为 .py 格式
先在本文保存的地方运行
cc.download()
下载数据到数据库中

在需要的地方导入
from 这个文件保存的名字 import random_proxies
然后直接使用 random_proxies() 会返回随机的proxies字典,如需保存可以赋值给其他变量即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值