工作中與項目中需要取抓取一些股票的實時信息等,有兩種取到可以獲取到一些需要的數據,一種是花錢買一些接口服務,還有就是爬蟲取網站爬取。
本人略了解tcp/ip與http以及https協議,后兩者作為建立在tcp/ip之上的應用層,在爬蟲中最麻煩的可能就是cookies的獲取,通過cookies信息,對方服務器就可以判斷
你是機器行為還是可能是人,簡單的網站,可以直接從響應頭獲取到cookies,但如果是通過js設置的cookies或者其它取到設置的,那就很難獲取到。
如果cookies就算拿到了,最近在工作中還碰到在Post請求中,不僅帶上了你的請求信息,還會通過一些算法攜帶一些認證信息,這個攜帶的認證信息,很有可能是通過cookie或者其它的一些參數計算出來的固定或者非固定的值。
如果為固定值,只需要拿到該post請求頭中的請求體信息就好了,如果為變動值,那只能通過破解js代碼的邏輯,自己再算一套【現在還未碰到過如此變態的反爬】
Python的爬蟲中,我個人使用最多的應該是requests模塊,作為封裝在urllib包基礎上的模塊,確實用起來很爽。如果在requests中,帶上需要的頭信息,那對方服務器也就會歡迎你了。
所以讓selenium配合requests那用起來就嗨了。
通過這里作者的轉載:https://www.cnblogs.com/startnow/p/14635147.html
可以發現三種方式,但我個人的總結,其實就是兩種,一種是通過代理將selenium與服務器之間的所有交互攔截下來,然后分析其中的數據,
還有一種本質是通過selenium內部的功能,攔截selenium內部的日志信息,然后通過查看日志,然后找出需要的請求信息。
第一個是selenium-wire來實現,這是包的地址https://github.com/wkeeling/selenium-wire
通過pip可以安裝使用,這個軟件本質也是在selenium與目標地址的交互中,設置了代理,通過代理,可以修改與獲取網絡傳輸中的任何信息。
from seleniumwire import webdriver # Import from seleniumwire # Create a new instance of the Chrome driver driver = webdriver.Chrome() # Go to the Google home page driver.get('https://www.google.com') # Access requests via the `requests` attribute for request in driver.requests: if request.response: print( request.url, request.response.status_code, request.response.headers['Content-Type'] )
這種方式還是比較方便的,你不用自己設置代理,不需要自己取處理繁雜的本地與服務器之間的交互信息,通過該模塊提供的接口就可以實現功能的實現。
第二種方式是通過自己假設代理服務器,來處理瀏覽器與服務器交互的信息
代理的軟件,我使用的是browsermob-proxy,地址在:https://github.com/lightbody/browsermob-proxy
該軟件通過Java編寫,我不懂Java那就看如何用,下面展示的是我在mac上的使用配置。
# 啟動代理 server = Server('browsermob-proxy-2.1-1.4/bin/browsermob-proxy') server.start() proxy = server.create_proxy() # 啟動瀏覽器 # chrome_options = Options() # chrome_options.add_argument('--ignore-certificate-errors') # chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy)) # # chrome_options.add_argument('--headless') # 無頭模式 # browser = webdriver.Chrome(options=chrome_options) chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--ignore-certificate-errors') chrome_options.add_argument("--proxy-server={0}".format(proxy.proxy)) browser = webdriver.Chrome(options=chrome_options) # 監聽結果 url2 = 'https://stockmarketmba.com/symbollookup.php' # url2 ='https://www.baidu.com'
# 新建一個監控助手 proxy.new_har(options={ 'captureContent': True, 'captureHeaders': True }) time.sleep(2) browser.get(url2) time.sleep(3) browser.refresh() time.sleep(2) input_box = browser.find_element_by_xpath('//*[@id="search"]') input_box.send_keys('TSLA\n') time.sleep(5)
# 輸出交互的信息 result = proxy.har print(str(proxy.har)) # 關閉代理和瀏覽器 proxy.close() browser.close()
前面兩種都是通過設置代理的方式獲取網絡的交互信息,在使用瀏覽器的時候會提示連接不安全,雖然我感覺沒啥影響。
第三種是通過selenium內置的性能測試模塊的日志功能來實現讀取selenium的瀏覽器與服務器的交互信息。
from time import sleep from selenium import webdriver from selenium.webdriver import DesiredCapabilities # make chrome log requests capabilities = DesiredCapabilities.CHROME capabilities["loggingPrefs"] = {"performance": "ALL"} # newer: goog:loggingPrefs driver = webdriver.Chrome( desired_capabilities=capabilities, executable_path="./chromedriver" ) # fetch a site that does xhr requests driver.get("https://sitewithajaxorsomething.com") sleep(5) # wait for the requests to take place # extract requests from logs logs_raw = driver.get_log("performance") logs = [json.loads(lr["message"])["message"] for lr in logs_raw] def log_filter(log_): return ( # is an actual response log_["method"] == "Network.responseReceived" # and json and "json" in log_["params"]["response"]["mimeType"] ) for log in filter(log_filter, logs): request_id = log["params"]["requestId"] resp_url = log["params"]["response"]["url"] print(f"Caught {resp_url}") print(driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id}))
如果chrome版本大於75,需要進行一些修改設置
方案1:
from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.chrome.options import Options d = DesiredCapabilities.CHROME d['loggingPrefs'] = { 'performance':'ALL' } chrome_options = Options() chrome_options.add_experimental_option('w3c', False) driver = webdriver.Chrome(desired_capabilities=d, options=chrome_options)
方案2:
import time from selenium import webdriver from selenium.webdriver import DesiredCapabilities capabilities = DesiredCapabilities.CHROME capabilities['goog:loggingPrefs'] = {"performance": "ALL"} # newer: goog:loggingPrefs browser = webdriver.Chrome(desired_capabilities=capabilities) browser.get('https://www.baidu.com') time.sleep(2) logs_raw = browser.get_log("performance") print(type(logs_raw)) browser.close()
這樣,三種方式以及模板,我都貼了,供自己與他們使用參考,雖然我現在沒寫后端,但希望大家寫爬蟲的時候,盡量少用或者不用多線程。
不要給對象服務器太大的壓力,Over
Over不了了,在服務器上面部署selenium必須添加參數headless參數,但一旦添加了headless參數,chrome的頭部信息中,可以從請求頭中看到headless的信息
為了避免被對方服務器發現,這種明顯機器行為的頭部信息,需要手動添加一個假的頭部信息
比如
chrome_options.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:82.0)')
經過本人測試,在headless的情況下,獲取cookie可能失敗,可以在需要cookie的頁面多refresh幾次,好了,今天就寫到這里,我取寫完整的腳本,將頭信息部署到redis緩存去了。