如何用 Python 爬取 QQ 空間說說和相冊?

文 | 某某白米飯
python

來源:Python 技術「ID: pythonall」web

QQ 空間在 2005 年被騰訊開發,已經經歷了 15 個年頭,在尚未微信的年代,看網友發表的心情、心事、照片大多都在 QQ 空間的裏。它承載了80、90 後的大量青春,下面咱們一塊兒用 selenium 模塊導出說說和相冊回憶青春吧chrome

安裝 selenium

selenium 是一個在瀏覽器中運行,以模擬用戶操做瀏覽器的方式獲取網頁源碼,使用 pip 安裝 selenium 模塊npm

pip install selenium

查看 chrome 瀏覽器版本並下載 對應的 chrome 瀏覽器驅動canvas

http://npm.taobao.org/mirrors/chromedriver 網址中找到相同版本的 chrome 驅動,並放在 python 程序運行的同一個文件夾中瀏覽器

登錄

按 F12 檢擦網頁源代碼,找到登陸和密碼的文本框,以下圖所示微信

def login(login_qq,password, business_qq):
    '''
    登錄
    :param login_qq: 登錄用的QQ
    :param password: 登錄的QQ密碼
    :param business_qq: 業務QQ
    :return: driver
    '''

    driver = webdriver.Chrome()

    driver.get('https://user.qzone.qq.com/{}/311'.format(business_qq))  # URL
    driver.implicitly_wait(10)  # 隱示等待,爲了等待充分加載好網址
    driver.find_element_by_id('login_div')
    driver.switch_to.frame('login_frame')  # 切到輸入帳號密碼的frame
    driver.find_element_by_id('switcher_plogin').click()  ##點擊‘帳號密碼登陸’
    driver.find_element_by_id('u').clear()  ##清空帳號欄
    driver.find_element_by_id('u').send_keys(login_qq)  # 輸入帳號
    driver.find_element_by_id('p').clear()  # 清空密碼欄
    driver.find_element_by_id('p').send_keys(password)  # 輸入密碼
    driver.find_element_by_id('login_button').click()  # 點擊‘登陸’
    driver.switch_to.default_content()

    driver.implicitly_wait(10)
    time.sleep(5)

    try:
        driver.find_element_by_id('QM_OwnerInfo_Icon')
        return driver
    except:
        print('不能訪問' + business_qq)
        return None

說說

登陸 QQ 後默認的頁面就在說說的界面,顯示一頁的說說是滾動加載的,必需要屢次下拉滾動條後才能獲取到該頁全部的說說,而後用 BeautifulSoup 模塊構建對象解析頁面,下圖是放說說的 iframeapp

def get_shuoshuo(driver):
    
    page = 1
    while True:
        # 下拉滾動條
        for j in range(15):
            driver.execute_script("window.scrollBy(0,5000)")
            time.sleep(2)

        # 切換 frame
        driver.switch_to.frame('app_canvas_frame')
        # 構建 BeautifulSoup 對象
        bs = BeautifulSoup(driver.page_source.encode('GBK''ignore').decode('gbk'))
        # 找到頁面上的全部說說
        pres = bs.find_all('pre', class_='content')

        for pre in pres:
            shuoshuo = pre.text
            tx = pre.parent.parent.find('a', class_="c_tx c_tx3 goDetail")['title']
            print(tx + ":" + shuoshuo)

        # 頁數判斷
        page = page + 1
        maxPage = bs.find('a', title='末頁').text

        if int(maxPage) < page:
            break

        driver.find_element_by_link_text(u'下一頁').click()
        # 回到主文檔
        driver.switch_to.default_content()
        # 等待頁面加載
        time.sleep(3)

相冊

下載相冊裏面的照片須要 selenium 模塊模擬鼠標一步步點擊頁面,先點擊上方的相冊按鈕,進去就是多個相冊的列表,下圖是單個相冊的超連接編輯器

在單個相冊中點擊照片,界面以下圖
flex

def get_photo(driver):
    
    # 照片下載路徑
    photo_path = "C:/Users/xxx/Desktop/photo/{}/{}.jpg"
    
    # 相冊索引
    photoIndex = 1

    while True:
        # 回到主文檔
        driver.switch_to.default_content()
        # driver.switch_to.parent_frame()
        # 點擊頭部的相冊按鈕
        driver.find_element_by_xpath('//*[@id="menuContainer"]/div/ul/li[3]/a').click()
        #等待加載
        driver.implicitly_wait(10)
        time.sleep(3)
        # 切換 frame
        driver.switch_to.frame('app_canvas_frame')
        # 各個相冊的超連接
        a = driver.find_elements_by_class_name('album-cover')
        # 單個相冊
        a[photoIndex].click()

        driver.implicitly_wait(10)
        time.sleep(3)
        # 相冊的第一張圖
        p = driver.find_elements_by_class_name('item-cover')[0]
        p.click()
        time.sleep(3)

        # 相冊大圖在父frame,切換到父frame
        driver.switch_to.parent_frame()
        # 循環相冊中的照片
        while True:
            # 照片url地址和名稱
            img = driver.find_element_by_id('js-img-disp')
            src = img.get_attribute('src').replace('&t=5''')
            name = driver.find_element_by_id("js-photo-name").text

            # 下載
            urlretrieve(src, photo_path.format(qq, name))

            # 取下面的 當前照片張數/總照片數量
            counts = driver.find_element_by_xpath('//*[@id="js-ctn-infoBar"]/div/div[1]/span').text

            counts = counts.split('/')
            # 最後一張的時候退出照片瀏覽
            if int(counts[0]) == int(counts[1]):
                # 右上角的 X 按鈕
                driver.find_element_by_xpath('//*[@id="js-viewer-main"]/div[1]/a').click()
                break
            # 點擊 下一張,網頁加載慢,因此10次加載
            for i in (110):
                if driver.find_element_by_id('js-btn-nextPhoto'):
                    n = driver.find_element_by_id('js-btn-nextPhoto')
                    ActionChains(driver).click(n).perform()
                    break
                else:
                    time.sleep(5)

        # 相冊數量比較,是否下載了所有的相冊
        photoIndex = photoIndex + 1
        if len(a) <= photoIndex:
            break

示例結果

總結

你們在看十幾年前的說說和照片是否是感受滿滿的黑歷史快要溢出屏幕了。時光荏苒、歲月如梭,願一切安好。


本文分享自微信公衆號 - 早起Python(zaoqi-python)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索