文章目錄
一、Scrapy無法返回爬取內容的幾種可能原因
1,ip封鎖爬取
在dos窗口,輸入 scrapy shell +你的網址
response的返回狀態碼是521 - Web 服務器已關閉 - 源服務器拒絕了雲服務器的連接!
HTTP狀態碼200,300,404等是什麼意思?參考一下網址:
https://www.cnblogs.com/cjwxf/p/6186287.html
https://blog.csdn.net/tan6600/article/details/51584087
2,xpath路徑不對
3,xpath路徑出現font,tbody標籤
把它去掉改成 ***/***,之後內容可以正常顯示,說明scrapy識別不了這兩個標籤。
4,xpath路徑不夠明確
觀察你要爬取網頁html結構,對要爬取的元素位置,最好把它的類名或者是id名寫上,以保證路徑的唯一性。
5,robot協議
如果在dos窗口中已經可以提取出要爬取的內容了,說明xpath路徑正確,但是在編寫的爬蟲文件中,執行spider卻不能爬取到結果,而在執行爬蟲程序的dos窗口中,你仔細觀察,發現有robot錯誤,response的返回編碼是503之類的異常編碼,那就需要你在setting.py中,把ROBOTSTXT_OBEY = True 改爲 False。
6,請求頭封鎖
這個網址在瀏覽器中可以打開,但是scrapy中不行,scrapy shell +網址來執行後出現下圖連接錯誤
這是因爲scrapy的默認請求頭是:“User-Agent”:“Scrapy/1.1.2 (+http://scrapy.org)”被網站封鎖了,所以你需要僞造一個網站的請求頭去進入這個網站。
你執行scrapy shell https://www.qiushibaike.com/ -s USER_AGENT=‘Mozilla/5.0’ 發現成功訪問,所以記得僞造請求頭。
參考:https://blog.csdn.net/weixin_44841312/article/details/95670015
————————————————————————————————
二、網站如何識別爬蟲?
方法1:http日誌和流量分析,如果單位時間內某個IP訪問頻率和流量超過特定閾值就可以界定爲爬蟲(封禁IP)
方法2:檢測Headers參數:一般有User-Agent,Referer、Cookies等
1.User-Agent是檢查用戶所用客戶端的種類和版本,在Scrapy中,通常是在下載器中間件中進行處理。
2.Referer是檢查此請求由哪裏來,通常可以做圖片的盜鏈判斷。在Scrapy中,如果某個頁面url是通過之前爬取的頁面提取到,Scrapy會自動把之前爬取的頁面url作爲Referfer。也可以通過上面的方式自己定義Referfer字段。
3.網站可能會檢測Cookie中session_id的使用次數,如果超過限制,就觸發反爬策略。
方法3:在網頁源碼內放置一個對瀏覽器不可見的鏈接,正常用戶使用瀏覽器是看不到該鏈接的當然也不會去點擊,如果檢測到該鏈接被點擊,來訪IP就會被界定爲爬蟲。
三、網站常見反爬蟲策略?
1.臨時或永久封禁來訪ip
2.返回驗證碼
3.異步加載(ajax):使只爬取靜態網頁的爬蟲什麼也得不到
4.爬蟲陷阱:讓你爬取的內容變成其他和本網站無關的信息
5.加速樂的服務:在訪問之前先判斷客戶端的cookie正不正確。如果不正確,返回521狀態碼,set-cookie並且返回一段js代碼通過瀏覽器執行後又可以生成一個cookie,只有這兩個cookie一起發送給服務器,纔會返回正確的網頁內容。
6.javascript渲染:網頁開發者將重要信息放在網頁中但不寫入html標籤中,而瀏覽器會自動渲染
五、實戰演練
1、在setting修改默認的User-Agent、默認HEADERS
參考:
https://blog.csdn.net/weixin_43430036/article/details/84851714
2、IP代理(未驗證)
import requests
url = "http://www.baidu.com"
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
response = requests.get(url, proxies=proxies)
print response.content
3、python爬蟲添加請求頭:
不止有一種,根據用的方法爲request、urllib、phantomjs請求等,有區別。
四、常見反反爬蟲策略?
(1)設置等待時間
① 直接:導入time,然後限制時間爲正常人瀏覽時間
② 間接:看具體情況來等待,比如某些元素需要一定時間加載。wait1.until(lambda driver:driver.find_element_by_xpath("//div[@id=‘link-report’]/span"))
(2 )使用高匿代理IP解決;
(3)針對驗證碼——如果不是每次都彈驗證碼也可以使用高匿代理IP解決,如果感覺高匿代理不穩定或者收集起來不方便使用Tor網絡也可以,如果每次都彈驗證碼那就得涉及到驗證碼識別了,簡單的驗證碼可以自己寫代碼處理,python有不少知名的圖像處理(識別)庫(如PIL/Pillow、Mahotas、Pymorph、pytesser、tesseract-ocr、openCV等)和算法(比如大名鼎鼎的KNN[K鄰近算法]和SVM[支持向量機]);但複雜的驗證碼例如涉及邏輯判斷和計算、字符粘連變形、前置噪音多色干擾、多語種字符混搭的,可能需要調用在線驗證碼識別軟件接口識別驗證碼,正確率百分之八九十以上。
(4)異步加載:網頁內容不會一次性全部展示出來,需要將滾動條滑到最底部才能繼續瀏覽下一頁內容。
① fiddler / wireshark抓包分析ajax請求的界面,再通過規律仿造服務器構造一個請求訪問服務器得到返回的真實數據包。
② 通過PhantomJS+Selenium模擬瀏覽器行爲,抓取經過js渲染後的頁面。phantomjs是一個無頭無界面瀏覽器,使用selenium可以驅動它模擬瀏覽器的一切操作,但缺點也很明顯,爬取效率低;注意的是,調用PhantomJs需要指定PhantomJs的可執行文件路徑,通常是將該路徑添加到系統的path路徑,讓程序執行時自動去path中尋找。使用Selenium後,請求不再由Scrapy的Downloader執行,所以之前添加的請求頭等信息都會失效,需要在Selenium中重新添加。本方法缺點也很明顯,爬取效率低;
(5)爬蟲陷阱:看情況而定,如果是比較簡單的死循環陷阱,可以對爬蟲將要爬取的鏈接進行判斷,不重複爬取相同的頁面,除此之外,對於特定的元素看清之後小心爬取,還可使用scrapy的LinkExtractor設定unique參數爲True即可或者直接設定爬蟲的最大循環次數。
此外增加爬取間隔和禁用cookie也能降低爬蟲被ban的概率。
(6)針對用戶行爲:
① cookie禁用:對於一些不需要登錄的網站,可以在setting.py文件中設置COOKIES_ENABLED = False
② 自動限速:在setting.py文件中設置DOWNLOAD_DELAY = 1
③判斷header:在請求時構造一個header,每次url請求更換一次user-agent。可以百度,也可看看之前的文章
④ 採用代理IP:可以做一個IP代理池,每次運行時隨機挑選一個做訪問IP。IP代理有收費有免費(免費的代理不一定能用,需要先做一下測試)
參考:
https://blog.csdn.net/xiaoxianerqq/article/details/82884725
https://blog.csdn.net/weixin_41931602/article/details/80679623
————————————————————————————————————————————————
csdn代碼是按照這兩個:
https://www.jianshu.com/p/ba1bba6670a6 與 https://www.tuicool.com/articles/VRfQR3U 類似,各有側重點點
仍然是策略與反策略的理論知識 https://www.cnblogs.com/micro-chen/p/8676312.html
繞過反爬蟲策略
1.設置下載延遲
在settings.py文件中設置
DOWNLOAD_DELAY=3
2.禁用Cookie
有些網站會根據訪問的cookie判斷是否爲機器人,除非特殊要求,我們都禁用cookie,在settings.py做如下設置:
COOKIES_ENABLED=False
原理解釋:
服務器對每一個訪問網頁的人都set-cookie,給其一個cookies,當該cookies訪問超過某一個閥值時就BAN掉該COOKIE,過一段時間再放出來,當然一般爬蟲都是不帶COOKIE進行訪問的,然而,網頁上有一部分內容如新浪微博是需要用戶登錄才能查看更多內容。
解決辦法:控制訪問速度,或者某些需要登錄的如新浪微博,在某寶上買多個賬號,生成多個cookies,在每一次訪問時帶上cookies。
3.使用user agent池(配置USER_AGENTS 和 PROXIES)
介紹兩種方法:
一、在setings中寫一個user agent列表並設置隨機方法(讓setings替我們選擇)
二、在settings中寫列表,在middleware.py中創建類,在downloadmiddleware中調用(讓中間件完成選擇)
第一種:settings創建user agent表,導入random,隨機用choise函數調用user agent。
import random
# user agent 列表
USER_AGENT_LIST = [
'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',
'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)',
'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)',
'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)',
'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)',
'iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0',
'Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)',
'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)'
]
# 隨機生成user agent
USER_AGENT = random.choice(USER_AGENT_LIST)
第二種:在middleware中調用user agent。先在setting中註釋user agent 防止干擾,在middlewares中創建類
import random
class UserAgentMiddleware(object):
def __init__(self):
self.user_agent_list = [
'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',
'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)',
'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)',
'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)',
'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)',
'iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0',
'Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)',
'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)'
]
#這個方法會在請求之前執行,所以可以添加代理pi和隨機請求頭等,參數2是發送的請求,參數3是發送請求的spider對象
def process_request(self,request,spider):
request.headers['USER_AGENT']=random.choice(self.user_agent_list)
然後在setting裏面啓用隨機請求頭中間件downloader middleware
DOWNLOADER_MIDDLEWARES = {
'爬蟲名.middlewares.UserAgentMiddleware': 543 #而不是300的吧
}
原理解釋:
“用戶代理”——UA字串的標準格式:瀏覽器標識 (操作系統標識; 加密等級標識; 瀏覽器語言) 渲染引擎標識版本信息。
服務器通過它判斷當前訪問對象是瀏覽器、郵件客戶端還是網絡爬蟲。
很多爬蟲的請求頭是默認的一些很明顯的爬蟲頭python-requests/2.18.4等,當運維人員發現攜帶有這類headers的數據包,直接拒絕訪問,返回403錯誤。
點擊查看關於headers和user_agent?(headers包括UA…)
以上代碼來源1:python爬蟲之scrapy中user agent淺談(兩種方法)
來源2:scrapy框架-下載中間件
解決方法:把headers僞裝成百度爬蟲或者其他瀏覽器頭即可。
關於隨機請求頭https://blog.csdn.net/qingminxiehui/article/details/81671161?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
4.使用IP池
修改settings.py文件中,b):添加代理IP設置PROXIES
PROXIES = [
{'ip_port': '111.11.228.75:80', 'user_pass': ''},
{'ip_port': '120.198.243.22:80', 'user_pass': ''},
{'ip_port': '111.8.60.9:8123', 'user_pass': ''},
{'ip_port': '101.71.27.120:80', 'user_pass': ''},
{'ip_port': '122.96.59.104:80', 'user_pass': ''},
{'ip_port': '122.224.249.122:8088', 'user_pass': ''},
]
#代理IP可以網上搜索一下,上面的代理IP獲取自:http://www.xici.net.co/
原理解釋:
web server應對爬蟲的策略之一就是直接將你的IP或者是整個IP段都封掉禁止訪問,這時候,當IP封掉後,轉換到其他的IP繼續訪問即可。
第二種思路:
IP代理這是應對反爬蟲的大招,可是免費的代理速度太慢,優質的代理收費又太高,所以個人推薦最好的方式就是ADSL重撥,目的就是通過ADSL的重撥使IP發生變化,窮人的IP池。
5.分佈式爬取:
採用分佈式爬取。暫時不講。
6.驗證碼驗證:
解決辦法:
python可以通過一些第三方庫如(pytesser,PIL)來對驗證碼進行處理,識別出正確的驗證碼,複雜的驗證碼可以通過機器學習讓爬蟲自動識別複雜驗證碼,讓程序自動識別驗證碼並自動輸入驗證碼繼續抓取
7.javascript渲染:
網頁開發者將重要信息放在網頁中但不寫入html標籤中,而瀏覽器會自動渲染
解決辦法:通過分析提取script中的js代碼來通過正則匹配提取信息內容或通過webdriver+phantomjs直接進行無頭瀏覽器渲染網頁。
案例:前程無憂網隨便打開一個前程無憂工作界面,直接用requests.get對其進行訪問,可以得到一頁的20個左右數據,顯然得到的不全,而用webdriver訪問同樣的頁面可以得到50個完整的工作信息。
8.ajax異步傳輸:
訪問網頁的時候服務器將網頁框架返回給客戶端,在與客戶端交互的過程中通過異步ajax技術傳輸數據包到客戶端,呈現在網頁上,爬蟲直接抓取的話信息爲空。
解決辦法:
通過fiddler或是wireshark抓包分析ajax請求的界面,然後自己通過規律仿造服務器構造一個請求訪問服務器得到返回的真實數據包。
案例:
拉勾網打開拉勾網的某一個工作招聘頁,可以看到許許多多的招聘信息數據,點擊下一頁後發現頁面框架不變化,url地址不變,而其中的每個招聘數據發生了變化,通過chrome開發者工具抓包找到了一個叫請求了一個叫做https://www.lagou.com/zhaopin/Java/2/?filterOption=3的網頁。打開該網頁發現爲第二頁真正的數據源,通過仿造請求可以抓取每一頁的數據。
9.加速樂:
有些網站使用了加速樂的服務,在訪問之前先判斷客戶端的cookie正不正確。如果不正確,返回521狀態碼,set-cookie並且返回一段js代碼通過瀏覽器執行後又可以生成一個cookie,只有這兩個cookie一起發送給服務器,纔會返回正確的網頁內容。
解決辦法:詳見https://www.cnblogs.com/micro-chen/p/8676312.html
10.?
注:
很多網頁的運維者通過組合以上幾種手段,然後形成一套反爬策略,就像之前碰到過一個複雜網絡傳輸+加速樂+cookies時效的反爬手段。
切記,放在requests中訪問的headers信息一定要和你操控的瀏覽器headers信息一致,因爲服務器端也會檢查cookies與headers信息是否一致。
——————————————————————————
存儲數據
採用MongoDB數據存儲爬取的漏洞數據。 https://www.jianshu.com/p/ba1bba6670a6