轉載自公眾號:JAVAandPythonJun
說在前面的話
Hello,我是JAP君,相信經常使用爬蟲的朋友對代理ip應該比較熟悉,代理ip就是可以模擬一個ip地址去訪問某個網站。我們有時候需要爬取某個網站的大量信息時,可能由于我們爬的次數(shù)太多導致我們的ip被對方的服務器暫時屏蔽(也就是所謂的防爬蟲防洪水的一種措施),這個時候就需要我們的代理ip出場了,今天我?guī)Т蠹襾砼廊∥鞔檀砩厦婷赓M提供的代理ip并且我們來檢測它的有效性來打造我們自己的代理ip池,廢話不多說,咱們動工!
2思路分析(寫爬蟲前大家都必須要分析一下)
沒錯上圖就是我們的西刺代理網站啦,今天我們就是來拿它的數(shù)據(jù),老司機一看這個界面就會自動右擊鼠標->查看源代碼,我們也來看看:
我們會發(fā)現(xiàn)數(shù)據(jù)都在<tr>里面,并且<tr>里面有很多的<td>,每一個<td>都包含了我們所需要的數(shù)據(jù)。
看過我以前一些爬蟲文章的朋友估計一下就知道該怎么下手了,但是不急我們還是來分析一下,畢竟這次數(shù)據(jù)量有點大,而且還得校驗代理ip的有效性。
給大家畫了張圖,其實思路也很簡單,也就不多闡述了。
3獲取所有的代理ip以及相關信息并保存至文件txt中
我們就按照我們的思路來,在這里我們需要用到的幾個庫,給大家寫出來:
from bs4 import BeautifulSoup
import requests
from urllib import request,error
import threading
導入庫后,我們首先獲得代理ip,我們來定義一個方法:(每一句的解釋我都寫在注釋里了)
def getProxy(url):
# 打開我們創(chuàng)建的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,我們發(fā)現(xiàn)原網址+頁碼就是我們需要的網址了,這里的page需要轉換成str類型
urls = url+str(page)
# 通過requests來獲取網頁源碼
rsp = requests.get(urls, headers=headers)
html = rsp.text
# 通過BeautifulSoup,來解析html頁面
soup = BeautifulSoup(html)
# 通過分析我們發(fā)現(xiàn)數(shù)據(jù)在 id為ip_list的table標簽中的tr標簽中
trs = soup.find('table', id='ip_list').find_all('tr') # 這里獲得的是一個list列表
# 我們循環(huán)這個列表
for item in trs[1:]:
# 并至少出每個tr中的所有td標簽
tds = item.find_all('td')
# 我們會發(fā)現(xiàn)有些img標簽里面是空的,所以這里我們需要加一個判斷
if tds[0].find('img') is None:
nation = '未知'
locate = '未知'
else:
nation = tds[0].find('img')['alt'].strip()
locate = tds[3].text.strip()
# 通過td列表里面的數(shù)據(jù),我們分別把它們提取出來
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()
# 將獲取到的數(shù)據(jù)按照規(guī)定格式寫入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去訪問百度所返回的狀態(tài)碼來辨別這個代理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}
# 創(chuàng)建proxyHandler
proxy_handler = request.ProxyHandler(proxy)
# 創(chuàng)建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
我們在這個方法中會得到一個狀態(tài)碼的返回,如果返回碼是200,那么這個代理ip就是可用的。
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調用函數(shù)
萬事俱備只欠調用!
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,所以分別有四個網址。這里我們也采用了線程的方法,主要是為了防止出現(xiàn)線程互相爭奪導致我們的數(shù)據(jù)不精確,在上面幾個方法中我們也通過了同步鎖來對其進行線程安全的保證。
6結尾
其實總體來說這個爬蟲不是特別的難,主要的難點在于數(shù)據(jù)量可能有點多,很多人可能不會考慮到線程安全的問題,導致數(shù)據(jù)獲取的不精確。
全部代碼:
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):
# 打開我們創(chuàng)建的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,我們發(fā)現(xiàn)原網址+頁碼就是我們需要的網址了,這里的page需要轉換成str類型
urls = url+str(page)
# 通過requests來獲取網頁源碼
rsp = requests.get(urls, headers=headers)
html = rsp.text
# 通過BeautifulSoup,來解析html頁面
soup = BeautifulSoup(html)
# 通過分析我們發(fā)現(xiàn)數(shù)據(jù)在 id為ip_list的table標簽中的tr標簽中
trs = soup.find('table', id='ip_list').find_all('tr') # 這里獲得的是一個list列表
# 我們循環(huán)這個列表
for item in trs[1:]:
# 并至少出每個tr中的所有td標簽
tds = item.find_all('td')
# 我們會發(fā)現(xiàn)有些img標簽里面是空的,所以這里我們需要加一個判斷
if tds[0].find('img') is None:
nation = '未知'
locate = '未知'
else:
nation = tds[0].find('img')['alt'].strip()
locate = tds[3].text.strip()
# 通過td列表里面的數(shù)據(jù),我們分別把它們提取出來
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()
# 將獲取到的數(shù)據(jù)按照規(guī)定格式寫入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}
# 創(chuàng)建proxyHandler
proxy_handler = request.ProxyHandler(proxy)
# 創(chuàng)建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()