爬虫ip代理池分析使用

代码目录结构

https://github.com/Python3WebSpider/ProxyPool/

#文件目录组织结构
.
├── deployment.yml
├── docker-compose.yml
├── Dockerfile
├── error.log
├── examples
│   ├── __init__.py
│   └── usage.py
├── ingress.yml
├── LICENSE
├── proxypool
│   ├── crawlers
│   │   ├── base.py
│   │   ├── __init__.py
│   │   ├── private
│   │   │   ├── __init__.py
│   │   │   └── __pycache__
│   │   │       └── __init__.cpython-36.pyc
│   │   ├── public
│   │   │   ├── daili66.py
│   │   │   ├── data5u.py
│   │   │   ├── __init__.py
│   │   │   ├── ip3366.py
│   │   │   ├── iphai.py
│   │   │   ├── kuaidaili.py
│   │   │   ├── __pycache__
│   │   │   │   ├── daili66.cpython-36.pyc
│   │   │   │   ├── data5u.cpython-36.pyc
│   │   │   │   ├── __init__.cpython-36.pyc
│   │   │   │   ├── ip3366.cpython-36.pyc
│   │   │   │   ├── iphai.cpython-36.pyc
│   │   │   │   ├── kuaidaili.cpython-36.pyc
│   │   │   │   ├── xicidaili.cpython-36.pyc
│   │   │   │   ├── xiladaili.cpython-36.pyc
│   │   │   │   └── zhandaye.cpython-36.pyc
│   │   │   ├── xicidaili.py
│   │   │   ├── xiladaili.py
│   │   │   └── zhandaye.py
│   │   └── __pycache__
│   │       ├── base.cpython-36.pyc
│   │       └── __init__.cpython-36.pyc
│   ├── exceptions
│   │   ├── empty.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── empty.cpython-36.pyc
│   │       └── __init__.cpython-36.pyc
│   ├── __init__.py
│   ├── processors
│   │   ├── getter.py
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   │   ├── getter.cpython-36.pyc
│   │   │   ├── __init__.cpython-36.pyc
│   │   │   ├── server.cpython-36.pyc
│   │   │   └── tester.cpython-36.pyc
│   │   ├── server.py
│   │   └── tester.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── scheduler.cpython-36.pyc
│   │   └── setting.cpython-36.pyc
│   ├── scheduler.py
│   ├── schemas
│   │   ├── __init__.py
│   │   ├── proxy.py
│   │   └── __pycache__
│   │       ├── __init__.cpython-36.pyc
│   │       └── proxy.cpython-36.pyc
│   ├── setting.py
│   ├── storages
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   │   ├── __init__.cpython-36.pyc
│   │   │   └── redis.cpython-36.pyc
│   │   └── redis.py
│   └── utils
│       ├── __init__.py
│       ├── parse.py
│       ├── proxy.py
│       └── __pycache__
│           ├── __init__.cpython-36.pyc
│           ├── parse.cpython-36.pyc
│           └── proxy.cpython-36.pyc
├── README.md
├── requirements.txt
├── run.py
├── runtime.log
└── supervisord.conf

19 directories, 69 files

utils

utils 包含两个工具函数

parse.py解析redis的连接字符串,然后返回密码, ip 和port

python3
>>> import re
>>> connection_string = "redis://[redhat]@192.168.0.1:6379"
>>> result = re.match('rediss?://(.*?)@(.*?):(d+)', connection_string)
>>> result.group(2)
'192.168.0.1'
>>> result
<_sre.SRE_Match object; span=(0, 33), match='redis://[redhat]@192.168.0.1:6379'>        
>>> result.groups()
('[redhat]', '192.168.0.1', '6379')
>>> result.group(3)
'6379'
>>> result.group(1)
'[redhat]'
>>> result.group(0)
'redis://[redhat]@192.168.0.1:6379'

proxy.py 传入ip和端口,获取一个类,打印该类则输出ip:port

知识点 :https://www.attrs.org/en/stable/examples.html

pip3 install attrs cattrs
装了 attrs 和 cattrs 这两个库,但是实际导入的时候是使用 attr 和 cattr 这两个包,是不带 s 的

使用attrs 后的代码示例:

from attr import attrs, attrib

@attrs
class Color(object):
    r = attrib(type=int, default=0)
    g = attrib(type=int, default=0)
    b = attrib(type=int, default=0)

if __name__ == '__main__':
    color = Color(255, 255, 255)
    print(color)
    
    
##输出结果
Color(r=255, g=255, b=255)

attrs 这个修饰符起了作用,然后根据定义的 attrib 属性自动帮我们实现了 __init____repr____eq____ne____lt____le____gt____ge____hash__

示例:

##attrs 定义后的类
from attr import attrs, attrib

@attrs
class SmartClass(object):
    a = attrib()
    b = attrib()
    
    
    
##相当于已经实现了这些方法:
class RoughClass(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return "RoughClass(a={}, b={})".format(self.a, self.b)

    def __eq__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) == (other.a, other.b)
        else:
            return NotImplemented

    def __ne__(self, other):
        result = self.__eq__(other)
        if result is NotImplemented:
            return NotImplemented
        else:
            return not result

    def __lt__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) < (other.a, other.b)
        else:
            return NotImplemented

    def __le__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) <= (other.a, other.b)
        else:
            return NotImplemented

    def __gt__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) > (other.a, other.b)
        else:
            return NotImplemented

    def __ge__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) >= (other.a, other.b)
        else:
            return NotImplemented

    def __hash__(self):
        return hash((self.__class__, self.a, self.b))

参考:

https://cuiqingcai.com/6552.html

storages

此模块主要初始化redis连接并实现存储,随机获取,降级分数, ip数量,判断指定ip是否存在

知识点:

pyredis

注释

def random(self) -> Proxy:

声明函数后那个箭头:"->" 是返回值的注释,-> Proxy 意思即是提醒函数使用者返回值会是一个Proxy型
>>> def f(ham: "传一个字符串", eggs: str = 'eggs') -> str :
...     print("Annotations:", f.__annotations__)
...     print("Arguments:", ham, eggs)
...     return ham + ' and ' + eggs
... 
>>> 
>>> 
>>> 
>>> f("test", 123)
Annotations: {'eggs': <class 'str'>, 'ham': '传一个字符串', 'return': <class 'str'>}
Arguments: test 123
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in f
TypeError: Can't convert 'int' object to str implicitly
>>> f("test", "tt")
Annotations: {'eggs': <class 'str'>, 'ham': '传一个字符串', 'return': <class 'str'>}
Arguments: test tt
'test and tt'



##.__annotations__是函数的参数注释和返回值注释
##"->" 是返回值的注释,-> str 意思即是提醒函数使用者返回值会是一个str型

setting

配置代码需要的环境变量,日志配置

processor

模块内包含代理ip 获取器,可用代理api server, 代理ip 可用测试器

Getter

初始化redis 连接,获取抓取函数, log catch

loguru 貌似在setting里设置一次就行,项目根目录下, 整个项目会生效???

不了解,待测试, 貌似有全局变量,可以自动的联系起来

调用crawlers内的各个网站的特别的类获取代理

server

利用flask 提供API 获取分数最高的代理

tester

使用异步aiohttp 不断测试代理的可用性,不断调整代理的分数

知识点

argparse 参数添加

multiprocessing

pyredis

loguru

retrying

pkgutil

inspect

原文地址:https://www.cnblogs.com/g2thend/p/12553035.html