淘寶爬蟲(chóng)之自動(dòng)登錄

最近在做一些淘寶數(shù)據(jù)的定時(shí)抓取demo參考github寝衫,關(guān)于定時(shí)任務(wù)的設(shè)置上一篇已經(jīng)介紹過(guò):APScheduler定時(shí)任務(wù)框架的使用迫筑,作為亞洲第一大電商平臺(tái)洞慎,淘寶的反爬機(jī)制是非常完善的埂材,在用selenium登陸淘寶的時(shí)候發(fā)現(xiàn)淘寶能檢測(cè)到并彈出滑塊,然后無(wú)論怎么滑動(dòng)都通過(guò)不了恤浪,在經(jīng)過(guò)一番搜索后發(fā)現(xiàn)很多網(wǎng)站對(duì)selenium都有檢測(cè)機(jī)制畅哑,如檢測(cè)是否存在特有標(biāo)識(shí) $cdc_asdjflasutopfhvcZLmcfl 、navigator.webdriver等水由。根據(jù)這條線索荠呐,可以在淘寶的js里找到了相關(guān)的檢測(cè)代碼:

檢測(cè)代碼.png

在控制臺(tái)下輸入window.navigator.webdriver會(huì)發(fā)現(xiàn)和正常的瀏覽器打開(kāi)的有所不同

屏幕快照 2019-02-14 下午5.38.45.png

如果瀏覽器是正常打開(kāi)的話,navigator.webdriver大的值應(yīng)該是undefined或者false砂客,如果為true說(shuō)明能檢測(cè)到selenium
原因發(fā)現(xiàn)以后怎么去解決這個(gè)問(wèn)題就比較頭疼了泥张,后來(lái)在一篇文章中發(fā)現(xiàn),針對(duì)這個(gè)問(wèn)題的兩個(gè)解決方案鞭盟,編輯chromedriver發(fā)現(xiàn)cdc_asdjflasutopfhvcZLmcfl是chromedriver里面的一個(gè)變量名圾结,我們只需要將這個(gè)變量名改成其他的就好了,變量名修改教程在《Can a website detect when you are using selenium with chromedriver?
Mac版本的可以通過(guò)如下方法將 cdc_ 替換為 dog_

perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver
//替換完成后查找下齿诉,如果查找不到說(shuō)明替換成功了
perl -ne 'while(/cdc_/g){print "$&\n";}' /path/to/chromedriver

Windows或者Linux版本可以利用Vim將 cdc_ 替換為 dog_

 vim /path/to/chromedriver

Mac和win已經(jīng)修改好的最新版Chromedriver可以參考百度云鏈接: https://pan.baidu.com/s/1392txVPKDMczBIrUP3noIA 提取碼: bnm3
其次針對(duì)navigator.webdriver 通過(guò)mitmproxy做中間人代理將對(duì)應(yīng)的屏蔽代碼注入到原網(wǎng)站中從而達(dá)到規(guī)避檢測(cè)目的

首先是配置mitmproxy

注入屏蔽代碼

TARGET_URL = 'https://g.alicdn.com/secdev/sufei_data/3.6.8/index.js'
INJECT_TEXT = 'Object.defineProperties(navigator,{webdriver:{get:() => false}});'

def response(flow):
    if flow.request.url.startswith(TARGET_URL):
        flow.response.text = INJECT_TEXT + flow.response.text
        print('注入成功')

    if 'um.js' in flow.request.url or '115.js' in flow.request.url:
    # 屏蔽selenium檢測(cè)
        flow.response.text = flow.response.text + INJECT_TEXT

在運(yùn)行前啟動(dòng)代理

mitmdump -s httpProxy.py -p 9000

淘寶自動(dòng)登錄

# -*- coding:UTF-8 -*-
import time
import re
from datetime import date, timedelta
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options

TB_LOGIN_URL = 'https://login.taobao.com/member/login.jhtml'
CHROME_DRIVER = '/usr/local/bin/chromedriver'    # Windows和Mac的配置路徑不一樣

class SessionException(Exception):
    """
    會(huì)話異常類(lèi)
    """
    def __init__(self, message):
        super().__init__(self)
        self.message = message

    def __str__(self):
        return self.message

class Crawler:

    def __init__(self):
        self.browser = None

    def start(self, username, password):
        print("初始化瀏覽器")
        self.__init_browser()
        print("切換至密碼輸入框")
        self.__switch_to_password_mode()
        time.sleep(0.5)
        print("輸入用戶名")
        self.__write_username(username)
        time.sleep(2.5)
        print("輸入密碼")
        self.__write_password(password)
        time.sleep(3.5)
        print("程序模擬解鎖")
        if self.__lock_exist():
            self.__unlock()
        print("開(kāi)始發(fā)起登錄請(qǐng)求")
        self.__submit()
        time.sleep(4.5)
        # 登錄成功筝野,直接請(qǐng)求頁(yè)面
        print("登錄成功,跳轉(zhuǎn)至目標(biāo)頁(yè)面")
        self.__navigate_to_target_page()
        time.sleep(6.5)
        print("解析頁(yè)面文本")
        crawler_list = self.__parse_page_content();
        # 連接數(shù)據(jù)庫(kù)并保存數(shù)據(jù)
        print("保存數(shù)據(jù)到mysql數(shù)據(jù)庫(kù)")
        self.__save_list_to_db(crawler_list)

    def __switch_to_password_mode(self):
        """
        切換到密碼模式
        :return:
        """
        if self.browser.find_element_by_id('J_QRCodeLogin').is_displayed():
            self.browser.find_element_by_id('J_Quick2Static').click()

    def __write_username(self, username):
        """
        輸入賬號(hào)
        :param username:
        :return:
        """
        username_input_element = self.browser.find_element_by_id('TPL_username_1')
        username_input_element.clear()
        username_input_element.send_keys(username)

    def __write_password(self, password):
        """
        輸入密碼
        :param password:
        :return:
        """
        password_input_element = self.browser.find_element_by_id("TPL_password_1")
        password_input_element.clear()
        password_input_element.send_keys(password)

    def __lock_exist(self):
        """
        判斷是否存在滑動(dòng)驗(yàn)證
        :return:
        """
        return self.__is_element_exist('#nc_1_wrapper') and self.browser.find_element_by_id(
            'nc_1_wrapper').is_displayed()

    def __unlock(self):
        """
        執(zhí)行滑動(dòng)解鎖
        :return:
        """
        bar_element = self.browser.find_element_by_id('nc_1_n1z')
        ActionChains(self.browser).drag_and_drop_by_offset(bar_element, 800, 0).perform()
        time.sleep(1.5)
        self.browser.get_screenshot_as_file('error.png')
        if self.__is_element_exist('.errloading > span'):
            error_message_element = self.browser.find_element_by_css_selector('.errloading > span')
            error_message = error_message_element.text
            self.browser.execute_script('noCaptcha.reset(1)')
            raise SessionException('滑動(dòng)驗(yàn)證失敗, message = ' + error_message)

    def __submit(self):
        """
        提交登錄
        :return:
        """
        self.browser.find_element_by_id('J_SubmitStatic').click()
        time.sleep(0.5)
        if self.__is_element_exist("#J_Message"):
            error_message_element = self.browser.find_element_by_css_selector('#J_Message > p')
            error_message = error_message_element.text
            raise SessionException('登錄出錯(cuò), message = ' + error_message)

    #跳轉(zhuǎn)至目標(biāo)頁(yè)面
    def __navigate_to_target_page(self):
        pass
    # 解析網(wǎng)頁(yè)數(shù)據(jù)
    def __parse_page_content(self):
        pass
    #保存數(shù)據(jù)
    def __save_list_to_db(self, crawler_list):
        pass

    def __init_browser(self):
        """
        初始化selenium瀏覽器
        :return:
        """
        options = Options()
        # options.add_argument("--headless")
        prefs = {"profile.managed_default_content_settings.images": 1}
        options.add_experimental_option("prefs", prefs)
        options.add_argument('--proxy-server=http://127.0.0.1:9000')
        options.add_argument('disable-infobars')
        options.add_argument('--no-sandbox')

        self.browser = webdriver.Chrome(executable_path=CHROME_DRIVER, options=options)
        self.browser.implicitly_wait(3)
        self.browser.maximize_window()
        self.browser.get(TB_LOGIN_URL)


#執(zhí)行命令行
Crawler().start('username'), 'password'))

這篇文章主要用來(lái)記錄自己在爬蟲(chóng)過(guò)程中遇到問(wèn)題的解決方案demo參考github粤剧,主要的參考文章是python利用selenium實(shí)現(xiàn)淘寶自動(dòng)登錄

當(dāng)然也有一些其他的解決方案歇竟,例如cookie驗(yàn)證登錄或是支付寶登錄等,這些還沒(méi)嘗試過(guò)抵恋,另外這篇文章也可以作為參考實(shí)踐一下淘寶爬蟲(chóng) 之 登陸驗(yàn)證(二)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末焕议,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子弧关,更是在濱河造成了極大的恐慌盅安,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件世囊,死亡現(xiàn)場(chǎng)離奇詭異别瞭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)株憾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)蝙寨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嗤瞎,你說(shuō)我怎么就攤上這事墙歪。” “怎么了贝奇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵虹菲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我掉瞳,道長(zhǎng)届惋,這世上最難降的妖魔是什么髓帽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮脑豹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衡查。我一直安慰自己瘩欺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布拌牲。 她就那樣靜靜地躺著俱饿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪塌忽。 梳的紋絲不亂的頭發(fā)上拍埠,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音土居,去河邊找鬼枣购。 笑死,一個(gè)胖子當(dāng)著我的面吹牛擦耀,可吹牛的內(nèi)容都是我干的棉圈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼眷蜓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼分瘾!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吁系,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤德召,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后汽纤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體上岗,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年冒版,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了液茎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辞嗡,死狀恐怖捆等,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情续室,我是刑警寧澤栋烤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站挺狰,受9級(jí)特大地震影響明郭,放射性物質(zhì)發(fā)生泄漏买窟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一薯定、第九天 我趴在偏房一處隱蔽的房頂上張望始绍。 院中可真熱鬧,春花似錦话侄、人聲如沸亏推。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吞杭。三九已至,卻和暖如春变丧,著一層夾襖步出監(jiān)牢的瞬間芽狗,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工痒蓬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留童擎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓谊却,卻偏偏與公主長(zhǎng)得像柔昼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炎辨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容