一、抓取代理IP
提供免费代理IP的网站还挺多的,我在‘西刺代理’上一阵猛抓后自己的IP就被其屏蔽了。只好换‘IP巴士’并乖乖的减缓抓取速度了。贴上抓取代码
import urllib.request
import urllib
import re
import time
import random
'''
遇到不懂的问题?Python学习交流群:821460695满足你的需求,资料都已经上传群文件,可以自行下载!
'''
#抓取代理IP
ip_totle=[] #所有页面的内容列表
for page in range(2,6):
url='http://ip84.com/dlgn/'+str(page)
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64)"}
request=urllib.request.Request(url=url,headers=headers)
response=urllib.request.urlopen(request)
content=response.read().decode('utf-8')
print('get page',page)
pattern=re.compile('<td>(\d.*?)</td>') #截取<td>与</td>之间第一个数为数字的内容
ip_page=re.findall(pattern,str(content))
ip_totle.extend(ip_page)
time.sleep(random.choice(range(1,3)))
#打印抓取内容
print('代理IP地址 ','\t','端口','\t','速度','\t','验证时间')
for i in range(0,len(ip_totle),4):
print(ip_totle[i],' ','\t',ip_totle[i+1],'\t',ip_totle[i+2],'\t',ip_totle[i+3])
复制以上代码即可抓取IP巴士上的大陆高匿代理IP了,其他地区或类型的可自行改URL,可能是网站内容在实时更新的原因,若从第一页开始抓取不怎么稳定,所以我从第二页开始抓取,打印部分结果如下
[外链图片转存失败(img-AQRrf0dZ-1566201089224)(https://upload-images.jianshu.io/upload_images/13406307-f2435ba70986e2df.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
二、验证代理IP的有效性
由于所处的网络可能连不上此代理或该代理连不上目标网址等原因,我们抓取的代理有可能是无效的,我们有必要验证所抓取代理IP的有效性。在urllib.request包中的ProxyHandler类可以设置代理访问网页,代码如下
import urllib.request
url = "http://quote.stockstar.com/stock" #打算抓取内容的网页
proxy_ip={'http': '27.17.32.142:80'} #想验证的代理IP
proxy_support = urllib.request.ProxyHandler(proxy_ip)
opener = urllib.request.build_opener(proxy_support)
opener.addheaders=[("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64)")]
urllib.request.install_opener(opener)
print(urllib.request.urlopen(url).read())
三、多线程快速验证
多线程验证的主要程序如下
#多线程验证
threads=[]
for i in range(len(proxys)):
thread=threading.Thread(target=test,args=[i])
threads.append(thread)
thread.start()
#阻塞主进程,等待所有子线程结束
for thread in threads:
thread.join()
一开始我我令元组参数args=(i),结果报‘test() argument after * must be an iterable, not int’的错误,误打误撞把小括号改为中括号后就有用了,暂时不解中其缘由,望知情者能告知。程序部分运行结果如下
[外链图片转存失败(img-wgO3xpRD-1566201089225)(https://upload-images.jianshu.io/upload_images/13406307-438be3e7ef079162.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
亲测多线程验证比单线程验证快了好几倍,所以以后在爬取网页量比较大时就可以先用此程序抓一些有效的代理IP,这样就可以解决IP被屏蔽的问题啦。
python3抓取代理IP并用多线程快速验证的完整代码如下
import urllib.request
import urllib
import re
import time
import random
import socket
import threading
'''
遇到不懂的问题?Python学习交流群:821460695满足你的需求,资料都已经上传群文件,可以自行下载!
'''
#抓取代理IP
ip_totle=[]
for page in range(2,6):
url='http://ip84.com/dlgn/'+str(page)
#url='http://www.xicidaili.com/nn/'+str(page) #西刺代理
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64)"}
request=urllib.request.Request(url=url,headers=headers)
response=urllib.request.urlopen(request)
content=response.read().decode('utf-8')
print('get page',page)
pattern=re.compile('<td>(\d.*?)</td>') #截取<td>与</td>之间第一个数为数字的内容
ip_page=re.findall(pattern,str(content))
ip_totle.extend(ip_page)
time.sleep(random.choice(range(1,3)))
#打印抓取内容
print('代理IP地址 ','\t','端口','\t','速度','\t','验证时间')
for i in range(0,len(ip_totle),4):
print(ip_totle[i],' ','\t',ip_totle[i+1],'\t',ip_totle[i+2],'\t',ip_totle[i+3])
#整理代理IP格式
proxys = []
for i in range(0,len(ip_totle),4):
proxy_host = ip_totle[i]+':'+ip_totle[i+1]
proxy_temp = {"http":proxy_host}
proxys.append(proxy_temp)
proxy_ip=open('proxy_ip.txt','w') #新建一个储存有效IP的文档
lock=threading.Lock() #建立一个锁
#验证代理IP有效性的方法
def test(i):
socket.setdefaulttimeout(5) #设置全局超时时间
url = "http://quote.stockstar.com/stock" #打算爬取的网址
try:
proxy_support = urllib.request.ProxyHandler(proxys[i])
opener = urllib.request.build_opener(proxy_support)
opener.addheaders=[("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64)")]
urllib.request.install_opener(opener)
res = urllib.request.urlopen(url).read()
lock.acquire() #获得锁
print(proxys[i],'is OK')
proxy_ip.write('%s\n' %str(proxys[i])) #写入该代理IP
lock.release() #释放锁
except Exception as e:
lock.acquire()
print(proxys[i],e)
lock.release()
#单线程验证
'''for i in range(len(proxys)):
test(i)'''
#多线程验证
threads=[]
for i in range(len(proxys)):
thread=threading.Thread(target=test,args=[i])
threads.append(thread)
thread.start()
#阻塞主进程,等待所有子线程结束
for thread in threads:
thread.join()
proxy_ip.close() #关闭文件