爬取免费代理,拥有自己的代理池
掌控安全学院
2021年10月25日 17:35

作者:掌控安全-秋紫山

很久很久以前,我有个梦想,就是SQL注入不要被ban,于是ip代理成为了首选,但是奈何钱包有限,只能爬取免费代理,于是借鉴了许多文章,形成了今日的ip代理池。

python编写,内容主要涉及多线程问题、以及爬虫。

一、具体实现流程:

包括三个模块: 获取ip代理模块(爬虫获取ip),代理池模块(实现存储爬取的ip,写入有效ip代理),验证模块(对爬取的ip进行验证),获取模块(获取有效ip,并去重!)。

二、代码分析:(按程序执行顺序)代码分析:(按程序执行顺序)

(一)、入口文件:StartApi.py

1.Init: 获取必要的参数。

2.getproxy: 调用module.GetProxy,多线程使用exec函数,实例化

3.module.GetProxy下的类,开始爬虫获取代理ip。

4.isproxy:调用module.IsProxy和module.OptPool类,循环判断获取代理池的ip,并进行判断。

startproxy:程序入口函数,三个模式:

-c api 可获取已爬取存在ips.txt的有效代理0ip;

-t 100 100个多线程各个爬虫爬取一次获取有效代理;

-t 50 -m 1 -time 10 50个多线程无限次循环爬取有效ip,并且每10分钟进行循环。

具体代码如下:

  1. # -*- coding:utf-8 -*-

  2. # Author:qiuzishan

  3. import module.GetProxy

  4. from module.OptPool import ProxyPool

  5. from module.IsProxy import IsProxy

  6. from threading import Thread

  7. import time

  8. from queue import Queue

  9. from argparse import ArgumentParser

  10. from module.GetApi import GetApi

  11. class StartApi:

  12.    def __init__(self):

  13.        arg = ArgumentParser(description='baidu_url_collection&#​39;)

  14.        arg.add_argument('-t&#​39;, help='线程数量 默认10个线程&#​39;, type=int, default=10)

  15.        arg.add_argument('-c&#​39;, help='默认爬取ip进行验证 -c api 即可获取ips.txt的ip值!', type=str, default=&#​39;getproxy')

  16.        arg.add_argument('-m&#​39;, help='默认只爬取一次,-m 1 可实现无线循环,默认8分钟爬取一次', type=int, default=0)

  17.        arg.add_argument('-time&#​39;, help='默认8分钟爬取一次,-m 10 实现每10分钟爬取一次,搭配-m使用,最好不低于5分钟', type=int, default=8)

  18.        args = arg.parse_args()

  19.        self.que = Queue()

  20.        self.c = args.c

  21.        self.t = args.t  # 获取线程!!!这很重要!

  22.        self.m = args.m

  23.        self.time = args.time

  24.    def getproxy(self):

  25.        '&#​39;'

  26.        有几个代理,就会有几个线程爬取代理!

  27.        :param msg:

  28.        :return: 循环获取代理,这里可以加入获取代理的实例

  29.        '&#​39;'

  30.        thread = []

  31.        usemodels = ['BeautifulSoup&#​39;, 'ProxyPool&#​39;, '__builtins__&#​39;, '__cached__&#​39;, '__doc__&#​39;, '__file__&#​39;, '__loader__&#​39;, '__name__&#​39;, '__package__&#​39;, '__spec__&#​39;, 'datetime&#​39;, 're&#​39;, 'requests&#​39;, 'time&#​39;]

  32.        getmodels = dir(module.GetProxy)

  33.        for i in getmodels:

  34.            if i not in usemodels:

  35.                # 用于测试是否存在代理print(i)

  36.                self.que.put('import module.GetProxy\nmodule.GetProxy.' + i + &#​39;()')

  37.        proxyNum = self.que.qsize()  # 有几个爬虫就开启几个线程

  38.        for i in range(0, proxyNum):

  39.            t = Thread(target=exec, args=(self.que.get(),))

  40.            thread.append(t)

  41.        for i in thread:

  42.            i.start()

  43.            # print(f&#​39;线程数:{i}开始')

  44.        for i in thread:

  45.            i.join()

  46.    def isproxy(self, msg):

  47.        "&#​34;"

  48.        :return: 循环判断代理

  49.        "&#​34;"

  50.        pp = ProxyPool()

  51.        ip = IsProxy(self.t)

  52.        print(msg)

  53.        while True:

  54.            flag = pp.get_length_pool()

  55.            if flag == 0:

  56.                print("退出循环&#​34;)

  57.                break  # 退出循环

  58.            ip.startIsProxy()

  59.    def startproxy(self):

  60.        '&#​39;'

  61.        多进程同时运行

  62.        '&#​39;'

  63.        if self.c == 'api&#​39;:

  64.            ga = GetApi()

  65.            ga.start(self.t)

  66.        else:

  67.            if self.m:

  68.                while True:

  69.                    getproxy = Thread(target=self.getproxy)

  70.                    isproxy = Thread(target=self.isproxy, args=('代理判断中&#​39;,))

  71.                    getproxy.start()

  72.                    time.sleep(5)  # IpPool一开始无数据,因此先爬取加入IpPool列表中,防止出错

  73.                    isproxy.start()

  74.                    time.sleep(self.time*60)  # 每隔多长时间爬取一次

  75.            else:

  76.                getproxy = Thread(target=self.getproxy)

  77.                isproxy = Thread(target=self.isproxy, args=('代理判断中&#​39;,))

  78.                getproxy.start()

  79.                time.sleep(5)  # IpPool一开始无数据,因此先爬取加入IpPool列表中,防止出错

  80.                isproxy.start()

  81.                getproxy.join()

  82.                isproxy.join()

  83. if __name__ == '__main__&#​39;:

  84.    print('&#​39;'

  85.        III                        pppppppp                                      lll

  86.        III                        pp     pp                                     lll

  87.        III                        pp      pp                                    lll

  88.        III  pppppppp              pp     pp        OOOOOOO        OOOOOOO       lll

  89.        III  pp     pp             pppppppp        OO      OO     OO      OO     lll

  90.        III  pp      pp            pp             OO        OO   OO        OO    lll

  91.        III  pp     pp             pp             OO        OO   OO        OO    lll

  92.        III  pppppppp   _________  pp              OO      OO     OO      OO     lll

  93.             pp                    pp               OOOOOOOO       OOOOOOOO      lll

  94.             pp

  95.             pp         {v 1.0 author:秋紫山 QQ:644976520 欢迎加q交流~~}

  96.             pp

  97.    '&#​39;')

  98.    start = time.perf_counter()

  99.    sa = StartApi()

  100.    sa.startproxy()

  101.    end = time.perf_counter()

  102.    print("use time:&#​34;+str(end - start) + "s&#​34;)

(二)爬取代理ip: module/GetProxy.py

自定义爬虫类:

1.Init:不需要改变,把print的内容稍微改改即可,实现实例化即可启动该爬虫,并把获取的爬虫加入代理池ProxyPool里面

2.get_lxml_by_url:获取需要爬取页面的内容

3.get_proxy_by_lxml:自定义的爬虫,需要返回ip列表。

具体代码:

例如ip88Proxy

  1. # -*- coding:utf-8 -*-

  2. # Author:qiuzishan

  3. import requests

  4. from bs4 import BeautifulSoup

  5. from module.OptPool import ProxyPool

  6. import time

  7. import re

  8. '&#​39;'

  9. 这里可以定义多个代理类,只要保证以“**.**.**.**:**”形式如池即可,然后在getproxy.py中加入多线程即可。

  10. '&#​39;'

  11. class demoProxy:  # demo

  12.    '&#​39;'

  13.    Get Agent from web 89ip

  14.    '&#​39;'

  15.    def __init__(self):  # 自动爬取并且把ip输入代理池!此段函数不需要更改,print 的内容更改一下即可

  16.        self.proxy = []

  17.        try:

  18.            print("demo代理开始爬取&#​34;)

  19.            self.proxy = self.get_proxy_by_lxml(self.get_lxml_by_url())

  20.        except Exception as e:

  21.            print("出错了:{}\n~aha代理demo凉了,求你了快去看看吧!".format(e))

  22.        if self.proxy != []:

  23.            pp = ProxyPool()

  24.            for p in self.proxy:

  25.                pp.get_into_pool(p)

  26.        else:

  27.            print("demo代理爬取的代理ip为空!代理可能凉了!&#​34;)

  28.    def get_lxml_by_url(self):

  29.        headers = {

  30.                'User-Agent&#​39;: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'

  31.                }

  32.        r = requests.get('&#​39;, headers=headers)  # 输入需要爬取的网站!

  33.        if r.status_code == 200:

  34.            response = r.text

  35.            return response

  36.        else:

  37.            exit('Error: Module GetAgent Url Error')

  38.    def get_proxy_by_lxml(self, response):

  39.        ip = []

  40.        # 爬取你的代理包括端口噢,例如,123.12.2.33:8080,然后放进ip列表里。

  41.        # 请输入您的爬虫~

  42.        # print(ip)

  43.        return ip

  44. class ip89Proxy:  # 89ip

  45.    '&#​39;'

  46.    Get Agent from web 89ip

  47.    '&#​39;'

  48.    def __init__(self):

  49.        self.proxy = []

  50.        try:

  51.            print("89ip代理开始爬取&#​34;)

  52.            self.proxy = self.get_proxy_by_lxml(self.get_lxml_by_url())

  53.        except Exception as e:

  54.            print("出错了:{}\n~aha代理89ip凉了,求你了快去看看吧!".format(e))

  55.        if self.proxy != []:

  56.            pp = ProxyPool()

  57.            for p in self.proxy:

  58.                pp.get_into_pool(p)

  59.        else:

  60.            print("89ip代理爬取的代理ip为空!代理可能凉了!&#​34;)

  61.    def get_lxml_by_url(self):

  62.        headers = {

  63.                'User-Agent&#​39;: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'

  64.                }

  65.        r = requests.get('https://www.89ip.cn/tqdl.html?num=200&address=&kill_address=&port=&kill_port=&isp=', headers=headers)

  66.        if r.status_code == 200:

  67.            response = r.text

  68.            return response

  69.        else:

  70.            print('Error: Module GetAgent Url Error')

  71.    def get_proxy_by_lxml(self, response):

  72.        ip = []

  73.        soup = BeautifulSoup(response, 'html5lib&#​39;)

  74.        soup.find_all('div&#​39;)

  75.        for div in soup.find_all('div&#​39;, style="padding-left:20px;&#​34;):

  76.            for child in div.children:

  77.                if child.string is not None:

  78.                    if '更好用的代理ip请访问&#​39; not in child.string:

  79.                        ip.append(child.string.strip())

  80.        # print(ip)

  81.        return ip

(三)ip加入代理池: module/OptPool.py

相信很容易看懂!

  1. # -*- coding:utf-8 -*-

  2. # Author:qiuzishan

  3. from queue import Queue

  4. # IpPool存储所有未检验的代理,Proxy用于存储可用的代理

  5. IpPool = Queue()

  6. Proxy = Queue()

  7. class ProxyPool:

  8.    '&#​39;'

  9.    代理池!

  10.    '&#​39;'

  11.    def get_into_pool(self, args):  # 放进代理池一个ip

  12.        '&#​39;'

  13.        :param args:

  14.        :return: unknown IP warehousing

  15.        '&#​39;'

  16.        IpPool.put(args)

  17.    def get_length_pool(self):  # 返回代理池未验证的ip数量

  18.        return IpPool.qsize()

  19.    def get_out_pool(self):  # 取得代理池一个ip

  20.        '&#​39;'

  21.        :return: unknown IP outgoing

  22.        '&#​39;'

  23.        if IpPool.qsize():

  24.            getip = IpPool.get()

  25.            return getip

  26.        else:

  27.            print("IpPool变量无代理ip未检测&#​34;)

  28.            return 0  # 防止报错

  29.    def get_into_proxy(self, args):  # 写入有效ip

  30.        '&#​39;'

  31.        :param args:

  32.        :return: effective IP warehousing

  33.        '&#​39;'

  34.        Proxy.put(args)

  35.        ip = Proxy.get()

  36.        print(ip + '有效已写入ips.txt&#​39;)

  37.        with open('ips.txt&#​39;, 'a&#​39;, encoding='utf-8&#​39;) as file:

  38.            file.write(ip+'\n&#​39;)

  39.    def get_out_proxy(self):  # 输出有效ip

  40.        '&#​39;'

  41.        :return: effective IP outgoing

  42.        '&#​39;'

  43.        proxy_txt = []

  44.        with open('ips.txt&#​39;, 'r&#​39;, encoding='utf-8&#​39;) as file:

  45.            self.pass_isproxy = file.readlines()

  46.            for i in self.pass_isproxy:

  47.                proxy_txt.append(i.replace('\n&#​39;, '&#​39;))

  48.            return proxy_txt

(四)验证代理池ip: module/IsProxy.py

  1. # -*- coding:utf-8 -*-

  2. # Author:qiuzishan

  3. import requests

  4. from module.OptPool import ProxyPool

  5. from threading import Thread

  6. class MyThread(Thread):  # 事实上没有调用这个函数,忽悠一下~

  7.    def __init__(self, func):

  8.        Thread.__init__(self)  #调用父类的init方法

  9.        self.func = func

  10.    def run(self):

  11.        self.result = self.func()

  12.    def get_result(self):

  13.        Thread.join(self)

  14.        print("asdasd&#​34;)

  15.        try:

  16.            return self.result

  17.        except Exception:

  18.            return None

  19. class IsProxy:

  20.    def __init__(self, t) -> None:

  21.        self.pp = ProxyPool()

  22.        self.t = t

  23.    def startIsProxy(self):

  24.        self.manyTread()

  25.    def manyTread(self):

  26.        "&#​34;"

  27.        多线程开启!

  28.        "&#​34;"

  29.        thread = []

  30.        if self.pp.get_length_pool() < self.t:  # 最后代理池的剩余ip的不够线程,线程等于剩余的数量

  31.            self.t = self.pp.get_length_pool()

  32.            print("线程为:{}&#​34;.format(self.t))

  33.        for i in range(0, self.t):

  34.            t = Thread(target=self.test_proxy)

  35.            thread.append(t)

  36.        for i in thread:

  37.            i.start()

  38.            # print(f&#​39;线程数:{i}开始')

  39.        for i in thread:

  40.            i.join()

  41.    def test_proxy(self):

  42.        ip = str(self.pp.get_out_pool())

  43.        # print(ip)

  44.        if ip != '0&#​39;:

  45.            proxies = {

  46.                'http&#​39;: 'http://&#​39; + ip,

  47.                'https&#​39;: 'https://&#​39; + ip,

  48.            }

  49.            try:

  50.                requests.get('https://www.baidu.com/&#​39;, proxies=proxies, timeout=10)

  51.                self.pp.get_into_proxy(ip)

  52.                return 1

  53.            except requests.exceptions.ProxyError:

  54.                print("无效ip&#​34; + ip)

  55.                return -1

  56.            except requests.exceptions.ConnectTimeout:

  57.                print("无效ip&#​34; + ip)

  58.                return -2

  59.            except requests.exceptions.ReadTimeout:

  60.                print("无效ip&#​34; + ip)

  61.                return -3

  62.            except requests.exceptions.ConnectionError:

  63.                print("无效ip&#​34; + ip)

  64.                return -4

  65.        else:

  66.            return 0

  67. if __name__ == '__main__&#​39;:

  68.    ip = IsProxy()

(五)、获取有效ip: module/GetApi.py

  1. # -*- coding:utf-8 -*-

  2. # Author:qiuzishan

  3. from module.OptPool import ProxyPool

  4. from module.QuChong import QuChong

  5. from module.IsProxy import IsProxy

  6. class GetApi:

  7.    def start(self, t):

  8.        self.t = t

  9.        self.get_api()

  10.    def get_api(self):

  11.        pp = ProxyPool()

  12.        proxy_txt = pp.get_out_proxy()

  13.        for i in proxy_txt:

  14.            print("ips.txt里面的ip代理有:&#​34; + i)

  15.            pp.get_into_pool(i)

  16.        with open('ips.txt&#​39;, 'w&#​39;, encoding='utf-8&#​39;) as file:

  17.            file.write('&#​39;)  # 清除ips.txt,清除过期无效代理ip

  18.        ip_test = IsProxy(self.t)

  19.        while True:

  20.            ip_test.startIsProxy()

  21.            flag = pp.get_length_pool()

  22.            if flag == 0:

  23.                print("退出循环&#​34;)

  24.                break  # 退出循环

  25.        xiaochu = QuChong()  # 去重后,显示代理

  26.        xiaochu.quchong()

  27. if __name__ == '__main__&#​39;:

  28.    ga = GetApi()

  29.    ga.start()

(六)、去重module/QuChong.py

  1. # -*- coding:utf-8 -*-

  2. # Author:qiuzishan

  3. class QuChong:

  4.    def quchong(self):

  5.        f = open('ips.txt&#​39;, 'r&#​39;, encoding='utf-8&#​39;)

  6.        lines = f.readlines()

  7.        n = 0

  8.        lines_clear = []

  9.        # 列表去重

  10.        for i in lines:

  11.            if i not in lines_clear:

  12.                lines_clear.append(i)

  13.                n = n+1

  14.        f.close()

  15.        # print(lines_clear)

  16.        f_clear = open("ips.txt&#​34;, 'w&#​39;, encoding='utf-8&#​39;)

  17.        for i in range(0, n):

  18.            f_clear.write(lines_clear[i])

  19.            print("最终有效ip:&#​34; + lines_clear[i])

  20.        f_clear.close()

三、使用方法:

1.命令:python StartApi.py -t 100 开了100个线程,最后把有效ip存在ips.txt(未去重) 效果:

2.命令:python StartApi.py -c api -t 20 再次验证ips.txt的ip,开启20个线程再次去验证有效ip,并去重。最后高效代理ip再次存在ips.txt

3.查看使用方法:python StartApi.py -h

爬取大量的ip进行验证,爬取高效的ip

以上代码看不懂都无所谓,白嫖就可以了。