python之爬取qq空間找說說


記錄一次爬取空間表白牆的圖片

有一說一,python是真的簡單,網上的資源也很全。本人作為一個連循環都寫不明白的小白,也能用python做到想到的事。

爬取圖片,只是為了把圖片轉換為文字,然后找一條特定的說說而已。

首先是登錄

此段代碼參考至博客

需要自行設置phantomjs.exe的路徑。還有就是現在貌似加了滑塊驗證,或者是因為訪問多了才有的限制,所以並沒有用這個登錄。

#!/usr/bin/python
# -*- coding:utf-8 -*-

from selenium import webdriver
import time

# 使用selenium
driver = webdriver.PhantomJS(executable_path="E:\\js\\bin\\phantomjs.exe")
driver.maximize_window()


# 登錄QQ空間
def get_shuoshuo(qq):
    driver.get('http://user.qzone.qq.com/{}/311'.format(qq))  # 說說位於網頁的/311界面下
    time.sleep(5)
    try:
        driver.find_element_by_id('login_div')
        a = True
    except:
        a = False
    if a == True:
        driver.switch_to.frame('login_frame')
        driver.find_element_by_id('switcher_plogin').click()
        driver.find_element_by_id('u').clear()
        # 選擇用戶名框
        driver.find_element_by_id('u').send_keys('你的qq號')
        driver.find_element_by_id('p').clear()
        driver.find_element_by_id('p').send_keys('你的qq密碼')
        driver.find_element_by_id('login_button').click()
        time.sleep(3)
    driver.implicitly_wait(3)
    try:
        driver.find_element_by_id('QM_OwnerInfo_Icon')
        b = True
    except:
        b = False
        print("shibai")
    if b == True:
        driver.switch_to.frame('app_canvas_frame')
        content = driver.find_elements_by_css_selector('.content')
        stime = driver.find_elements_by_css_selector('.c_tx.c_tx3.goDetail')  # 可根據字段需要匹配多個元素
        for con, sti in zip(content, stime):
            data = {
                'time': sti.text,
                'shuos': con.text
            }
            print(data)

    cookie = driver.get_cookies()
    cookie_dict = []
    for c in cookie:
        ck = "{0}={1};".format(c['name'], c['value'])
        cookie_dict.append(ck)
    i = ''
    for c in cookie_dict:
        i += c
    print('Cookies:', i)
    print("==========完成================")

    driver.close()
    driver.quit()


if __name__ == '__main__':
    get_shuoshuo("別人的qq號")  # 需要爬取的qq

掃碼登錄

此段代碼參考自知乎

親測掃碼登錄可行,可以獲得cookie。雖然對其中一些數據不太了解。

#!/usr/bin/python
# -*- coding:utf-8 -*-

#定義登錄函數
import re
from time import sleep

from PIL import Image
from selenium import webdriver


def QR_login():
    def getGTK(cookie):
        """ 根據cookie得到GTK """
        hashes = 5381
        for letter in cookie['p_skey']:
            hashes += (hashes << 5) + ord(letter)
        return hashes & 0x7fffffff
    browser=webdriver.PhantomJS(executable_path="E:\\js\\bin\\phantomjs.exe")#這里要輸入你的phantomjs所在的路徑
    url="https://qzone.qq.com/"#QQ登錄網址
    browser.get(url)
    browser.maximize_window()#全屏
    sleep(3)#等三秒
    browser.get_screenshot_as_file('QR.png')#截屏並保存圖片
    im = Image.open('QR.png')#打開圖片
    im.show()#用手機掃二維碼登錄qq空間
    sleep(15)#等二十秒,可根據自己的網速和性能修改
    print(browser.title)#打印網頁標題
    cookie = {}#初始化cookie字典
    for elem in browser.get_cookies():#取cookies
        cookie[elem['name']] = elem['value']
    print('Get the cookie of QQlogin successfully!(共%d個鍵值對)' % (len(cookie)))
    print(cookie)
    html = browser.page_source#保存網頁源碼
    g_qzonetoken=re.search(r'window\.g_qzonetoken = \(function\(\)\{ try\{return (.*?);\} catch\(e\)',html)#從網頁源碼中提取g_qzonetoken
    gtk=getGTK(cookie)#通過getGTK函數計算gtk
    browser.quit()
    print("gtk ", gtk)
    print(g_qzonetoken)
    print("====")
    print(g_qzonetoken.__dict__)
    return (cookie,gtk,g_qzonetoken.group(1))
if __name__=="__main__":
    QR_login()

不過對本人而言,並不需要這么麻煩。

python實現帶cookie的get請求就可以了。所以,我選擇用fiddler。

操作:

1.打開fiddler,打開空間,使用fiddler觀看數據包。

這個看得我有點懵,因為怎么加載也不會有jpg的數據包,但是網頁內容命名有圖片啊,於是直接分析網頁數據
image

看看圖片的鏈接。找到了這個 phototj.photo.store.qq.com/psc 這個就是圖片的請求了。

於是對網頁切換頁數,觀察數據包,確定加載網頁內容的鏈接。

得到了這個

https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6

這個實際是get請求,末尾帶很多參數,可以通過fiddler查看。

保存這條鏈接的響應,打開txt,果然能搜到很多phototj.photo.store.qq.com/psc

那就是確認無疑了。

2.不停切換網頁頁數,看看加載不同頁,請求的差別在哪里。

參數很多,但是經過測試驗證,只需要pos和num屬性。其中num不變為20,pos為每次加載的起點。

比如第一頁,pos=0,第二頁,pos=20,第三頁,pos=40.因為每一頁固定20條說說。

3.利用fiddler的composer功能,把上面鏈接的請求視圖中的所有內容復制到里面,

復制到Raw里面,點擊Execute,看看有什么響應。主要看看是不是和網頁點擊加載出來的一樣。

還有就是改變pos的數值,看看加載內容的變化。

測試完畢,一切都好,那就沒問題了。接下來只要python能發出一樣的請求就好了。
image

4.使用python發出get請求並處理數據

代碼:

Get獲取數據內容

def getContent(pos):
    url = 'https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?pos=' + str(pos) + '&num=20' #作為博客,我刪減了其他get參數,用的時候,復制fiddler的get鏈接,然后修改成類似這樣就好了。
    header = {
        'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="99", "Microsoft Edge";v="99"',
        'sec-ch-ua-mobile': '?0',
        'Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.46',
        'sec-ch-ua-platform': '"Windows"',
        'Referer': '根據上面第3點里面的內容改',
        'Cookie': '你自己的cooke'
    }

    web = requests.get(url, headers=header)
    data = web.content
    soup = BeautifulSoup(data, "html.parser")  # 多種解析器,這里選這個就夠用了
    getPhotoUrl(soup.prettify())

處理數據(注意下面的代碼要放到上面的上面,這里只是按照處理的先后順序貼代碼)

filename = "url.txt"
filea = open(filename, "a", encoding='utf-8')
def getPhotoUrl(str):
    str = str.replace("_Callback(", ""); #需要做一些處理,才能轉換為json
    str = str.replace("}});", "}}") #作者作為小白,一直用str.replace沒反應,才想起str = str.replace
    # print(str)
    obj = json.loads(str)
    print(str)
    # for data in obj:
    #     print(obj[data])

    if obj['msglist'] == None:  #調試了半天,原來是沒有數據了。
        print("none")
    else:
        for data1 in obj["msglist"]:
            if 'pic' in data1: #這都是坑,有的里面沒有圖片
                for data2 in data1["pic"]:
                    if 'smallurl' in data2: #這都是坑,有的里面沒有圖片
                        print(data2["smallurl"], file=filea)

運行代碼:

for i in range (60):#空間看着有150多頁,實際到59頁就沒有數據了
    print(i)
    getContent(i*20)#60

導入包

import requests
from lxml.html import fromstring
from bs4 import BeautifulSoup
import time
import json

結果:
image

上面json取數據怎么來的:

第3步的時候,利用fiddler查看響應,切換到json即可。一開始還傻傻的手動分割數據。

5.讀取url.txt,下載圖片到文件夾。

代碼:

def writeData(index,data):
    filename = './picture/' + str(index) + ".jpg"
    file = open(filename,"wb")
    file.write(data)
    file.close()

file = open("url.txt","r")
url = file.readline()
index = 0
while url:
    url = url.replace("\n","")
    obj = requests.get(url=url)
    writeData(index,obj.content)
    url = file.readline()
    index = index + 1
print("finish")

需要注意的事,本人只是想做這件事而已,並不在意什么規范。所以都是一個python文件,一個函數,做一件事的。不要全部代碼復制到一個tet,然后運行不了啥的。

運行結果:
image

6.識別圖片,保存識別內容到txt

代碼:

#!/usr/bin/python
# -*- coding:utf-8 -*-

import pytesseract
from PIL import Image
# 讀取圖片
# im = Image.open('3.jpg')
# 識別文字
# string = pytesseract.image_to_string(im,lang='chi_sim')
# print(string)


index = 500 #500條500條的識別,找到我要的說說就不弄了。
for i in range(500):
    filename = './picture/' + str(i+index) + ".jpg"
    im = Image.open(filename)
    string = pytesseract.image_to_string(im, lang='chi_sim')
    print(i+index)
    # print("index = ",str(i)," ",string,file = filea)
    stra = "index = " + str(i+index) + " " + string
    filea = open("data.txt", 'a', encoding='utf-8')#注意要加encoding=‘utf-8' 因為默認是ansi編碼
    filea.write(stra)

7.總結:

python真是好用啊,看着控制台輸出的排列整齊的數據,感覺好像很厲害。

主要是這個發送請求很方便。

之前在爬取小說的時候,一開始是用的Qt里面的post,結果請求多了,線程太多就崩了。但是python不會,請求9000多個鏈接,也不會怎么樣。

還有就是fiddler也是網頁分析的利器啊,沒有fiddler,想提取數據都要費好大勁了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM