新手參考學習了http://cuiqingcai.com/3256.html,原版寫的真的很好!感謝!
會遇到網站反爬蟲策略下面幾點:
- 1 / 限制IP訪問頻率,超過頻率就斷開連接。(這種方法解決辦法就是,降低爬蟲的速度在每個請求前面加上time.sleep;或者不停的更換代理IP,這樣就繞過反爬蟲機制啦!)
- 2 / 後臺對訪問進行統計,如果單個userAgent訪問超過閾值,予以封鎖。(效果出奇的棒!不過誤傷也超級大,一般站點不會使用,不過我們也考慮進去
- 3/ 還有針對於cookies的 (這個解決辦法更簡單,一般網站不會用)
import requests
import re
import random
#創建一個反反爬的類
class download:
def __init__(self):
self.user_agent_list[
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
def get(self,url):
UA = random.choice(self,user_agent_list)##從user_agent_list中隨機取出一個字符串。
headers = {'User_Agent':UA}##構造一個完整的User_Agent
response = requests.get(url,headers=headers)
return response
————處理IP訪問頻率問題#導入需要的包
from bs4 import BeautifulSoup
import os
from BackClimb import request
#建立一個抓圖類
class mzitu():
#主入口函數
def all_url(self,url):
html = request.get(url,3) ##調用request函數吧地址傳進去,返回一個response
all_a = BeautifulSoup(html.text,'lxml').find('div',class_='all').find_all('a')##用Soup對象的find方法找標籤先查找class爲all的div標籤,然後查找所有<a>標籤。find_all是查找所有<a>標籤
for a in all_a:
title = a.get_text()
print(u'開始保存:',title)##提示保存XXX
path = str(title).replace('?','_')##設置名字變量,將?替換成_
self.mkdir(path)##調用mkdir函數創建文件夾,path代表的是標題名
os.chdir('F:\mzitu\\'+path) ##改變工作路徑
href = a['href']##取出<a>裏面的href屬性
self.html(href)##調用html函數吧href參數傳遞過去,href是套圖的地址
#設置一個函數處理套圖地址獲得圖片的頁面地址
def html(self,href):
html = request.get(href,3)##調用request函數把套圖地址傳進去,返回一個response
max_span = BeautifulSoup(html.text,'lxml').find_all('span')[10].get_text()##查找所有的<span>標籤獲取最後一個標籤中的文本也就是最後一個頁面了
for page in range(1,int(max_span)+1):##用range產生頁面序列
page_url = href + '/'+str(page)##手動拼接每一個頁面地址
self.img(page_url)##調用img函數
#設置一個函數處理圖片頁面地址獲得圖片的實際地址
def img(self,page_url):
img_html = request.get(page_url,3)##調用request函數把圖片頁面地址傳進去,返回一個response
img_url = BeautifulSoup(img_html.text,'lxml').find('div',class_='main-image').find('img')['src']##用img_Soup對象的find方法找標籤先查找class爲main-image的div標籤,然後查找<img>標籤裏面的src。
self.save(img_url)##調用save函數保存圖片,把img_url地址傳遞過去
#設置一個保存圖片的函數
def save(self,img_url):
name = img_url[-9:-4]##取url的倒數第四至第九位做圖片的名字
print('開始保存:',img_url)
img = request.get(img_url,3)##調用request函數把圖片地址傳進去,返回一個response
f = open(name+'.jpg','ab')##寫入多媒體文件必須要b這個參數
f.write(img.content)##多媒體文件要用conctent
f.close()##關閉文件對象
#創建一個函數用來創建文件夾
def mkdir(self,path):
path = path.strip() ##去除path前後空格
isExists = os.path.exists(os.path.join('F:\mzitu',path))##join將各部分合成一個路徑名。os.path.exists判斷後面的路徑是否存在
if not isExists: ##如果爲False,創建文件夾
print(u'創建了一個名字叫做',path,u'的文件夾!')
os.makedirs(os.path.join('F:\mzitu',path))##創建多層文件夾,用join合成單獨的一個路徑文件夾
return True
else:
print(u'名字叫做',path,u'的文件夾已經存在了!')
return False
#
# #創建獲取網頁response的函數並返回
# def request(self,url):
# headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}#設置瀏覽器請求頭
# content = requests.get(url,headers=headers) ##使用requests中的get方法獲取頁面的內容,加上瀏覽器請求頭
# return content
Mzitu = mzitu() ##實例化
#這就是入口!
Mzitu.all_url('http://www.mzitu.com/all')
——反反爬代碼import requests
import re
import random
import time
#創建一個反反爬的類
class download:
def __init__(self):
self.iplist = [] ##初始化一個list用來存放獲取到的ip
html = requests.get(' http://haoip.cc/tiqu.htm')##使用requests中的get方法獲取頁面的內容
iplistn = re.findall(r'r/>(.*?)<b',html.text,re.S)##正則表達式,表示從html中獲取所有r/><b中的內容,re.S的意思是包括匹配包括換行符,findall返回的是列表
for ip in iplistn:
i = re.sub('\n','',ip)##利用re.sub替換方法,將\n替換爲空
self.iplist.append(i.strip())##將兩端去除空格後添加到上面的list裏面
self.user_agent_list=[
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
def get(self,url,timeout,proxy=None,num_retries=6):##給函數一個默認參數proxy爲空,默認num_retries爲6次
UA = random.choice(self.user_agent_list)##從user_agent_list中隨機取出一個字符串。
headers = {'User_Agent':UA}##構造一個完整的User_Agent
if proxy == None:##當代理爲空時,不使用代理獲取response
try:
return requests.get(url,headers=headers)##返回一個requests.get的頁面文件,調用隨機的headers,服務器以爲我們是真的瀏覽器了
except:##如果上面的代碼執行報錯則執行下面的代碼
if num_retries >0: ##num_retries是限定的重試次數
time.sleep(10) ##延遲10秒
print(u'獲取網頁出錯,10s後將獲取倒數第:',num_retries,u'次')
return self.get(url,timeout,num_retries-1)##調用自身,並減1,實現循環6次
else:
print(u'開始使用代理')
time.sleep(10)
IP = ''.join(str(random.choice(self.iplist)).strip())##將從self.iplist中隨機獲取的字符串處理成需要的格式。去除兩邊空格後,用join拼接?
proxy = {'http':IP}
return self.get(url,timeout,proxy)##代理不爲空的時候
else: ##當代理不爲空
try:
IP = ''.join(str(random.choice(self.iplist)).strip())##將從self.iplist中隨機獲取的字符串處理成需要的格式。去除兩邊空格後,用join拼接?
proxy = {'http':IP}##構造成一個代理
return requests.get(url,headers=headers,proxies = proxy,timeout=timeout)##使用代理獲取response
except:
if num_retries >0:
time.sleep(10)
IP = ''.join(str(random.choice(self.iplist)).strip())
proxy = {'http':IP}
print(u'正在更換代理,10s後將重新獲取倒數第',num_retries,u'次')
print(u'當前代理是:',proxy)
return self.get(url,timeout,proxy,num_retries-1)
else:
print(u'代理也不好使!取消代理')
return self.get(url,3)
request = download()