python爬虫小白升仙_4-----爬取代理IP并多线程检测IP有效性

本文实现爬取"https://www.xicidaili.com/nn/"该网站的高匿代理ip,并使用多线程进行IP有效性的检测

涉及:

1. requests.get添加参数headers

2. 多页网页数据的爬取

3. 使用xpath获取的列表为空的问题的处理

4. 代理IP的有效性检测

5. 多线程的简单使用,提高ip验证的效率

 

网页信息:

请求头:
headers = {
    "Host": "www.xicidaili.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
}

运行结果:

爬取5页,共500条信息,获取其ip、port、http/https类型,处理数据,组成239组,检测代理ip的有效性,得到最终proxies

代理ip:requests.get(url,headers=headers,proxies=random.choice(proxies))    在列表里随机选取ip

问题:使用xpath获取的列表为空

原因:浏览器会对html文本进行一定的规范化,所以会自动在路径中加入tbody,导致读取失败,去除tbody即可。
# ip_list=xml.xpath('//table[@id="ip_list"]//tbody//tr//td[2]/text()')  # 之前返回空列表的写法
ip_list = xml.xpath('//table[@id="ip_list"]//tr//td[2]/text()')  # ip  修改后ok

多线程:

# 通过多线程验证ip的有效性
threads=[]  # 创建列表
for i in range(len(get_effective_ip.complete_ip)):
    thread=threading.Thread(target=get_effective_ip.verify_ip,args=[i])  # target:目标方法  args:方法的参数
    threads.append(thread)   # 添加线程到列表
    thread.start()    # 启动线程
# 阻塞主进程,等待所有子线程结束
for t in threads:
    t.join()
for ip in get_effective_ip.effective_ip_list:
    print(ip)

源码:

class Get_IP(object):
    def __init__(self):
        self.complete_ip = []
        self.effective_ip_list = []

    #  获取ip  index:爬取的页数
    def get_ip(self,index):
        total_ip_list=[]
        total_port_list=[]
        total_http_list=[]
        headers = {
            "Host": "www.xicidaili.com",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
        }
        for i in range(index):
            response = requests.get("https://www.xicidaili.com/nn/" + str(i+1), headers=headers)
            xml = etree.HTML(response.text)
            # print(response.text)
            # 浏览器会对html文本进行一定的规范化,所以会自动在路径中加入tbody,导致读取失败,在此处直接在路径中去除tbody即可。
            # ip_list=xml.xpath('//table[@id="ip_list"]//tbody//tr//td[2]/text()')  # 返回空列表
            ip_list = xml.xpath('//table[@id="ip_list"]//tr//td[2]/text()')  # ip
            port_list = xml.xpath('//table[@id="ip_list"]//tr//td[3]/text()')  # 端口
            http_list = xml.xpath('//table[@id="ip_list"]//tr//td[6]/text()')  # http or  https
            total_ip_list=total_ip_list+ip_list
            total_port_list=total_port_list+port_list
            total_http_list=total_http_list+http_list
        print(len(total_ip_list))
        self.get_complete_ip(ip_list=total_ip_list, port_list=total_port_list, http_list=total_http_list)


    # 处理数据,得到完整的ip
    def get_complete_ip(self,ip_list,port_list,http_list):
        http_ip = []
        https_ip = []
        # 区分http和https,并将ip和port拼接起来
        for i in range(len(port_list)):
            if "HTTP"==http_list[i]:
                http_ip.append("http://"+ip_list[i]+":"+port_list[i])
            elif "HTTPS"==http_list[i]:
                https_ip.append("https://"+ip_list[i]+":"+port_list[i])
        # 由于要将http_ip与https_ip凑成对组成字典,故选取数量较少的一组
        if len(http_ip)>len(https_ip):
            group_num=len(https_ip)
        else:
            group_num=len(http_ip)
        print(group_num)
        # 将http/https和ip组成字典,再形成列表,构造出proxies(包括多组ip)
        for i in range(group_num):
            ip=dict(http=http_ip[i],https=https_ip[i])
            self.complete_ip.append(ip)
        # print(self.complete_ip)

    # 通过get请求返回结果的响应码来判断ip是否有效
    def verify_ip(self,index):
        try:
            response = requests.get("https://www.baidu.com/", proxies=self.complete_ip[index], timeout=3)
            if response.status_code == 200:
                self.effective_ip_list.append(self.complete_ip[index])
        except:
            pass
if __name__ == '__main__':
    get_effective_ip=Get_IP()
    get_effective_ip.get_ip(5)
    # 通过多线程验证ip的有效性
    threads=[]  # 创建列表
    for i in range(len(get_effective_ip.complete_ip)):
        thread=threading.Thread(target=get_effective_ip.verify_ip,args=[i])  # target:目标方法  args:方法的参数
        threads.append(thread)   # 添加线程到列表
        thread.start()    # 启动线程
    # 阻塞主进程,等待所有子线程结束
    for t in threads:
        t.join()
    for ip in get_effective_ip.effective_ip_list:
        print(ip)

effective_ip_list为最终的ip

 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值