一.瀏覽器代理
1.直接處理:
1.1在setting中配置瀏覽器的各類代理:
user_agent_list=[
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36", ......
]
1.2然后在各個請求中調用:
import random from setting import user_agent_list headers= { "Host":"", ...... "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36", } def parse(self,response): ...... user_agent=random.choice(user_agent_list) self.header["User-Agent"]=user_agent yeild scrapy.Request(request_url,headers=self.headers,callback=...)
1.3缺點:
使用麻煩,各個請求都要調用,而且耦合性高。
2.使用downloader-middlewares:
2.1使用downloader-middleware(setting中默認是注銷了的):
2.2useragent源碼如下(默認的User-Agent為Scraoy,可以直接在setting中配置USER_AGENT="......"就會替換Scrapy如紅框中):
2.3自定義useragentmiddleware(需要在setting中將默認的middleware致為none或數字比自定以的小):
官網簡介
2.3.1直接重寫函數:
#這樣能實現,寫一個random()函數選擇代理,但維護user_agent_list很麻煩,需要重啟spider class RandomUserAgentMiddleware(object): #隨機選擇User-Agent def __init__(self,crawler): super(RandomUserAgentMiddleware,self).__init__() self.user_agent_list=crawler.setting.get("user_agent_list","") @classmethod def from_crawler(cls,crawler): return cls(crawler) def process_request(self,request,spider): request.headers.setdefault('User-Agent',random())
2.3.2fake_useragent的使用:
安裝:pip install fake_useragent
使用:
from fake_useragent import UserAgent ...... class RandomUserAgentMiddleware(object): #隨機選擇User-Agent,所有瀏覽器 def __init__(self,crawler): super(RandomUserAgentMiddleware,self).__init__() self.ua = UserAgent() @classmethod def from_crawler(cls,crawler): return cls(crawler) def process_request(self,request,spider): request.headers.setdefault('User-Agent',self.ua.random)
class RandomUserAgentMiddleware(object): # 隨機選擇User-Agent def __init__(self, crawler): super(RandomUserAgentMiddleware, self).__init__() self.ua = UserAgent() #RANDOM_UA_TYPE為setting中配置的瀏覽器類型 self.ua_type = crawler.settings.get("RANDOM_UA_TYPE", "random") @classmethod def from_crawler(cls, crawler): return cls(crawler) def process_request(self, request, spider): #函數里定義函數(動態語言閉包特性),獲取是哪種瀏覽器類型的隨機 def get_ua(): #相當於取self.ua.ua_type return getattr(self.ua, self.ua_type) request.headers.setdefault('User-Agent', get_ua())
2.3.3自定義中間件配置:
二.IP代理設置
1.重啟路由器:
IP在絕大多數情況會變,用本機IP比用代理IP爬取速度更快。
2.代理IP原理:
1.本機向代理服務器發起請求訪問某個網站——>
2.代理服務器訪問請求的網站——>
3.數據返回給代理服務器——>
4.代理服務器把數據返回給本機。
3.免費ip網站獲取ip(西刺網【設置一定間隔】):

1 # _*_ encoding:utf-8 _*_ 2 __author__ = 'LYQ' 3 __date__ = '2018/10/6 17:16' 4 import requests 5 from scrapy.selector import Selector 6 import MySQLdb 7 8 conn = MySQLdb.Connect(host="localhost", user="root", passwd="112358", db="xici", charset="utf8") 9 cursor = conn.cursor() 10 11 12 def crawl_ips(): 13 headers = { 14 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 15 } 16 for i in range(1, 3460): 17 re = requests.get("http://www.xicidaili.com/nn/{0}".format(i), headers=headers) 18 selector = Selector(text=re.text) 19 ip_lists = selector.css('#ip_list tr') 20 get_ips = [] 21 for ip_list in ip_lists[1:]: 22 speed = ip_list.css(".bar::attr(title)").extract_first() 23 if speed: 24 speed = float(speed.split('秒')[0]) 25 texts = ip_list.css("td::text").extract() 26 ip = texts[0] 27 port = texts[1] 28 proxy_type = ip_list.xpath("td[6]/text()").extract_first() 29 get_ips.append((ip, port, proxy_type, speed)) 30 for ip_info in get_ips: 31 cursor.execute( 32 "INSERT REPLACE INTO proxy_ips(ip,port,type,speed) VALUES('{0}','{1}','{2}','{3}')".format(ip_info[0], 33 ip_info[1], 34 ip_info[2], 35 ip_info[3]) 36 ) 37 conn.commit() 38 39 40 class Get_ip(object): 41 def judge_ip(self, ip, port): 42 # 判斷ip是否可用 43 http_url = 'https://www.baidu.com' 44 proxy_url = 'https://{0}:{1}'.format(ip, port) 45 try: 46 proxy_dict = { 47 'http': proxy_url 48 } 49 response = requests.get(http_url, proxies=proxy_dict) 50 except: 51 print("該ip:{0}不可用".format(ip)) 52 self.delete_ip(ip) 53 return False 54 else: 55 code = response.status_code 56 if code >= 200 and code < 300: 57 print("ip:{0}有效".format(ip)) 58 return True 59 else: 60 print("該ip:{0}不可用".format(ip)) 61 self.delete_ip(ip) 62 return False 63 64 def delete_ip(self, ip): 65 delete_sql = """ 66 delete from proxy_ips where ip='{0}' 67 """.format(ip) 68 cursor.execute(delete_sql) 69 conn.commit() 70 return True 71 72 def get_random_ip(self): 73 random_sql = """ 74 SELECT ip,port from proxy_ips ORDER BY RAND() LIMIT 1 75 """ 76 result = cursor.execute(random_sql) 77 for ip_info in cursor.fetchall(): 78 ip = ip_info[0] 79 port = ip_info[1] 80 judge_re=self.judge_ip(ip, port) 81 if judge_re: 82 return 'http://{0}:{1}'.format(ip,port) 83 else: 84 return self.get_random_ip() 85 86 if __name__=='__main__': 87 # crawl_ips() 88 get_ip = Get_ip() 89 a = get_ip.get_random_ip()
4.ip代理中間件書寫:
class RandomProxyMiddleware(object): #動態代理ip的使用 def process_request(self, request, spider): get_ip=Get_ip() request.meta['proxy']=get_ip.get_random_ip()
5.開源庫的使用(scrapy_proxy處理ip):
scrapy-crawla,haipproxy,scrapy-proxies等,可以在github上查看
6.Tor(洋蔥網絡的使用),可以隱藏ip(需要vpn)
三.驗證碼的識別
1.編碼實現(tesseract-ocr):
需要數據訓練,識別率低。
2.在線打碼(識別率在90%以上):
2.1雲打碼平台的使用:
注冊之后(開發者和用戶模式),可以下載對應的調用實列查看
軟件添加
驗證碼類型
錯誤狀態碼,可以在官網查看所有
2.2識別接口:

1 import json 2 import requests 3 4 class YDMHttp(object): 5 apiurl = 'http://api.yundama.com/api.php' 6 username = '' 7 password = '' 8 appid = '' 9 appkey = '' 10 11 def __init__(self, username, password, appid, appkey): 12 self.username = username 13 self.password = password 14 self.appid = str(appid) 15 self.appkey = appkey 16 17 def balance(self): 18 data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey} 19 response_data = requests.post(self.apiurl, data=data) 20 ret_data = json.loads(response_data.text) 21 if ret_data["ret"] == 0: 22 print ("獲取剩余積分", ret_data["balance"]) 23 return ret_data["balance"] 24 else: 25 return None 26 27 def login(self): 28 data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey} 29 response_data = requests.post(self.apiurl, data=data) 30 ret_data = json.loads(response_data.text) 31 if ret_data["ret"] == 0: 32 print ("登錄成功", ret_data["uid"]) 33 return ret_data["uid"] 34 else: 35 return None 36 37 def decode(self, filename, codetype, timeout): 38 data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)} 39 files = {'file': open(filename, 'rb')} 40 response_data = requests.post(self.apiurl, files=files, data=data) 41 ret_data = json.loads(response_data.text) 42 if ret_data["ret"] == 0: 43 print ("識別成功", ret_data["text"]) 44 return ret_data["text"] 45 else: 46 return None 47 48 if __name__ == "__main__": 49 # 用戶名 50 username = '' 51 # 密碼 52 password = '' 53 # 軟件ID,開發者分成必要參數。登錄開發者后台【我的軟件】獲得! 54 appid = 5921 55 # 軟件密鑰,開發者分成必要參數。登錄開發者后台【我的軟件】獲得! 56 appkey = '4b29b3e33db637975d5e51bdf9f2c03b' 57 # 圖片文件 58 filename = 'getimage.jpg' 59 # 驗證碼類型,# 例:1004表示4位字母數字,不同類型收費不同。請准確填寫,否則影響識別率。在此查詢所有類型 http://www.yundama.com/price.html 60 codetype = 1004 61 # 超時時間,秒 62 timeout = 60 63 # 檢查 64 if (username == 'username'): 65 print ('請設置好相關參數再測試') 66 else: 67 # 初始化 68 yundama = YDMHttp(username, password, appid, appkey) 69 70 # 登陸雲打碼 71 uid = yundama.login() 72 print ('uid: %s' % uid) 73 74 # 查詢余額 75 balance = yundama.balance() 76 print ('balance: %s' % balance) 77 78 # 開始識別,圖片路徑,驗證碼類型ID,超時時間(秒),識別結果 79 text = yundama.decode(filename, codetype, timeout)
結果如下
3.人工打碼:
識別率最高,費用高。
四.配置使爬蟲被識別率降低
1.cookie的禁用:
1.1setting.py中(不需登錄的網站):
COOKIES_ENABLED = False
1.2自動限速(AutoThrottle)擴展:
主要配置(setting中):
AUTOTHROTTLE_ENABLED 默認: False
啟用AutoThrottle擴展。
AUTOTHROTTLE_START_DELAY 默認: 5.0
初始下載延遲(單位:秒)。
AUTOTHROTTLE_MAX_DELAY 默認: 60.0
在高延遲情況下最大的下載延遲(單位秒)。
AUTOTHROTTLE_DEBUG 默認: False
起用AutoThrottle調試(debug)模式,展示每個接收到的response。 您可以通過此來查看限速參數是如何實時被調整的。
1.3不同的spider設置不同的setting:
在spider中設置(這里的屬性會覆蓋setting中的):
custom_setting={ "COOKIES_ENABLED":True, ...... }