美文网首页python爬虫编程网赚python社区
Python建立ip代理池(多线程)

Python建立ip代理池(多线程)

作者: 苍简 | 来源:发表于2019-02-28 20:53 被阅读94次

    转载自公众号:JAVAandPythonJun

    说在前面的话

    Hello,我是JAP君,相信经常使用爬虫的朋友对代理ip应该比较熟悉,代理ip就是可以模拟一个ip地址去访问某个网站。我们有时候需要爬取某个网站的大量信息时,可能由于我们爬的次数太多导致我们的ip被对方的服务器暂时屏蔽(也就是所谓的防爬虫防洪水的一种措施),这个时候就需要我们的代理ip出场了,今天我带大家来爬取西刺代理上面免费提供的代理ip并且我们来检测它的有效性来打造我们自己的代理ip池,废话不多说,咱们动工!

    2思路分析(写爬虫前大家都必须要分析一下)

    image image

    没错上图就是我们的西刺代理网站啦,今天我们就是来拿它的数据,老司机一看这个界面就会自动右击鼠标->查看源代码,我们也来看看:

    image

    我们会发现数据都在<tr>里面,并且<tr>里面有很多的<td>,每一个<td>都包含了我们所需要的数据。

    看过我以前一些爬虫文章的朋友估计一下就知道该怎么下手了,但是不急我们还是来分析一下,毕竟这次数据量有点大,而且还得校验代理ip的有效性。

    image

    给大家画了张图,其实思路也很简单,也就不多阐述了。

    3获取所有的代理ip以及相关信息并保存至文件txt中

    我们就按照我们的思路来,在这里我们需要用到的几个库,给大家写出来:

    from bs4 import BeautifulSoup
    import requests
    from urllib import request,error
    import threading
    

    导入库后,我们首先获得代理ip,我们来定义一个方法:(每一句的解释我都写在注释里了)

    def getProxy(url):
       # 打开我们创建的txt文件
       proxyFile = open('proxy.txt', 'a')
       # 设置UA标识
       headers = {
           'User-Agent': 'Mozilla / 5.0(Windows NT 10.0;WOW64) AppleWebKit '
                         '/ 537.36(KHTML, likeGecko) Chrome / 63.0.3239.132Safari / 537.36'
       }
       # page是我们需要获取多少页的ip,这里我们获取到第9页
       for page in range(1, 10):
           # 通过观察URL,我们发现原网址+页码就是我们需要的网址了,这里的page需要转换成str类型
           urls = url+str(page)
           # 通过requests来获取网页源码
           rsp = requests.get(urls, headers=headers)
           html = rsp.text
           # 通过BeautifulSoup,来解析html页面
           soup = BeautifulSoup(html)
           # 通过分析我们发现数据在 id为ip_list的table标签中的tr标签中
           trs = soup.find('table', id='ip_list').find_all('tr') # 这里获得的是一个list列表
           # 我们循环这个列表
           for item in trs[1:]:
               # 并至少出每个tr中的所有td标签
               tds = item.find_all('td')
               # 我们会发现有些img标签里面是空的,所以这里我们需要加一个判断
               if tds[0].find('img') is None:
                   nation = '未知'
                   locate = '未知'
               else:
                   nation = tds[0].find('img')['alt'].strip()
                   locate = tds[3].text.strip()
               # 通过td列表里面的数据,我们分别把它们提取出来
               ip = tds[1].text.strip()
               port = tds[2].text.strip()
               anony = tds[4].text.strip()
               protocol = tds[5].text.strip()
               speed = tds[6].find('div')['title'].strip()
               time = tds[8].text.strip()
               # 将获取到的数据按照规定格式写入txt文本中,这样方便我们获取
               proxyFile.write('%s|%s|%s|%s|%s|%s|%s|%s\n' % (nation, ip, port, locate, anony, protocol, speed, time))
    

    上面的代码就是我们抓取西刺代理上的所有ip并将它们写入txt中,每一句的解释我都写在注释里面了,这里也就不多说了。

    4校验代理ip的可用性

    这里我是通过代理ip去访问百度所返回的状态码来辨别这个代理ip到底有没有用的。

    def verifyProxy(ip):
       '''
       验证代理的有效性
       '''
       requestHeader = {
           'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36"
       }
       url = "http://www.baidu.com"
       # 填写代理地址
       proxy = {'http': ip}
       # 创建proxyHandler
       proxy_handler = request.ProxyHandler(proxy)
       # 创建opener
       proxy_opener = request.build_opener(proxy_handler)
       # 安装opener
       request.install_opener(proxy_opener)
    
       try:
           req = request.Request(url, headers=requestHeader)
           rsq = request.urlopen(req, timeout=5.0)
           code = rsq.getcode()
           return code
       except error.URLError as e:
           return e
    

    我们在这个方法中会得到一个状态码的返回,如果返回码是200,那么这个代理ip就是可用的。

    image
    def verifyProxyList():
       
       verifiedFile = open('verified.txt', 'a')
    
       while True:
           lock.acquire()
           ll = inFile.readline().strip()
           lock.release()
           if len(ll) == 0 : break
           line = ll.strip().split('|')
           ip = line[1]
           port = line[2]
           realip = ip+':'+port
           code = verifyProxy(realip)
           if code == 200:
               lock.acquire()
               print("---Success:" + ip + ":" + port)
               verifiedFile.write(ll + "\n")
               lock.release()
           else:
               print("---Failure:" + ip + ":" + port)
    

    我们写完校验方法后,我们就从我们事先爬取到的所有代理ip的txt文件中获取到ip和端口(ip地址:端口),我们通过判断返回值是否为200来进行写入到有效的txt文件中。

    5调用函数

    万事俱备只欠调用!

    if __name__ == '__main__':
       tmp = open('proxy.txt', 'w')
       tmp.write("")
       tmp.close()
       tmp1 = open('verified.txt', 'w')
       tmp1.write("")
       tmp1.close()
       getProxy("http://www.xicidaili.com/nn/")
       getProxy("http://www.xicidaili.com/nt/")
       getProxy("http://www.xicidaili.com/wn/")
       getProxy("http://www.xicidaili.com/wt/")
    
       all_thread = []
       # 30个线程
       for i in range(30):
           t = threading.Thread(target=verifyProxyList)
           all_thread.append(t)
           t.start()
    
       for t in all_thread:
           t.join()
    
       inFile.close()
       verifiedtxt.close()
    

    因为西刺代理提供了四种代理ip,所以分别有四个网址。这里我们也采用了线程的方法,主要是为了防止出现线程互相争夺导致我们的数据不精确,在上面几个方法中我们也通过了同步锁来对其进行线程安全的保证。

    6结尾

    其实总体来说这个爬虫不是特别的难,主要的难点在于数据量可能有点多,很多人可能不会考虑到线程安全的问题,导致数据获取的不精确。

    全部代码:

    from bs4 import BeautifulSoup
    import requests
    from urllib import request,error
    import threading
    
    
    inFile = open('proxy.txt')
    verifiedtxt = open('verified.txt')
    lock = threading.Lock()
    def getProxy(url):
        # 打开我们创建的txt文件
        proxyFile = open('proxy.txt', 'a')
        # 设置UA标识
        headers = {
            'User-Agent': 'Mozilla / 5.0(Windows NT 10.0;WOW64) AppleWebKit '
                          '/ 537.36(KHTML, likeGecko) Chrome / 63.0.3239.132Safari / 537.36'
        }
        # page是我们需要获取多少页的ip,这里我们获取到第9页
        for page in range(1, 10):
            # 通过观察URL,我们发现原网址+页码就是我们需要的网址了,这里的page需要转换成str类型
            urls = url+str(page)
            # 通过requests来获取网页源码
            rsp = requests.get(urls, headers=headers)
            html = rsp.text
            # 通过BeautifulSoup,来解析html页面
            soup = BeautifulSoup(html)
            # 通过分析我们发现数据在 id为ip_list的table标签中的tr标签中
            trs = soup.find('table', id='ip_list').find_all('tr') # 这里获得的是一个list列表
            # 我们循环这个列表
            for item in trs[1:]:
                # 并至少出每个tr中的所有td标签
                tds = item.find_all('td')
                # 我们会发现有些img标签里面是空的,所以这里我们需要加一个判断
                if tds[0].find('img') is None:
                    nation = '未知'
                    locate = '未知'
                else:
                    nation = tds[0].find('img')['alt'].strip()
                    locate = tds[3].text.strip()
                # 通过td列表里面的数据,我们分别把它们提取出来
                ip = tds[1].text.strip()
                port = tds[2].text.strip()
                anony = tds[4].text.strip()
                protocol = tds[5].text.strip()
                speed = tds[6].find('div')['title'].strip()
                time = tds[8].text.strip()
                # 将获取到的数据按照规定格式写入txt文本中,这样方便我们获取
                proxyFile.write('%s|%s|%s|%s|%s|%s|%s|%s\n' % (nation, ip, port, locate, anony, protocol, speed, time))
    
    
    def verifyProxyList():
        
        verifiedFile = open('verified.txt', 'a')
    
        while True:
            lock.acquire()
            ll = inFile.readline().strip()
            lock.release()
            if len(ll) == 0 : break
            line = ll.strip().split('|')
            ip = line[1]
            port = line[2]
            realip = ip+':'+port
            code = verifyProxy(realip)
            if code == 200:
                lock.acquire()
                print("---Success:" + ip + ":" + port)
                verifiedFile.write(ll + "\n")
                lock.release()
            else:
                print("---Failure:" + ip + ":" + port)
    
    
    
    
    def verifyProxy(ip):
        '''
        验证代理的有效性
        '''
        requestHeader = {
            'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36"
        }
        url = "http://www.baidu.com"
        # 填写代理地址
        proxy = {'http': ip}
        # 创建proxyHandler
        proxy_handler = request.ProxyHandler(proxy)
        # 创建opener
        proxy_opener = request.build_opener(proxy_handler)
        # 安装opener
        request.install_opener(proxy_opener)
    
        try:
            req = request.Request(url, headers=requestHeader)
            rsq = request.urlopen(req, timeout=5.0)
            code = rsq.getcode()
            return code
        except error.URLError as e:
            return e
    
    if __name__ == '__main__':
        tmp = open('proxy.txt', 'w')
        tmp.write("")
        tmp.close()
        tmp1 = open('verified.txt', 'w')
        tmp1.write("")
        tmp1.close()
        getProxy("http://www.xicidaili.com/nn/")
        getProxy("http://www.xicidaili.com/nt/")
        getProxy("http://www.xicidaili.com/wn/")
        getProxy("http://www.xicidaili.com/wt/")
    
        all_thread = []
        for i in range(30):
            t = threading.Thread(target=verifyProxyList)
            all_thread.append(t)
            t.start()
    
        for t in all_thread:
            t.join()
    
        inFile.close()
        verifiedtxt.close()
    

    相关文章

      网友评论

        本文标题:Python建立ip代理池(多线程)

        本文链接:https://www.haomeiwen.com/subject/dzxluqtx.html