Urllib3+BeautifulSoup+Thread:多线程爬虫教程(爬取西刺代理IP)

导入模块

from bs4 import BeautifulSoup
import urllib3
import urllib
import threading 

Urllib3+BeautifulSoup+Thread:多线程爬虫教程(爬取西刺代理IP)

爬虫是学python中最好玩的学习方法,也是方便生活、工作中的有效利器,爬虫帮我们工作,那会节省大量的人力。

在该博客中,分成5个步骤来简单教大家如何用好爬虫。最后贴出源码

1 函数:获取网页内容

urllib3一般是爬虫中必用的打开网页的利器,西刺网站不需要验证用户,获取网页十分简单。若想进一步了解详见官网(英文):http://urllib3.readthedocs.io/en/latest/ ,中文优秀博客:https://blog.csdn.net/LookForDream_/article/details/78624594

#获取网页HTML码
def getContent(url):
    http=urllib3.PoolManager()
    response=http.request('get',url)
    #网页返回200表示可打开网页
    print('网页 %s 返回代码:%s'%(url,response.status))
    return response.data

2 获取每页的代理IP

该步骤是爬虫中最核心的部分,要分析出爬取的网页的规律。网页规律分析不好,写出来的代码可能又臭又长。BeautifulSoup是较为容易上手的解析网页的爬虫工具,BeautifulSoup可调用xml、html.parser、lxml解析器,性能优点各有不同,而官网推荐我们使用lxml解析器。BeautifulSoup中文官网:https://blog.csdn.net/kikaylee/article/details/56841789

Proxys=[]
pages=5
#爬去西刺10页的代理IP
for i in range(0,pages):
    url='http://www.xicidaili.com/nn/%d'%(i+1)
    content=getContent(url) #获取网页内容
    if content!=None:
        soup=BeautifulSoup(content,'lxml')

        #分析网页源码得,tr标签中class=''或class='odd'都满足
        Tags=soup.find_all('tr',attrs={'class':'odd'})+soup.find_all('tr',attrs={'class':''})[1:]

        #获取该页所有的代理IP
        for tag in Tags:
            t=tag.find_all('td')
            ip=t[1].get_text()
            post=t[2].get_text()
            protocol=t[5].get_text().lower() #变小写
            Proxys.append(protocol+'://'+ip+':'+post)

print('共爬取了%d个代理IP'%len(Proxys))

代码结果:

网页 http://www.xicidaili.com/nn/1 返回代码:200
网页 http://www.xicidaili.com/nn/2 返回代码:200
网页 http://www.xicidaili.com/nn/3 返回代码:200
网页 http://www.xicidaili.com/nn/4 返回代码:200
网页 http://www.xicidaili.com/nn/5 返回代码:200
共爬取了500个代理IP

3 函数:测试代理IP是否有效

在这里用的是urllib设置代理IP来测试代理IP是否有效。

def testProxy(pro):
    protocol=pro.split(':')[0]

    #设置urllib中的代理IP
    opener=urllib.request.build_opener( urllib.request.ProxyHandler({protocol:pro}) )
    urllib.request.install_opener(opener)

    #若能打开test_url则保存该代理IP
    try:
        response=urllib.request.urlopen(test_url,timeout=timeout)
        response.read()
    except:
        print("代理IP:%s 无效"%pro)
    else:
        if pro not in alive_Proxys:
            alive_Proxys.append(pro)

4 多线程调用上述函数

单线程测试代理IP是十分缓慢的,故使用多线程。但在使用多线程中要注意join方法阻塞线程到结束。

test_url='http://baidu.com'
n=10 #线程数
timeout=3 
alive_Proxys=[] #保存可用代理

pro=Proxys.pop()
while Proxys:
    T=[]
    for i in range(n):
        t=threading.Thread(target=testProxy,args=(pro,))
        T.append(t)
        t.start()
        if Proxys:
            pro=Proxys.pop()
        else:
            break  

    #阻塞n个进程结束后再重新创建线程
    for t in T:
        t.join()

print("可用代理IP:%d"%len(alive_Proxys))

代码结果:

代理IP:http://114.228.74.205:6666 无效
代理IP:http://222.77.48.46:47437 无效
代理IP:http://223.241.118.205:18118 无效
代理IP:http://123.163.178.116:25746 无效
#中间省略了很多....
可用代理IP:339

5 写入文件

with open('Proxys.txt','w') as fp:
    for line in alive_Proxys:
        fp.write("%s\n"%line)
print("写入完毕")

代码结果:

写入完毕

源码

from bs4 import BeautifulSoup
import urllib3
import urllib
import threading 

#获取网页HTML码
def getContent(url):
    http=urllib3.PoolManager()
    response=http.request('get',url)
    print('网页 %s 返回代码:%s'%(url,response.status))
    return response.data

#测试代理是否可用
def testProxy(pro):
    protocol=pro.split(':')[0]

    #设置urllib中的代理IP
    opener=urllib.request.build_opener( urllib.request.ProxyHandler({protocol:pro}) )
    urllib.request.install_opener(opener)

    #若能打开test_url则保存该代理IP
    try:
        response=urllib.request.urlopen(test_url,timeout=timeout)
        response.read()
    except:
        print("代理IP:%s 无效"%pro)
    else:
        if pro not in alive_Proxys:
            alive_Proxys.append(pro)

#获取代理IP
Proxys=[]
pages=5
#爬去西刺10页的代理IP
for i in range(0,pages):
    url='http://www.xicidaili.com/nn/%d'%(i+1)
    content=getContent(url) #获取网页内容
    if content!=None:
        soup=BeautifulSoup(content,'lxml')

        #分析网页源码得,tr标签中class=''或class='odd'都满足
        Tags=soup.find_all('tr',attrs={'class':'odd'})+soup.find_all('tr',attrs={'class':''})[1:]

        #获取该页所有的代理IP
        for tag in Tags:
            t=tag.find_all('td')
            ip=t[1].get_text()
            post=t[2].get_text()
            protocol=t[5].get_text().lower()
            Proxys.append(protocol+'://'+ip+':'+post)

print('共爬取了%d个代理IP'%len(Proxys))


#测试代理IP是否可用
test_url='http://baidu.com'
n=10 #线程数
timeout=3 
alive_Proxys=[] #保存可用代理

pro=Proxys.pop()
while Proxys:
    T=[]
    for i in range(n):
        t=threading.Thread(target=testProxy,args=(pro,))
        T.append(t)
        t.start()
        if Proxys:
            pro=Proxys.pop()
        else:
            break 

    #阻塞n个进程结束后再重新创建线程
    for t in T:
        t.join()

print("可用代理IP:%d"%len(alive_Proxys))

#写入文件
with open('Proxys.txt','w') as fp:
    for line in alive_Proxys:
        fp.write("%s\n"%line)
print("写入完毕")

谢谢大家的浏览,
希望我的努力能帮助到您,
共勉!

你可能感兴趣的:(Python,爬虫)