纵有疾风起
人生不言弃

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

转载自公众号:JAVAandPythonJun

说在前面的话

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

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

Python建立ip代理池(多线程)插图
image
Python建立ip代理池(多线程)插图1
image

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

Python建立ip代理池(多线程)插图2
image

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

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

Python建立ip代理池(多线程)插图3
image

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

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

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

from bs4 import BeautifulSoupimport requestsfrom urllib import request,errorimport 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就是可用的。

Python建立ip代理池(多线程)插图4
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 BeautifulSoupimport requestsfrom urllib import request,errorimport threadinginFile = 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 eif __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()

文章转载于:https://www.jianshu.com/p/2daa34a435df

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » Python建立ip代理池(多线程)
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录