1. 程式人生 > 實用技巧 >用 Python 爬取 QQ 空間說說和相簿

用 Python 爬取 QQ 空間說說和相簿

QQ 空間在 2005 年被騰訊開發,已經經歷了 15 個年頭,在還沒有微信的年代,看網友發表的心情、心事、照片大多都在 QQ 空間的裡。它承載了80、90 後的大量青春,下面我們一起用 selenium 模組匯出說說和相簿回憶青春吧

很多人學習python,不知道從何學起。
很多人學習python,掌握了基本語法過後,不知道在哪裡尋找案例上手。
很多已經做案例的人,卻不知道如何去學習更加高深的知識。
那麼針對這三類人,我給大家提供一個好的學習平臺,免費領取視訊教程,電子書籍,以及課程的原始碼!
QQ群:101677771

安裝 selenium

selenium 是一個在瀏覽器中執行,以模擬使用者操作瀏覽器的方式獲取網頁原始碼,使用 pip 安裝 selenium 模組

pip install selenium

檢視 chrome 瀏覽器版本並下載 對應的 chrome 瀏覽器驅動

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 模組構建物件解析頁面,下圖是放說說的 iframe

def get_shuoshuo(driver):
    
    page = 1
    while True:
        # 下拉滾動條
        for j in range(1, 5):
            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 模組模擬滑鼠一步步點選頁面,先點選上方的相簿按鈕,進去就是多個相簿的列表,下圖是單個相簿的超連結

在單個相簿中點選照片,介面如下圖

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 (1, 10):
                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

示例結果

總結

大家在看十幾年前的說說和照片是不是感覺滿滿的黑歷史快要溢位螢幕了。時光荏苒、歲月如梭,願一切安好。