[Python]公式轉圖片程式最後一個知識點多執行緒ip驗證
最好的方式是:用多執行緒方式,使用代理去訪問某個網站,然後輸出可用的代理。
python 爬蟲 ip池怎麼做? - Kaito的回答 - 知乎
https://www.zhihu.com/question/47464143/answer/124035743
嗯知道關鍵詞了,搜尋「多執行緒驗證ip」,非常多結果,選擇自己能看懂思路的,大概知道哪一部分是幹什麼的就行。
我選擇了一個http://www.cnblogs.com/sjzh/p/5990152.html
這是他的源程式,模仿的第一步是分析這個源程式,看看這個源程式方不方便改成我要的功能。
import urllib.request
import urllib
import re
import time
import random
import socket
import threading
#抓取代理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() #關閉檔案
看下結構就行,程式到大概是兩部分,第一部分抓取ip,第二部分驗證ip。我們自己有抓取ip的程式所以前面可以不要,列表proxys[]用來儲存爬取的ip並且傳遞給第二部分使用,那把我們爬取的ip複製到這裡就行了,注意看看格式,proxy_temp = {"http":proxy_host}人家的格式是字典形式的,OK為了避免改第二部分的程式,我們把ip也改成這種格式,對後面的程式就沒有影響了。
import urllib.request
import urllib
import re
import time
import random
import socket
import threading
#抓取代理IP
#整理代理IP格式
ip_list = ['27.40.146.105:61234', '123.163.154.134:808', '110.200.155.21:8118', '116.192.26.17:1080', '39.72.54.28:8118', '112.93.236.224:9797', '115.46.77.233:8123', '114.231.243.208:30544', '14.153.54.167:3128', '117.66.167.30:8118', '110.73.8.147:8123', '219.136.173.59:9999', '116.31.2.113:8118']
all_ip=[]
proxys=[]
for i in ip_list:
proxy = {'http':i}
proxys.append(proxy)
#保證的格式和原來一樣
# 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() #關閉檔案
把我們的ip_list複製過來,修改格式,然後把一下讀寫操作都去掉,我們不要讀寫。執行一下
OK,有錯誤,沒事,有錯誤就對了,通常我們找到的程式都不能直接用,我們試試把提示的錯誤改掉,看看能不能解決。
搜尋「fixture 'i' not found」
我搜索了很多結果,都沒有直接告訴我答案,我都準備換一個程式碼了,我突然想到搜尋過程中錯誤提示是跟一個叫pytest的關鍵詞一起出現,會不會是函式名不能要test?
import urllib.request
import urllib
import re
import time
import random
import socket
import threading
#抓取代理IP
#整理代理IP格式
ip_list = ['27.40.146.105:61234', '123.163.154.134:808', '110.200.155.21:8118', '116.192.26.17:1080', '39.72.54.28:8118', '112.93.236.224:9797', '115.46.77.233:8123', '114.231.243.208:30544', '14.153.54.167:3128', '117.66.167.30:8118', '110.73.8.147:8123', '219.136.173.59:9999', '116.31.2.113:8118']
proxys=[]
for i in ip_list:
proxy = {'http':i}
proxys.append(proxy)
#保證的格式和原來一樣
# proxy_ip=open('proxy_ip.txt','w') #新建一個儲存有效IP的文件
lock=threading.Lock() #建立一個鎖
#驗證代理IP有效性的方法
def iptest(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=iptest,args=[i])
threads.append(thread)
thread.start()
#阻塞主程序,等待所有子執行緒結束
for thread in threads:
thread.join()
# proxy_ip.close() #關閉檔案
終於解決了,如果沒有想到我會怎麼做?我會換一個程式繼續修改。模仿會出現各種問題,學習也是在解決問題中進行的,所以遇到問題是好事,如果你複製粘貼後就實現了你的功能,那你其實學到的就很少,但是如果你遇到各種問題,並且解決了一部分,即使還沒成功,你已經在進步了。這次我是再也不會忘記函式名不能叫test了。
最後只需要把我們需要的內容打印出來即可。
import urllib.request
import urllib
import time
import socket
import threading
ip_list=['27.40.146.105:61234', '123.163.154.134:808', '110.200.155.21:8118', '116.192.26.17:1080', '39.72.54.28:8118', '112.93.236.224:9797', '115.46.77.233:8123', '114.231.243.208:30544', '14.153.54.167:3128', '117.66.167.30:8118', '110.73.8.147:8123', '219.136.173.59:9999', '116.31.2.113:8118']
# 驗證代理IP有效性的方法
proxys=[]
all_ip=[]
for i in ip_list:
proxy = {'http':i}
# print(type(proxy))
proxys.append(proxy)
lock = threading.Lock() # 建立一個鎖
#不可以使用test作為函式或者檔名
def iptest(i):
socket.setdefaulttimeout(5) # 設定全域性超時時間
url = "http://www.baidu.com/" # 打算爬取的網址
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')
all_ip.append(str(proxys[i]['http']))
# 釋放鎖,開啟下一個執行緒
lock.release() # 釋放鎖
except Exception as e:
lock.acquire()
print(proxys[i], e)
lock.release()
# 單執行緒驗證
# 多執行緒驗證
threads = []
start = time.clock()
# print(len(proxys))
for i in range(len(proxys)):
thread = threading.Thread(target=iptest, args=[i])
threads.append(thread)
thread.start()
# 阻塞主程序,等待所有子執行緒結束
for thread in threads:
thread.join()
end = time.clock()
print(all_ip)
print("開始時間: %f s" % start)
print("結束時間: %f s" % end)
print("校驗IP耗時: %f s" % (end - start))
完成了功能,高興之餘別忘了再看看程式,這個程式大概意思是,有多少個ip就建立多少個執行緒,然後每個執行緒都執行的是iptest(i)這個函式,就等於是同時執行著多個iptest(i)函式,所以雖然我還不知道執行緒的一些知識,是不是我修改iptest(i)函式,就可以得到並行執行的其他功能呢?又可以做很多有意思的改進了。
到這裡我們的公式轉圖片程式的半自動化功能就全部實現了,你現在有了爬取ip,多執行緒驗證等手段,你已經可以做一個你自己想要的功能了,還等什麼燥起來吧。
關注微信公眾號,回覆【公式圖片】即可獲取原始碼,同時歡迎加我的個人微信進行交流哦。