简易爬取免费代理IP

爬取maitian屡次被封,先建立一个免费代理ip池吧
暂时保存为txt格式

思路:

1、找到免费的ip代理网站
以西刺代理的4个网站为例:
国内普通代理: http://www.xicidaili.com/nt/
国内高匿代理: http://www.xicidaili.com/nn/
国内https代理:http://www.xicidaili.com/wn/
国外http代理: http://www.xicidaili.com/wt/
2、使用requests框架多线程方式爬取
①添加user-agent池;
②4种类型的ip代理网站,每个网站多页爬取,创建线程池,每页为一个线程;
3、使用xpath解析
4、验证获取ip的有效性
5、仅保存有效ip
6、查看一共保存了多个有效ip,计算爬取时间

理清思路开始操作:

import requests
import random
from lxml import etree
import time
from threading import Thread

为了锻炼自己养成好习惯,这里封装一个ip爬取类

class IpSpider(object):

    def __init__(self,path):
        #指定文件保存路径
        self.path = path

反爬的第一步:添加请求头,创建一个请求头列表,方便获取

    def get_headers(self):
        ug_list = [
		 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"]
        #调用random方法,随机选取一个user-agent
        ug = random.choice(ug_list)
        #将选好的ug添加到请求头里
        headers = {'User-Agent':ug}
        return headers

获取ip的类方法:

    def get_ip(self,ip_type,pagenum):
        #创建url列表
        url_list =  ['http://www.xicidaili.com/nt/',  # xicidaili国内普通代理
                'http://www.xicidaili.com/nn/',  # xicidaili国内高匿代理
                'http://www.xicidaili.com/wn/',  # xicidaili国内https代理
                'http://www.xicidaili.com/wt/']  # xicidaili国外http代理
        #4个类型的网站+多页,拼接url
        #ip_type是类型的index,pagenum是页码
        url = url_list[ip_type] + str(pagenum)
        #获取请求头
        headers = self.get_headers()
        #传入url和headers发送request请求,获取响应体
        response = requests.get(url,headers=headers,timeout=5).text
        #对获取到的数据进行转译,以便提供给xpath进行解析
        data = etree.HTML(response)
        #分析网页,每行一个ip地址,使用xpath获取整页中所有包含ip数据的标签列表
        all = data.xpath('.//table[@id="ip_list"]//tr')
        #遍历得到的列表,去掉表头(表头无数据)
        for i in all[1:]:
            #获取host
            host = i.xpath('./td[2]/text()')[0]
            #获取port
            port = i .xpath('./td[3]/text()')[0]
            #拼接得到一个ip地址
            ip = host + ':' + port
            #print(ip)
            #验证ip地址是否有效果,调用check_ip方法
            is_avali = self.check_ip(ip) 
            #使用if语句
            if is_avali:
               #若返回True,则调用save_ip函数保存ip
                self.save_ip(ip)
                #print(ip,'有效')
            #else:
                #print(ip,'无效')
            #返回False可以跳过不管

验证ip有效性的类方法:

    def check_ip(self,ip):
        headers = self.get_headers()
        #使用百度作为验证网页,用来验证获取的是否为有效ip
        check_url = 'https://www.baidu.com'
        #构建proxies参数,这里因为以四个不同类型网站为例,不确定获取的是哪种类型的ip
        #需要判断ip类型,requests框架中,可以自动识别ip类型
        proxies = {'http':ip,'https':ip}
        #为了避免报错中断,使用try—except语句 
        try:
            response = requests.get(url=check_url,
            						headers=headers,
            						proxies=proxies,
            						timeout=30)
            #布尔值判断,若请求成功返回True
            return response.status_code == 200
         except:
            return False
            #请求失败返回False

保存有效ip

    def save_ip(self,ip):
        #保存有效ip到指定路径
        with open(self.path,'a',encoding='utf-8') as f:
            f.write(ip +'\n')
        #创建一个file,使用增加数据模式保存ip,每保存一个ip,进行换行

统计ip数量:

    def ip_count(self):
        #从指定路径读取ip个数
        with open(self.path,'r',encoding='utf-8')as f:
            ip_list = f.readlines()
            #按行读取ip数据,获得一个ip列表,计算列表长度即获取的ip数量
            count = len(ip_list)
        return count

创建线程池,统筹调用多线程爬取:

    def start(self):
        #程序运行
        #创建一个开始的时间
        start = time.time()
        #创建一个线程池,方便开启和阻塞线程
        threds=[]
        #创建线程,4个ip_type的网站,每个网站获取前三页,创建4*3个线程执行get_ip
        for ip_type in range(4):
            for pagenum in range(3):
                t = Thread(target=self.get_ip,args=(ip_type,pagenum))
                #放入线程池
                threds.append(t)
        print('开始爬取ip代理')
        #开启线程
        for i in threds:
            i.start()
        #阻塞线程,防止主程序提前结束
        for i in threds:
            i.join()
        print('爬取完成')
        #记录结束时间
        end = time.time()
        #检查共耗时多久
        time_consuming = end - start
        #获取ip数量
        ip_count = self.ip_count()

        print('共获取有效代理ip: %s 个,耗时:%s' % (ip_count,time_consuming))

最后一步,指定保存路径,可以开始运行啦

if __name__ == '__main__':

    path = './ip_list_0920.txt'
    IpSpider(path).start()
总结: 比较初级的ip获取保存方式,没有使用数据库,保存在txt格式中,使用代理池时,调用readlines方式逐行读取ip,免费ip的存活率很低,有需要的话尽量使用付费ip吧^^

WechatIMG330.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值