32.使用selenium爬取知乎璧坟,并實(shí)現(xiàn)多頁(yè)保存為一個(gè)PDF文件

1.動(dòng)機(jī)

對(duì)于知乎的一些高知大V既穆,他們的回答總是那么具有說服力,通過閱讀他們的回答雀鹃,了解他們對(duì)熱點(diǎn)事件的分析方式幻工,通過現(xiàn)象看本質(zhì),一不至于被帶節(jié)奏黎茎,二增加自己的知識(shí)面囊颅。多讀多看,大有裨益傅瞻。那如果在網(wǎng)絡(luò)信號(hào)不太好或不舍得太多流量的情況下(窮)踢代,能夠翻看他們的回答就太好了。
本篇介紹一下如何把”惡喵的奶爸“知乎回答頁(yè)全部下載下來(lái)并保存為一個(gè)PDF俭正。

1.1.分析

實(shí)現(xiàn)方式一奸鬓,獲取全部HTML源代碼,將多個(gè)HTML文件合成一個(gè)HTML文件掸读,將最后合成的這個(gè)文件保存為PDF串远。
實(shí)現(xiàn)方式二宏多,將單個(gè)HTML文件保存為PDF,再將多個(gè)PDF合成一個(gè)澡罚。
經(jīng)分析伸但,后者更容易實(shí)現(xiàn)。
在正式爬之前留搔,多做一些本地的測(cè)試更胖,在本地能夠行得通,再去騷擾目標(biāo)網(wǎng)站隔显。這樣做的目的却妨,一是不讓網(wǎng)站運(yùn)營(yíng)者惡心;二是節(jié)約自己的時(shí)間和精力括眠,因?yàn)榇笮途W(wǎng)站大多有自己的反爬措施彪标,頻繁騷擾兩三次,ip就被封了掷豺,那還要考慮換ip等一系列問題捞烟。

2.將本地HTML保存為PDF文件

先用selenium訪問以下目標(biāo)網(wǎng)站,將源代碼保存到本地HTML当船,然后用本地的HTML做測(cè)試题画。

# -*- coding: utf-8 -*-
# @AuThor  : frank_lee
import pdfkit
htmlfile = open("zhihu_answer.html", 'r', encoding='utf-8')
confg = pdfkit.configuration(wkhtmltopdf=r'D:\htmlpdf\wkhtmltopdf\bin\wkhtmltopdf.exe')
pdfkit.from_url(htmlfile, 'zhihu.pdf', configuration=confg)
2.1.上面代碼能夠正常執(zhí)行的先決條件--安裝wkhtmltopdf、pdfkit
2.1.1.先安裝wkhtmltopdf德频,這個(gè)工具的下載網(wǎng)站是:https://wkhtmltopdf.org/downloads.html

根據(jù)自己的操作系統(tǒng)下載對(duì)應(yīng)的版本即可苍息。安裝完成后可以將其加入到環(huán)境變量中,也可以不加入抱婉,但每次使用時(shí)需要調(diào)用wkhtmltopdf.exe的絕對(duì)路徑档叔。

2.2.2.安裝pdfkit模塊
pip install pdfkit

3.將一個(gè)本地HTML文件保存為多個(gè)PDF文件

import pdfkit
import time
i = 0
while i < 4:
    # pdfname = "zhihu{}".format(i)+".pdf"
    htmlfile = open("zhihu_answer.html", 'r', encoding='utf-8')
    confg = pdfkit.configuration(wkhtmltopdf=r'D:\htmlpdf\wkhtmltopdf\bin\wkhtmltopdf.exe')
    pdfkit.from_url(htmlfile, "zhihu{}".format(i)+".pdf", configuration=confg)
    i += 1
    time.sleep(10)

while循環(huán)和for循環(huán)都可以實(shí)現(xiàn),但是如果這樣寫蒸绩,只會(huì)保存為一個(gè)完整的PDF文件衙四,剩下的都是空白PDF:

# -*- coding: utf-8 -*-
# @AuThor  : frank_lee
import pdfkit
import time
htmlfile = open("zhihu_answer.html", 'r', encoding='utf-8')
confg = pdfkit.configuration(wkhtmltopdf=r'D:\htmlpdf\wkhtmltopdf\bin\wkhtmltopdf.exe')
i = 0
while i < 4:
    # pdfname = "zhihu{}".format(i)+".pdf"
    pdfkit.from_url(htmlfile, "zhihu{}".format(i)+".pdf", configuration=confg)
    i += 1
    time.sleep(10)

所以要注意代碼的執(zhí)行順序。

4.將多個(gè)PDF文件合成一個(gè)PDF文件

# -*- coding: utf-8 -*-
# @AuThor  : frank_lee
import os, PyPDF2

# 找出所有的pdf文件,并將文件名保存至列表患亿。
filelist = []
for filename in os.listdir('./dir-with-pdfs'):
    if filename.endswith('.pdf'):
        filelist.append(filename)

# 創(chuàng)建一個(gè)新的pdf
newPdfFile = PyPDF2.PdfFileWriter()

# 循環(huán)打開每一個(gè)pdf文件传蹈,將內(nèi)容添加至新的pdf
for filename in filelist:
    pdfFile = open('./dir-with-pdfs/' + filename, 'rb')
    pdfObj = PyPDF2.PdfFileReader(pdfFile)
    # 獲取頁(yè)數(shù)
    pageNum = pdfObj.numPages

    for num in range(0, pageNum):
        pageContent = pdfObj.getPage(num)
        newPdfFile.addPage(pageContent)
        
newFile = open('zhihu_emiao.pdf', 'wb')
newPdfFile.write(newFile)
newFile.close()

5.動(dòng)真格的

在上一篇的基礎(chǔ)上,添加登錄功能步藕,因?yàn)橹跤行┯行┐骎的回答頁(yè)面不登錄就能訪問惦界,有些則不行。



5.1.模擬登錄

如果能夠避開驗(yàn)證碼實(shí)現(xiàn)登錄咙冗,豈不是很輕松沾歪,哎,想一下還蠻激動(dòng)雾消,試一下使用selenium結(jié)合瀏覽器開發(fā)者模式還真可以灾搏,關(guān)鍵代碼如下:

options = webdriver.ChromeOptions()
options.add_experimental_option(
    'excludeSwitches', ['enable-automation'])
self.browser = webdriver.Chrome(options=options)

在該模式下挫望,可以完美避開驗(yàn)證碼,直接輸入用戶名和密碼就能實(shí)現(xiàn)登錄狂窑。如果用戶名和密碼還要手動(dòng)輸入就太low了媳板。此時(shí),selenium可能會(huì)說泉哈,兄弟蛉幸,顯示等待了解一下。這里的代碼帶有“self”丛晦,因?yàn)橥暾a是包含一個(gè)zhihu_infos類奕纫。如果直接定義一個(gè)函數(shù),或者隨心所欲采呐,不定義函數(shù)若锁,想到哪兒是哪兒搁骑,可以將其刪掉斧吐。下面的代碼用到了顯示等待,顯示等待是針對(duì)于某個(gè)特定的元素設(shè)置的等待時(shí)間仲器,如果在規(guī)定的時(shí)間范圍內(nèi)煤率,沒有找到元素,則會(huì)拋出異常乏冀,如果在規(guī)定的時(shí)間內(nèi)找到了元素蝶糯,則直接執(zhí)行,即找到元素就執(zhí)行相關(guān)操作辆沦。WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.XX, 'XX')))

既然有until昼捍,自然也有until_not

WebDriverWait()一般由until()或 until_not()方法配合使用
until(method, message=' '):調(diào)用該方法提供的驅(qū)動(dòng)程序作為一個(gè)參數(shù),直到返回值為True
until_not(method, message=' '):調(diào)用該方法提供的驅(qū)動(dòng)程序作為一個(gè)參數(shù)肢扯,直到返回值為False

# 等待 登錄選項(xiàng) 出現(xiàn)妒茬,并點(diǎn)擊
password_login = self.wait.until(EC.presence_of_element_located(
    (By.CSS_SELECTOR, '.SignContainer-switch > span:nth-child(1)')))
password_login.click()
time.sleep(3)
# 等待 賬號(hào) 出現(xiàn)
zhihu_user = self.wait.until(EC.presence_of_element_located(
    (By.CSS_SELECTOR, '.SignFlow-accountInput > input:nth-child(1)')))
zhihu_user.send_keys(zhihu_username)

# 等待 密碼 出現(xiàn)
zhihu_pwd = self.wait.until(
    EC.presence_of_element_located(
        (By.CSS_SELECTOR,
         '.SignFlow-password > div:nth-child(1) > div:nth-child(1) > input:nth-child(1)')))
zhihu_pwd.send_keys(zhihu_password)

# 等待 登錄按鈕 出現(xiàn)
submit = self.wait.until(
    EC.presence_of_element_located(
        (By.CSS_SELECTOR, 'button.Button:nth-child(5)')))
submit.click()
time.sleep(10)
5.2.實(shí)現(xiàn)點(diǎn)擊

和上篇一樣,不點(diǎn)擊蔚晨,是無(wú)法查看完整回答的乍钻,不同點(diǎn)是這個(gè)回答頁(yè)面共有20個(gè)回答,上篇是10個(gè)铭腕。



實(shí)現(xiàn)點(diǎn)擊并返回網(wǎng)頁(yè)源代碼:

def get_pagesource(self, url):
    self.browser.get(url=url)
    self.browser.maximize_window()
    time.sleep(5)

    # 執(zhí)行點(diǎn)擊動(dòng)作
    for j in range(1, 21):
        content_click = '#Profile-answers > div:nth-child(2) > div:nth-child(' + str(
            j) + ') > div > div.RichContent.is-collapsed > div.RichContent-inner'
        try:
            complete_content = self.wait.until(
                EC.presence_of_element_located(
                    (By.CSS_SELECTOR, content_click)))
            complete_content.click()
            time.sleep(1)
        except BaseException:
            pass
    pagedata = self.browser.page_source
    return pagedata
5.3.將網(wǎng)頁(yè)源代碼以.html的格式保存到本地
def save_to_html(self, base_file_name, pagedata):
    filename = base_file_name + ".html"
    with open(self.html_path + filename, "wb") as f:
        f.write(pagedata.encode("utf-8", "ignore"))
        f.close()
    return filename
5.4.將已保存的HTML保存為PDF格式
def html_to_pdf(self, base_file_name, htmlname):
    pdfname = base_file_name + ".pdf"
    htmlfile = open(self.html_path+htmlname, 'r', encoding='utf-8')
    confg = pdfkit.configuration(
        wkhtmltopdf=r'D:\htmlpdf\wkhtmltopdf\bin\wkhtmltopdf.exe')
    pdfkit.from_url(htmlfile, self.pdf_path + pdfname, configuration=confg)
5.5.將多個(gè)PDF文件保存為一個(gè)
def Many_to_one(self):
    # 找出所有的pdf文件,并將文件名保存至列表银择。
    filelist = []
    for filename in os.listdir('./pdf_file'):
        if filename.endswith('.pdf'):
            filelist.append(filename)

    # 創(chuàng)建一個(gè)新的pdf
    newPdfFile = PyPDF2.PdfFileWriter()

    # 循環(huán)打開每一個(gè)pdf文件,將內(nèi)容添加至新的pdf
    for filename in filelist:
        pdfFile = open('./pdf_file/' + filename, 'rb')
        pdfObj = PyPDF2.PdfFileReader(pdfFile)
        # 獲取頁(yè)數(shù)
        pageNum = pdfObj.numPages

        for num in range(1, pageNum):
            pageContent = pdfObj.getPage(num)
            newPdfFile.addPage(pageContent)

    newFile = open(self.pdf_path+'惡喵的奶爸.pdf', 'wb')
    newPdfFile.write(newFile)
    newFile.close()

6.完整代碼

完整代碼實(shí)現(xiàn)了將多頁(yè)回答HTML格式保存為一個(gè)文件夾累舷,PDF格式的保存到另外一個(gè)文件夾浩考,最后將多個(gè)PDF文件合成一個(gè)PDF文件。由于代碼行數(shù)較多被盈,貼在這里不太美觀析孽,如有需要請(qǐng)查看github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末析蝴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绿淋,更是在濱河造成了極大的恐慌闷畸,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吞滞,死亡現(xiàn)場(chǎng)離奇詭異佑菩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)裁赠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門殿漠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人佩捞,你說我怎么就攤上這事绞幌。” “怎么了一忱?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵莲蜘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我帘营,道長(zhǎng)票渠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任芬迄,我火速辦了婚禮问顷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘禀梳。我一直安慰自己杜窄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布算途。 她就那樣靜靜地躺著塞耕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪郊艘。 梳的紋絲不亂的頭發(fā)上荷科,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音纱注,去河邊找鬼畏浆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛狞贱,可吹牛的內(nèi)容都是我干的刻获。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼瞎嬉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蝎毡!你這毒婦竟也來(lái)了厚柳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沐兵,失蹤者是張志新(化名)和其女友劉穎别垮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扎谎,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碳想,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了毁靶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胧奔。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖预吆,靈堂內(nèi)的尸體忽然破棺而出龙填,到底是詐尸還是另有隱情,我是刑警寧澤拐叉,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布岩遗,位于F島的核電站,受9級(jí)特大地震影響巷嚣,放射性物質(zhì)發(fā)生泄漏喘先。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一廷粒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧红且,春花似錦坝茎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至壁酬,卻和暖如春次酌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舆乔。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工岳服, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人希俩。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓吊宋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親颜武。 傳聞我的和親對(duì)象是個(gè)殘疾皇子璃搜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)拖吼、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,121評(píng)論 4 61
  • 一天過去了这吻,平平淡淡吊档,可真是休息了,沒學(xué)習(xí)唾糯,沒工作籍铁,上午收拾家,下午打麻將趾断,吃了飯斗地主看視頻拒名。確實(shí)沒什么感受。
    阿燕_7526閱讀 107評(píng)論 0 2
  • 進(jìn)門第一句絕對(duì)是喊媽芋酌,出門最后一句也一定是媽增显,跟老爸說話只會(huì)問一句“爸,我媽呢”脐帝,在我心里地位這么崇高的媽同云,她最愛...
    懶人菜菜閱讀 781評(píng)論 0 0