多线程爬取免费代理ip池 (给我爬)

Posted 风信子的猫Redamancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程爬取免费代理ip池 (给我爬)相关的知识,希望对你有一定的参考价值。

多线程爬取免费代理ip池 (给我爬)


天网恢恢疏而不漏,有时候爬太多数据的时候会把自己的ip给封掉,所以呢,我左思右想,就想能不能把自己的ip给换掉,换成那种高匿ip,这样的话,就找不到我的真实ip,这样我就可以好好隐藏自己了哈哈哈。 (注意:本博客和代码仅可用于计算机技术学习及数据抓取、爬虫采集等合法行为)

安装的库

首先我们可以打开我们的命令行,输入以下代码安装这些库,这样才能保证我们的结果能够正确运行。

pip install lxml requests pathos

IP 隐藏

在我们用python进行爬虫操作的时候,如何影藏自己的ip地址呢,众所周知,如果我们在我们的百度上直接查询ip地址几个字,我们就可以得到我们自己的ip地址

那如何将我们的ip地址改掉呢,其实有很多种方法,我们可以直接就把本机ip改掉,这样的话,他做什么事情我们的ip都被改掉了,当然,我们也可以利用代码进行修改,只需要多加一个参数proxies即可

比如现在我们找到了另一个有效的ip,我拿此来用,我只需要设置我们的proxies参数即可

# 用到的库
import requests
# 写入获取到的ip地址到proxy
proxy = {
    'https':'221.178.232.130:8080'
}
# 用百度检测ip代理是否成功
url = 'https://www.baidu.com/s?'
# 请求网页传的参数
params={
    'wd':'ip地址'
}
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}
# 发送get请求
response = requests.get(url=url,headers=headers,params=params,proxies=proxy)
print(response.text)

# 获取返回页面保存到本地,便于查看
with open('ip.html','w',encoding='utf-8') as f:
    f.write(response.text)

可以查看页面是否ip地址变了,如果变了说明成功了,当然,其实我们测试的时候,只是需要看看我们的状态码是否是200,如果是200,就说明我们其实已经成功了

代理ip

为了隐藏自己的ip,我们就需要用代理ip了

从IP代理的隐蔽性级别进行划分,代理可以分为三种,即高度匿名代理、普通匿名代理和透明代理。

代理类型代理服务器端的配置描述
透明代理REMOTE_ADDR = Proxy IP;HTTP_VIA = Proxy IP;HTTP_X_FORWARDED_FOR = Your IP透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以从HTTP_X_FORWARDED_FOR来查到你是谁。
匿名代理REMOTE_ADDR = proxy IP;HTTP_VIA = proxy IP;HTTP_X_FORWARDED_FOR = proxy IP匿名代理比透明代理进步了一点:别人只能知道你用了代理,无法知道你是谁。
高匿代理REMOTE_ADDR = Proxy IP;HTTP_VIA = Proxy IP;HTTP_X_FORWARDED_FOR = Random IP address高匿代理让别人根本无法发现你是在用代理,所以是最好的选择。

接下来我们来介绍一下,如何去自动爬取代理ip,因为有时候手动去调proxy太麻烦了

我们首先给出几个免费代理ip的网址

http://www.ip3366.net/
http://www.feidudaili.com/index/gratis/index
https://proxy.ip3366.net/free/
https://www.89ip.cn/index.html
http://www.66ip.cn/1.html

如果我们打开这些网站,我们可以看到有很多免费代理ip和他们的端口,比如

在这里面我们可以利用这些代理ip,但是有时候,这些代理ip是有问题的,所以我们在用的时候又要进行测试,因为毕竟这些是免费的ip,是很不稳定的,我们也可以出钱买ip,这样我们得到的ip就是稳定的,免费ip是很难稳定的。

多线程爬取

接下来,我就想对其进行爬取,批量爬取,一个一个测试,将正确的存入文件中,我们可以下次进行使用

读入代理ip

目的其实很简单,如果我们的文件本身有这个ip,我们就不必要继续写入相同的,这样会比较浪费时间

def read_proxy(path='ip_proxy.txt'):
    if not os.path.exists(path):
        f = open(path,'w')
        f.close()
    with open(path,'r') as f:
        PROXY = f.readlines()
        PROXY = [proxy.replace('\\n', '') for proxy in PROXY]
    return PROXY

写入代理ip

这个也就更显而易见了吧,就是将正确的代理ip写入我们的文件中,还是比较简单的。

# 将代理ip写入文件
def write_proxy(proxy,path='ip_proxy.txt'):
    if proxy not in PROXY:
        with open('ip_proxy.txt','a+') as fp:
            fp.write(proxy + '\\n')
            print("正在写入 ip: {1} ".format(proxy))
        print("录入完成")
    else:
        print("文件中已有相同ip,未录入")

验证代理ip

这里有一个很重要的代码也就是,验证代理ip,因为我们的ip地址并不是所有都是可用的,所以我们应该验证他们,如果是正确的,我们再进行写入,如果是错误的,那我们不会进行写入操作。

# 验证已得到IP的可用性
def test_proxies(proxies):
    url = "https://www.1688.com/"
    header = {
        "User-Agent": random.choice(my_headers),
        'Connection': 'close'
    }
    for proxy in proxies:
        try:
            response = requests.get(url,headers=header,proxies={"http":proxy,'https':proxy},timeout=2)
            # time = response.elapsed.total_seconds()
            # print(time)
            if response.status_code == 200:
                print('-'*15,"该代理IP可用: {0}".format(proxy),'-'*15)
                write_proxy(proxy)
            else:
                print("该代理IP不可用: {0}".format(proxy))
        except Exception as e:
            print("该代理IP无效: {0}".format(proxy))
    

解析网页得到代理ip

对于我们的网页来说,里面有很多的代理ip,他们的格式都是类似的,所以我们需要从解析我们的网页得到代理ip,然后进行我们的测试,如果成功就会写入进行,这里我们就需要用我们的xpath解析我们的网页,当然,也可以用BeautifSoup

# 解析网页,并得到网页中的代理IP
def get_proxy(html,xpath):
    selector = etree.HTML(html)
    proxies = []
    XPATH = xpath
    for each in selector.xpath(XPATH):
        # ip.append(each[0])
        ip = each.xpath('./td[1]/text()')[0].strip()
        port = each.xpath('./td[2]/text()')[0].strip()
        proxy = ip + ':' + port
        proxies.append(proxy)
    # print('ip 有' ,len(proxies) , '条')
    test_proxies(proxies)

获取网页响应

这个就更简单了,实际上就是对我们的网页进行响应,在用以上代码进行解析,也是比较简单的,不过这里面有两个参数

# 营造请求头,获取网页响应
def get_html(url_xpath,page):
    header = {
        "User-Agent": random.choice(my_headers),
        'Connection': 'close'
    }
    url,xpath = url_xpath['url'],url_xpath['xpath']
    # print(url,xpath)
    response = requests.get(url%page, headers=header,proxies=proxies)
    # print(response.text)
    get_proxy(response.text ,xpath)

测试已有文件的ip是否正确

由于我们毕竟是免费的ip,所以来说,我们就需要对其进行再一次测试,因为可能他很快就要失效了

def test_files(path):
    proxies = read_proxy(path)
    proxies = list(set(proxies))
    url = "https://www.1688.com/"
    header = {
        "User-Agent": random.choice(my_headers),
        'Connection': 'close'
    }
    f = open(path,'w')
    for proxy in proxies:
        try:
            response = requests.get(url,headers=header,proxies={"http":proxy,'https':proxy},timeout=2)
            # time = response.elapsed.total_seconds()
            # print(time)
            if response.status_code == 200:
                print('-'*15,"该代理IP可用: {0}".format(proxy),'-'*15)
                f.write(proxy + '\\n')
            else:
                print("该代理IP不可用: {0}".format(proxy))
        except Exception as e:
            print("该代理IP无效: {0}".format(proxy))
    f.close()    

多线程爬取

其实对于这一块来说,我们可以一个一个爬取的,但是我觉得太慢了,在这个时间效率为王的时代,我觉得我们还是有必要用一些多线程的,这里我们就需要用一下pathos库,用里面的线程池进行一个多线程的爬取

pool = Pool(30)
for name,ip in ip_url.items():
    # print(name,ip)    
    e_pages = ip['page']
    total_page = [i for i in range(s_pages,e_pages + 1)]    
    url_xpath = [ip]*(e_pages-s_pages + 1)
    pool.map(get_html,url_xpath,total_page)
    print('\\n'*3,name,'已经被爬完','\\n'*3)
    time.sleep(30)
    pool.close()
    pool.join()

我这里还用了30个线程去爬取,这样可能极大的提高了效率,相当于一次性爬30个页面,我觉得这可能能很大的提高我们的效率吧

不过这里关于多线程的知识还是需要大家去努力看看,我这里还是不详细讲了

这里出现有时候print奇奇怪怪的原因是,我们利用了多线程,所以每一个线程都是独立的,有时候更快导致了,我们输出有时候也会有一点点乱,但是在我们的文件中不会,只是看起来有点奇怪哈哈

做好心理准备,爬取下来的IP,可能立马就失效了,毕竟免费的(便宜没什么好货对吧,而且可能大家都在爬爬爬)

完整代码

最后的最后呢,我还是给出完整的代码,每个人在自己的电脑上都可以运行的,只要安装正确那些库,有什么问题都可以跟我讨论,我最后再多嘴一句**(注意:本博客和代码仅可用于计算机技术学习及数据抓取、爬虫采集等合法行为)**

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# @File    :   ip.py
# @Time    :   2021/09/30 19:32:52
# @Author  :   DKJ
# @Contact :   1016617094@qq.com
# @Software:   VScode

# here put the import lib
import requests
from lxml import etree
import random
import os
from pathos.multiprocessing import ProcessingPool as Pool
import time    


my_headers = [
    "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14",
    "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)",
    'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11',
    'Opera/9.25 (Windows NT 5.1; U; en)',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
    'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)',
    'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12',
    'Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9',
    "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Ubuntu/11.04 Chromium/16.0.912.77 Chrome/16.0.912.77 Safari/535.7",
    "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0 "
]
PROXY = []
proxies = {}
def read_proxy(path='ip_proxy.txt'):
    if not os.path.exists(path):
        f = open(path,'w')
        f.close()
    with open(path,'r') as f:
        PROXY = f.readlines()
        PROXY = [proxy.replace('\\n', '') for proxy in PROXY]
    return PROXY

# 将代理ip写入文件
def write_proxy(proxy,path='ip_proxy.txt'):
    if proxy not in PROXY:
        with open('ip_proxy.txt','a+') as fp:
            fp.write(proxy + '\\n')
            print("正在写入 ip: {1} ".format(proxy))
        print("录入完成")
    else:
        print("文件中已有相同ip,未录入")
    
# 验证已得到IP的可用性
def test_proxies(proxies):
    url = "https://www.1688.com/"
    header = {
        "User-Agent": random.choice(my_headers),
        'Connection': 'close'
    }
    for proxy in proxies:
        try:
            response = requests.get(url,headers=header,proxies={"http":proxy,'https':proxy},timeout=2)
            # time = response.elapsed.total_seconds()
            # print(time)
            if response.status_code == 200:
                print('-'*15,"该代理IP可用: {0}".format(proxy),'-'*15)
                write_proxy(proxy)
            else:
                print("该代理IP不可用: {0}".format(proxy))
        except Exception as e:
            print("该代理IP无效: {0}".format(proxy))
    

# 解析网页,并得到网页中的代理IP
def get_proxy(html,xpath):
    selector = etree.HTML(html)
    proxies = []
    XPATH = xpath
    for each in selector.xpath(XPATH):
        # ip.append(each[0])
        ip = each.xpath('./td[1]/text()')[0].strip()
        port = each.xpath('./td[2]/text()')[0].strip()
        proxy = ip + ':' + port
        proxies.append(proxy)
    # print('ip 有' ,len(proxies) , '条')
    test_proxies(proxies)
    
# 营造请求头,获取网页响应
def get_html(url_xpath,page):
    header = {
        "User-Agent": random.choice(my_headers),
        'Connection': 'close'
    }
    url,xpath = url_xpath['url'],url_xpath['xpath']
    # print(url,xpath)
    response = requests.get(url%page, headers=header,proxies=proxies)
    # print(response.text)
    get_proxy(response.text ,xpath)
 
 
def test_files(path):
    proxies = read_proxy(path)
    proxies = list(set(proxies))
    url = "https://www.1688.com/"
    header = {
        "User-Agent": random.choice(my_headers),
        'Connection': 'close'
    }
    f = open(path,'w')
    for proxy in proxies:
        try:
            response = requests.get(url,headers=header,proxies={"http":proxy,'https':proxy},timeout=2)
            # time = response.elapsed.total_seconds()
            # print(time)
            if response.status_code == 200:
                print('-'*15,"该代理IP可用: {0}".format(proxy),'-'*15)
                f.write(proxy + '\\n')
            else:
                print("该代理IP不可用: {0}".format(proxy))
        except Exception as e:
            print("该代理IP无效: {0}".format(proxy))
    f.close()    
    
if __name__ == "__main__":
    requests.DEFAULT_RETRIES = 5  # 增加重试连接次数
    s = requests.session()
    s.keep_alive = False  # 关闭多余连接
    # 代理ip的爬取源地址
    PATH = 'ip_proxy.txt'
    test_files(PATH)
    print('测试完毕')
    # time.sleep(10)
    PROXY = read_proxy(PATH)
    if len(PROXY) !=  0:
        proxy = random.choices(PROXY)
        proxies['https'],proxies['http'] = proxy,proxy
    ip_url = {'飞度代理':{'url':'http://www.feidudaili.com/index/gratis/index?page=%s',
                      'xpath':'//div[@class="section clearfix"]//table[@class="data_table"]/tbody/tr',
                      'page':24},
              '89代理':{'url':'http://www.89ip.cn/index_%s.html',
                      'xpath':'//table[@class="layui-table"]/tbody/tr',
                      'page':11},
              '齐云代理':{'url':'https://proxy.ip3366.net/free/?action=china&page=%s',
                      'xpath':'//*[@id="content"]/section/div[2]/table/tbody/tr',
                      'page':10},
              'UU http代理':{'url':'http://www.uuhttp.com/index/free/index?page=%s',
                           'xpath':'//div[@class="dial_left fadeInLeft free_page"]//div[@class="price_table"]//tbody/tr',
                           'page':'600'},
              '66免费代理':{'url':'http://www.66ip.cn/%s.html',
                  'xpath':'//div[@class="layui-row layui-col-space15"]//table/tbody/tr',
                  'page':1000},
              '云代理':{'url':'http://www.ip3366.net/?stype=1&page=%s',
                     'xpath':'//div[@id="container"]//div[@id="list"]/table/tbody/tr',
                     'page':10}
              }
    # get_html(ip_url['89代理'],1)
    s_pages = 1
    pool = Pool(30)
    for name,ip in ip_url.items():
        # print(name,ip)    
        e_pages = ip['page']
        total_page = [i for i in range(s_pages,e_pages + 1)]    
        url_xpath = [ip]*(e_pages-s_pages + 1)
        pool.map(get_html,url_xpath,total_page)
        print(爬取免费IP,建立自己的爬虫IP池

python爬虫+多线程+多进程+构建IP代理池

Python构建代理池,突破IP的封锁爬取海量数据(附项目源码)

多线程爬取百度百科

给我爬!3天掌握Scrapy

Python3爬虫Scrapy使用IP代理池和随机User-Agent