Python 使用 selenium 模擬登陸淘寶

 

 

selenium 模擬登陸淘寶:
https://mp.weixin.qq.com/s?__biz=MzI0OTc0MzAwNA==&mid=2247487680&idx=1&sn=e40947f382116ff59761f250ee45dce3

 

 

學爬蟲,總能聽到「模擬登錄」這四個字,究竟什麼是「模擬登錄」?

通俗一點講,「模擬登錄」就是程序用賬號和密碼自動登錄一個網站。然後,拿到只有登錄後,才能下載的網站數據。比如,我們只有登錄淘寶賬號之後,才能看到購物車裏有哪些東西,這裏,就以「模擬登錄」淘寶爲例進行講解

 

 

1. Selenium

 

模擬登錄無非兩種方法:

  • 請求包分析模擬登錄。這個需要抓包分析請求,解析各種參數,還可能涉及一些加密算法。
  • 自動化測試工具模擬登錄。這個可以繞過一些繁瑣的分析過程,直接定位元素進行操作,但也會遇到一些反爬策略。

兩者,都有各自的操作技巧。這裏使用自動化測試工具 Selenium 模擬登錄。

 

Selenium 是一個自動化測試工具,支持各種主流瀏覽器,例如 Chrome、Safari、Firefox 等。

不知道什麼是自動化測試工具沒關係,我會通過實戰操作,慢慢講解。

不管怎樣,先安裝 Selenium 再說。

pip install selenium

使用 pip 直接安裝 selenium。

除了安裝 Python 的 Selenium 第三方庫,還需要根據瀏覽器配置相應的瀏覽器驅動。

安裝三大瀏覽器驅動 driver
        1. chromedriver 下載地址:http://chromedriver.chromium.org
            chromedriver 鏡像下載地址 :http://npm.taobao.org/mirrors/chromedriver
        2. Firefox 的驅動 geckodriver 下載地址:https://github.com/mozilla/geckodriver/releases
        3. IE 的驅動 IEdriver 下載地址:http://www.nuget.org/packages/Selenium.WebDriver.IEDriver

注意:下載解壓後,將chromedriver.exe , geckodriver.exe , Iedriver.exe 放到 Python 的安裝目錄,例如 D:\python 。 然後再將 Python 的安裝目錄添加到系統環境變量的 Path下面。

爬蟲 Selenium Chromium 與 Chromedriver對應版本( 注意是 chromium,不是 Chrome ):
淘寶鏡像地址在每個文件夾的 notes.txt 中存有 chromium 和 Chromedriver 的版本對應(一般3個chromium版本對應1個Chromedriver 版本)。

chromium     chromedriver
v64-66 v2.37
v63-65 v2.36
v62-64 v2.35
v61-63 v2.34
v60-62 v2.33

然後打開 Python IDE 分別輸入以下代碼來啓動不同的瀏覽器

# 啓動谷歌瀏覽器
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('http://www.baidu.com/')


# 啓動火狐瀏覽器
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('http://www.baidu.com/')


# 啓動IE瀏覽器
from selenium import webdriver
browser = webdriver.Ie()
browser.get('http://www.baidu.com/')

 

 

2. 小試牛刀

 

使用 Selenium 登錄百度看一下。


from selenium import webdriver

if __name__ == "__main__":
    browser = webdriver.Chrome(r'D:\software\Python3\chromedriver.exe')
    # browser = webdriver.Chrome()
    browser.get('https://www.baidu.com/')
    pass

結果如下圖所示:

程序會自動打開 Chrome 瀏覽器,並打開 www.baidu.com。

再來個複雜一些的例子。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys


if __name__ == "__main__":
    # driver = webdriver.Chrome("path\to\your\chromedriver.exe")
    driver = webdriver.Chrome()
    driver.get("https://www.python.org")
    assert "Python" in driver.title
    elem = driver.find_element_by_name("q")
    elem.send_keys("pycon")
    elem.send_keys(Keys.RETURN)
    print(driver.page_source)

運行結果:

寫好程序,瀏覽器自動操作,是不是很簡單,很酷炫?

這就是自動化測試工具,程序寫好,瀏覽器自動執行你的寫的操作。

find_element_by_* 是一種定位網頁元素的方法,有很多方式:

find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector

可以通過,標籤的 id 屬性、name 屬性、class_name 屬性查找元素,也可以通過 xpath 等。

這裏面,其實用到最多的就是 xpath,因爲好用。

不用動腦思考怎麼寫 xpath,就能操作,方便好用。舉個例子,比如我想找到 baidu.com 的搜索框的元素:

在搜索框位置,點擊右鍵,選擇 copy 下的 copy xpath,直接複製 xpath 。

粘貼出來你會看到如下內容://*[@id="kw"]

其實意思就是從根目錄開始找,找到 id 屬性爲 kw 的標籤。

定位到搜索框,就可以通過百度輸入 Jack Cui,搜索我的相關內容。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

if __name__ == "__main__":
    # driver = webdriver.Chrome("path\to\your\chromedriver.exe")
    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")
    elem = driver.find_element_by_xpath('//*[@id="kw"]')
    elem.send_keys("Jack Cui")
    elem.send_keys(Keys.RETURN)

運行結果:

可以看到,運行程序,搜索 Jack Cui,能搜到我的個人網站、CSDN 和知乎等。

Selenium 就是這麼簡單省事。

如果想學習更多,關於 Selenuim 其他的基本方法和 Xpath 的基礎知識,可以看下面文章。

文章地址:https://blog.csdn.net/c406495762/article/details/72331737

詳細的,關於 Selenium 的 API 文檔,可以看官方手冊。

官方手冊:https://selenium-python.readthedocs.io/index.html

好了,基礎知識準備完畢。

只要你會使用 copy xpath,基本的 Selenium 操作,就可以開始跟我一起「模擬登錄」淘寶。

 

 

 

3. 登陸淘寶,掏空錢包

 

1. 模擬登錄淘寶

用 Selenium 模擬登錄,就邊看邊寫,按照人的操作步驟寫代碼即可。

打開淘寶,上來第一步肯定是點擊登錄按鈕,不會寫 XPath,那就複製這個標籤的 XPath。

因此點擊登錄的代碼就是:

browser.find_element_by_xpath('//*[@id="J_SiteNavLogin"]/div[1]/div[1]/a[1]').click()

找到登錄元素位置,然後 click() 點擊。

點擊登錄後,進入登陸頁面,找到賬號框和密碼框位置,並輸入賬號和密碼。

還是簡單粗暴的複製粘貼 XPath 即可。

browser.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username)
browser.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password)

username 和 password 就是你要輸入的賬號和密碼。

輸入完密碼之後,可能會出現一個驗證碼滑動窗口。

這種滑動窗口也好解決,還是複製 XPath 匹配元素,然後使用 Selenium 的 ActionChains 方法,拖動滑塊。

最後點擊登陸按鈕

登陸後,再讀取下用戶名,看下是否登陸成功即可。

分析完畢,直接上代碼。

from selenium import webdriver
import logging
import time
from selenium.common.exceptions import NoSuchElementException, WebDriverException
from retrying import retry
from selenium.webdriver import ActionChains

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class TaoBao(object):
    def __init__(self):
        super(TaoBao, self).__init__()
        # self.browser = webdriver.Chrome("path\to\your\chromedriver.exe")
        self.browser = webdriver.Chrome()
        # 最大化窗口
        self.browser.maximize_window()
        self.browser.implicitly_wait(5)
        self.domain = 'http://www.taobao.com'
        self.action_chains = ActionChains(self.browser)

    def login(self, username, password):
        while True:
            self.browser.get(self.domain)
            time.sleep(1)

            # 會xpath可以簡化這幾步
            # self.browser.find_element_by_class_name('h').click()
            # self.browser.find_element_by_id('fm-login-id').send_keys(username)
            # self.browser.find_element_by_id('fm-login-password').send_keys(password)
            self.browser.find_element_by_xpath('//*[@id="J_SiteNavLogin"]/div[1]/div[1]/a[1]').click()
            self.browser.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username)
            self.browser.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password)
            time.sleep(1)

            try:
                # 出現驗證碼,滑動驗證
                slider = self.browser.find_element_by_xpath("//span[contains(@class, 'btn_slide')]")
                if slider.is_displayed():
                    # 拖拽滑塊
                    self.action_chains.drag_and_drop_by_offset(slider, 258, 0).perform()
                    time.sleep(0.5)
                    # 釋放滑塊,相當於點擊拖拽之後的釋放鼠標
                    self.action_chains.release().perform()
            except (NoSuchElementException, WebDriverException):
                logger.info('未出現登錄驗證碼')

            # 會xpath可以簡化點擊登陸按鈕
            # self.browser.find_element_by_class_name('password-login').click()
            self.browser.find_element_by_xpath('//*[@id="login-form"]/div[4]/button').click()

            nickname = self.get_nickname()
            if nickname:
                logger.info('登錄成功,呢稱爲:' + nickname)
                break
            logger.debug('登錄出錯,5s後繼續登錄')
            time.sleep(5)

    def get_nickname(self):
        self.browser.get(self.domain)
        time.sleep(0.5)
        try:
            return self.browser.find_element_by_class_name('site-nav-user').text
        except NoSuchElementException:
            return ''


if __name__ == '__main__':
    # 填入自己的用戶名,密碼
    username = 'username'
    password = 'password'
    tb = TaoBao()
    tb.login(username, password)

代碼加了一些異常處理,以及 log 信息的打印。這裏需要注意的是,滑塊不是每次都出,所以要加個判斷。

輸入你的賬號和密碼,指定 Chrome 驅動路徑,運行代碼,看看能否如我們所願的登陸成功。

可以看到,賬號密碼,都輸入了,驗證碼也通過。

但是,就是登陸不上!這是爲什麼呢?

 

 

2.淘寶反 Selenium 登陸破解

很簡單,淘寶有反爬蟲,而且是專門針對 Selenium 的。這麼操作,永遠登陸不進去。遇到這種反爬的時候,不要慌,慢慢思考。通常,遇到這種反爬蟲,第一反應就是:驗證碼滑塊滑地太快了。被檢測出來了。我剛開始也是這麼想,所以我自己寫了一個滑動方法。勻速、加速、減速,甚至顫顫巍巍滑動,都不行!顯然,跟驗證碼滑塊無關。這時候,就得學會測試,分析出它的放爬蟲策略。分步測試,你就會發現,賬號密碼程序輸入,滑塊程序滑動,然後暫停程序,我們手動鼠標點擊登錄,就能登陸成功。神奇吧?這是爲啥?我猜測,應該是淘寶,有針對 Selenium 的 find_element_by_* 方法的 click 事件監聽。只要是使用 Selenium 完成的點擊事件,淘寶就不讓你登錄。

具體怎麼實現的我不清楚,但是我知道怎麼破解。

很簡單,Selenium 這個點擊方法不行,那就換個第三方庫唄!

Python 最不缺的就是各種各樣的第三方庫。

pyautogui 瞭解一下。pyautogui 功能強大,可以操控電腦的鼠標,有類似「按鍵精靈」的功能。pyautogui 的有些方法,甚至比「按鍵精靈」更強大。

安裝方法也很簡單,使用 pip 即可。

python -m pip install pyautogui

用法很簡單,截取登錄按鈕那裏的圖片,像這樣:

然後 pyautogui 就可以根據這張圖片,找到按鈕的座標,然後操控電腦的鼠標進行點擊。

coords = pyautogui.locateOnScreen('1.png')
x, y = pyautogui.center(coords)
pyautogui.leftClick(x, y)

就問你強大不?直接修改代碼,開搞!

from selenium import webdriver
import logging
import time
from selenium.common.exceptions import NoSuchElementException, WebDriverException
from retrying import retry
from selenium.webdriver import ActionChains

import pyautogui

pyautogui.PAUSE = 0.5

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class TaoBao(object):
    def __init__(self):
        super(TaoBao, self).__init__()
        # self.browser = webdriver.Chrome("path\to\your\chromedriver.exe")
        self.browser = webdriver.Chrome()
        # 最大化窗口
        self.browser.maximize_window()
        self.browser.implicitly_wait(5)
        self.domain = 'http://www.taobao.com'
        self.action_chains = ActionChains(self.browser)

    def login(self, username, password):
        while True:
            self.browser.get(self.domain)
            time.sleep(1)

            # 會xpath可以簡化這幾步
            # self.browser.find_element_by_class_name('h').click()
            # self.browser.find_element_by_id('fm-login-id').send_keys(username)
            # self.browser.find_element_by_id('fm-login-password').send_keys(password)
            self.browser.find_element_by_xpath('//*[@id="J_SiteNavLogin"]/div[1]/div[1]/a[1]').click()
            self.browser.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username)
            self.browser.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password)
            time.sleep(1)

            try:
                # 出現驗證碼,滑動驗證
                slider = self.browser.find_element_by_xpath("//span[contains(@class, 'btn_slide')]")
                if slider.is_displayed():
                    # 拖拽滑塊
                    self.action_chains.drag_and_drop_by_offset(slider, 258, 0).perform()
                    time.sleep(0.5)
                    # 釋放滑塊,相當於點擊拖拽之後的釋放鼠標
                    self.action_chains.release().perform()
            except (NoSuchElementException, WebDriverException):
                logger.info('未出現登錄驗證碼')

            # 會xpath可以簡化點擊登陸按鈕,但都無法登錄,需要使用 pyautogui 完成點擊事件
            # self.browser.find_element_by_class_name('password-login').click()
            # self.browser.find_element_by_xpath('//*[@id="login-form"]/div[4]/button').click()
            # 圖片地址
            coords = pyautogui.locateOnScreen('./1.png')
            x, y = pyautogui.center(coords)
            pyautogui.leftClick(x, y)

            nickname = self.get_nickname()
            if nickname:
                logger.info('登錄成功,呢稱爲:' + nickname)
                break
            logger.debug('登錄出錯,5s後繼續登錄')
            time.sleep(5)

    def get_nickname(self):
        self.browser.get(self.domain)
        time.sleep(0.5)
        try:
            return self.browser.find_element_by_class_name('site-nav-user').text
        except NoSuchElementException:
            return ''


if __name__ == '__main__':
    # 填入自己的用戶名,密碼
    username = '淘寶用戶名'
    password = '淘寶密碼'
    tb = TaoBao()
    tb.login(username, password)

運行效果:

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章