記錄一次爬取空間表白牆的圖片
有一說一,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的數據包,但是網頁內容命名有圖片啊,於是直接分析網頁數據
看看圖片的鏈接。找到了這個 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能發出一樣的請求就好了。
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
結果:
上面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,然后運行不了啥的。
運行結果:
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,想提取數據都要費好大勁了。