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

转载自公众号: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()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容