1. 程式人生 > >Python爬取句子迷-莎士比亞語錄

Python爬取句子迷-莎士比亞語錄

爬取句子迷——莎士比亞語錄(約2290個句子,229個分頁)

這個練手的過程,在我不使用IP代理的情況下,我使用的IP慘遭封禁數次,好在隔幾個小時就會被解封,但我卻好比黏人的鼻涕蟲一般,句子不給我,我就不走了,哼哼。

工具使用的是 Python3.7 + requests + BeautifulSoup4 + 執行緒

首先句子迷是具有一定反爬程式的,具體是怎樣的就不清楚,但是文字還是整整齊齊擺放著,這個還是很友好的,前端頁面分析完就開始我數次爬取嘗試。

第一次嘗試爬取資料

規規矩矩的在邊緣試探,結果很不理想,字都存放在TXT檔案中(171KB),根本爬不完就被封IP了,返回給你一個403的狀態碼,很過分的哦,就幾個字也這麼小氣不給我,還反爬,既然被封了,我就只能睡覺了唄!

第二、三次嘗試

我一早起來,發現句子迷這個網站又能訪問了,開心的很吶,還以為被封了就不能再訪問了呢,然後就開始了我第二次嘗試,這次我想著不能這麼明目張膽了,得猥瑣一點的,用時間換取完整且成功的結果。

當然這個方法就是利用sleep進行偽裝咯,因為一共229頁,我設定每爬取5頁就隨機休息5以內秒哦,time.sleep(random.randint(1,5)) ,這樣我不過分吧!可是呢,結果又讓我失望了一波,IP再一次被封,當然我也不會放棄,解封之時就是我再戰之時,當然這樣設定一下還是有收穫的,爬取到相當於上一次兩倍的資料量。第三次嘗試,我為了避免休眠數字隨機性被檢測到,我專門設定了小數加在後面,然而並沒有什麼用。

第四次嘗試

永不言棄的我在第四次不好意思的是又失敗了,但這一次我完全放下了身段,因為這次我打算睡眠1-5秒的同時只爬取一頁的資料,這個不過分吧,跟人手動點選的速度差不多了吧,想著多花點時間趕緊了結了吧。誰知我才離開電腦不久IP就被封了,得到的句子比起之前的反而更少了,而且封的同時 我發現請求這個頁面被封前我都休息了5秒,這就讓我懷疑 並不是訪問頻率過快,而是訪問週期過長? 然後我趕緊修改程式,開啟了我第三次嘗試,因為寬頻IP被封了,迫於需要更換IP,這接下來的嘗試則是使用的手機熱點...0.0,原本都沒想著能成功的。

第五次嘗試

這一次我想使用的是執行緒,通過html程式碼中pager-last

class下的a標籤獲取總頁數,然後建立對應數量的執行緒,同時爬取每一頁的句子並存儲在 對應頁數.txt 檔案中,每個txt檔案相當於10個句子。這一次我終於成功拿到我想要的所有資料,還蠻興奮咯,差點逼得我要使用代理了。

部分程式碼如下

#coding=utf-8
import requests
from requests import codes
import io
import bs4
import os
import random
import time
import threading
from bs4 import BeautifulSoup

webUrl = 'https://www.juzimi.com/'
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}

def downLoadPageExtra(url):
    try:
        realUrl = webUrl + '/writer/%E8%8E%8E%E5%A3%AB%E6%AF%94%E4%BA%9A'+"?page="+str(url)
        content = requests.get(realUrl,headers = headers)
        content.encoding = "UTF-8"
        if codes.ok == content.status_code:
            soup = BeautifulSoup(content.text,'html.parser')
            downLoadTxt = soup.findAll('a',class_='xlistju')
            f = open("juzimi"+ "/" + str(url) + ".txt", 'a', encoding='utf-8')
            for dlt in downLoadTxt:
                f.writelines((dlt.text)+"\r\n\r\n")
            print(str(url)+"OK")
            f.close()
        else:
            print("狀態碼出錯")
    except:
        print("getPageCodeError1")
def downLoadPage(url):
    try:
        content = requests.get(url,headers = headers)
        content.encoding = "UTF-8"
        if codes.ok == content.status_code:
            soup = BeautifulSoup(content.text,'html.parser')
            downLoadTxt = soup.findAll('a',class_='xlistju')
            #獲取標題建立檔案
            title = str(soup.title.string).strip('/').split('?')[0]
            #獲取頁數
            pageCounts = soup.find('li',class_='pager-last').find_all('a')[0].text
            f=open("juzimi"+"/"+ title + ".txt", 'a',encoding='utf-8')
            for dlt in downLoadTxt:
                f.writelines(str(dlt.text)+"\r\n\r\n")
            f.close()
            print("第一句完成")
            for num in range(1,int(pageCounts)):
                t = threading.Thread(target=downLoadPageExtra,args=(num,))
                t.start()
            print('爬取完成...')
    except requests.ConnectionError:
        print("getPageCodeError2")



if __name__ == '__main__':
    dirSave = 'juzimi/'
    if os.path.exists(dirSave) is False:
        os.makedirs(dirSave)
    downLoadPage(webUrl + '/writer/%E8%8E%8E%E5%A3%AB%E6%AF%94%E4%BA%9A')

程式碼具體如上,不保證百分百直接能執行,因為是從專案中複製過來並且做了部分修改,但是大致原理已說明,使用多執行緒,因為是IO密集型,所以多執行緒還是挺好使的,速度那是相當的快啊,幾十秒就通通搞定,當然我們如果需要將所有txt檔案合併成一個的話,我又寫了一個合併程式。

程式碼如下


import io
# 通過html頁面標題命名的txt檔案,並且儲存的第一頁的句子
mergeTxtName = '莎士比亞經典語錄_名言_名句賞析_句子迷.txt'
# 開始標記
start = 1
# 結束標記
end = 228
f = open(mergeTxtName,'a',encoding='utf-8')
for n in range(start,end + 1):
    g = open(str(n)+'.txt','r',encoding='utf-8')
    f.write(g.read())
    print(str(n)+"完成")
    g.close()
f.close()
print("ok")

此程式碼檔案應當放置在下載目錄中,否則請修改對應路徑,若並不是獲取莎士比亞的句子,還需要修改mergeTxtName字串,此程式碼不提供刪除已合併的txt檔案,若需要可自行增加...自寫程式時請注意檔案讀寫操作時的字型編碼問題...

總結

寫爬蟲當多多練手,基礎的熟練,再有針對的提高難度,征服更多網站,第一次嘗試使用部落格園的markdown風格,相比較有道雲筆記本的書寫,這裡不是很習慣,先試著一次,個人感覺效果好的話以後就用這種方式寫了,要是有一個實時預覽該有多好啊。

爬取了莎士比亞的句子後並不是滿足於技術的提升,說到底並沒有多少提升,總歸的來說還是屬於靜態介面,初心則是想閱覽一下這些有趣的句子,有一些話語寫的真的很好,併成為我的座右銘:

我荒廢了時間,時間便把我荒廢了。