工作中与项目中需要取抓取一些股票的实时信息等,有两种取到可以获取到一些需要的数据,一种是花钱买一些接口服务,还有就是爬虫取网站爬取。
本人略了解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缓存去了。