目标分析:
大家都有很多需要在淘宝抢购、秒拍的商品,蛮长地等待时间到来并人肉抢商品,总是一件令人烦躁的事情。而github上许多优秀的开源代码,都声称可以自动化完成指定商品抢购,然而当真的运行这些程序时候,就会发现各种各样的小坑需要踩,本文就是想总结一下最近使用此类程序发现的问题,希望能裨补缺漏、有所广益。本人亲测可以正常运行,淘宝也不会检测出正在用机器抢购商品。
原始项目:
https://github.com/Jesseslco/taobao_auto_buy/tree/alpha
这个原始项目是我从众多淘宝自动下单开源程序中,感觉代码最优雅,可扩展性比较好的程序,但是在实际使用过程中,却发现它连基本的订购一个不需要抢购的商品都做不到,下面记录一下我的排错日志。
解决方案:
1. 添加实验性功能参数
现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为undefined。而使用selenium访问则该值为true,我们需要添加如下的option。
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions
opts = ChromeOptions()
opts.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2}) # 不加载图片,加快访问速度
opts.add_experimental_option('excludeSwitches', ['enable-automation']) # 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
driver = Chrome(options=option)
2. 添加字段清除程序
只采用上述代码是不够的,实测还是会被阿里检测机制探测到。所以我们在每个网页刚刚打开,还没有运行网页的脚本前,运行下面给定的脚本。
from selenium.webdriver import Chrome
driver = Chrome('./chromedriver')
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
driver.get('http://baidu.com')
需要特别注意的是,只要出现了打开新的网页或者刷新旧网页事件,我们就需要加一段这样的代码在最前面,比如:
self._browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
self._browser.switch_to.window(self._browser.window_handles[1])
def _click_until_redirect(self, element, current_url):
self._browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
while current_url == self._browser.current_url:
try:
element.click()
except:
continue
3. 通过上述手段,基本旧不会被检测到用了selenium,该代码还有一个坑,也就是chrome drive 版本要和电脑的chrome版本一致。
这里有个宝藏网址,可以下载各种版本。
4. 另外就是如果抢购紧俏物品,最好加一个毫秒级别的定时功能,偷偷告诉你,抢购某超市上面的53度茅台,应该提前750ms左右运行程序。
def _timer(self, buy_time):
buy_time_raw = datetime.strptime(buy_time, "%Y-%m-%d %H:%M:%S:%f")
print(buy_time_raw)
while datetime.now() < buy_time_raw:
self._timer_printer(buy_time_raw)
5. 此时这个框架还不够快,建议修改一下代码逻辑,具体来说:
首先,通过手工的方式把要抢购的物品加入购物车;
然后,清洗一下代码,让程序直接进入你的购物车,到点直接提交需求,把buy函数稍微修改一下,就变成了购物车模式,要注意config里面打开的链接,也要换成你购物车的url。
def _buy(self):
self._logger.info("正在倒计时")
self._timer(self._buy_time)
self._logger.info("开始抢购")
sumit_element = WebDriverWait(self._browser, 300, self.delta).until(EC.element_to_be_clickable((By.ID, "J_Go")))
self._click_until_redirect(sumit_element, self._browser.current_url)
self._logger.info(sumit_element)
#
checkout_element = WebDriverWait(self._browser, 300, self.delta).until(EC.element_to_be_clickable((By.XPATH, "//div[@id='submitOrderPC_1']//a[@class='go-btn']")))
self._logger.info(checkout_element)
self._click_until_redirect(checkout_element, self._browser.current_url)
self._logger.info("抢购结束")
好,谢谢各位朋友,各位朋友耗子尾汁,早日抢到心怡的商品。