1. 程式人生 > >【每週一爬】爬取盜版小說網的小說

【每週一爬】爬取盜版小說網的小說

【本帖持續更新,直到能將一本書全部爬到一個.txt檔案中】
一:準備工作
        爬取的網站地址:http://b.faloo.com/tag/6293.html         爬取的書:與校花同居的大盜  連結:https://b.faloo.com/f/163306.html 找到存放文字的html標籤         先開啟小說的第一章,我們可以採用審查元素的方式來找到這個網頁的原始碼。一般我們可以通過右擊-審查元素  來檢視網頁的原始碼,但這個網頁跟我之前遇到的不同,右鍵出現的是此網頁的功能。因此可以選擇按F12來找到網頁的原始碼         但這裡我選擇用python中requests庫的get方法來檢視:         
import requests
from bs4 import BeautifulSoup
url = "https://b.faloo.com/p/163306/1.html"
r = requests.get(url)
print(r.text)
結果如下: 在這裡我們就可以明確地看到文字被存放在一個名為div的標籤裡,它的id屬性為content,如此我們便鎖定了要爬取的標籤。

二:爬取單個章節

我們首先爬取第一章的內容:
import requests
from bs4 import BeautifulSoup
url = "https://b.faloo.com/p/163306/1.html"
try:
    r = requests.get(url)   #解析網頁
    r.raise_for_status      #檢查網頁能否正常訪問,不能則報錯
    html = r.text           #獲取網頁html
    soup = BeautifulSoup(html,'html.parser')   #用html.parser解析器解析html
    div = soup.find_all("div",id = "content")[0]  #查詢名為div,id屬性為content的標籤,由於返回的是一個列表,因此取列表裡的值
    print(div)
except:
    print("出錯了")
程式碼寫好後,我們看下結果:
可以看到,我們已經獲取了文字內容,但是裡面並沒有分段而且存在<br/>等這類的標籤。此時如果你用type()函式檢查下div的型別,可以發現它是bs4裡定義的Tag型別。 事實上,我們需要的是字串型別,當我們將其轉化為字串時,這些標籤就會自己消失了。我們需要解決的,是分段問題。 我們可以看到,爬取的內容的每一段開頭有幾個字元的空格,我們可以將這些空格轉化為換行符來達到換行的目的,因此我們選擇replace方法。 程式碼如下:
import requests
from bs4 import BeautifulSoup
url = "https://b.faloo.com/p/163306/1.html"
try:
    r = requests.get(url)   #解析網頁
    r.raise_for_status      #檢查網頁能否正常訪問,不能則報錯
    html = r.text           #獲取網頁html
    soup = BeautifulSoup(html,'html.parser')   #用html.parser解析器解析html
    div = soup.find_all("div",id = "content")[0]
    div = div.text.replace('  ','\n\n'+'  ')
    print(div)
except:
    print("出錯了")

最終執行結果如下: 到此,我們就完成了對單個章節的爬取。接下來,我將進行對整本書的爬取並生成一個txt檔案來儲存這些文字。


<hr color = "red"/>

2018.4.3號更新如下:

三:將整本書爬下並將文字存入一個txt文件中
       在開始這部分之前,我們首先要知道如何通過程式碼在系統盤指定位置生成一個txt。在這裡我們使用open()函式。但是,有可能我們所選擇的系統盤位置已經有了一個相同檔名的資料夾或是txt檔案,如何來避免我們爬取的內容將原有檔案的內容給覆蓋或破壞呢?         我們選擇python的os模組。         編寫程式碼如下:
import os
if not os.path.exists("D://1.txt"):
    f = open('D://1.txt','w')
    f.write('這是寫入的內容')
    f.close()
else:
    print("已存在相同檔名")

os.path.exists()函式可以判斷指定目錄和名稱的資料夾或是檔案是否已經存在,如果存在,返回True,不存在返回False

上述程式碼第一次執行結果如下:

第二次時由於已經存在同名資料夾,所以結果如下: 好,我們現在已經可以將內容寫入文字,接下來進行對整本書的爬取。 首先,我們要先分析這本書在網站上的結構。 對包含章節目錄的網頁進行審查元素:


我們可以看到,章節超連結指向一個<a>標籤,在<a>標籤中由一個屬性href。在html協議中,href存放的是一個url。

我們開啟第一章,看一下url。


我們發現,href前面加上一個“http:”正好就是我們想要章節的url!

那麼我們就得到了獲取章節連結的方法——通過獲取<a>標籤中的href



結構分析好後,我們就要著手盡心程式碼的編寫了。
我們先理清思路。 1.我們需要一個函式來獲取所有的章節連結,並返回一個儲存所有url連結的列表 def getUrl():     return url_list

2.我們需要一個函式來迴圈調取url_list中的連結,並解析網頁html,將所需要的文字爬取下來存到一個txt中間中 def getContent():
3.最後我們需要調取函式


好了,如上就是我們對爬取一本書的思路,三個主要的程式碼框架都已經列出來了,我們最後要做的就是把程式碼補齊:
import requests
import os
from bs4 import BeautifulSoup

main_url = "https://b.faloo.com/f/163306.html"     #指定帶有章節連結的url
chapter_names=[]   #用於存放章節名
url_list = []    #用於存放章節連結
path = "D://與同居的大盜.txt"    #指定一個根目錄存放txt檔案
num = 0

'''定義一個獲取章節連結的函式
這個函式的作用是從main_url中提取出所有章節的連結
並且放到url_list中去,最後返回url_list
以供下一個函式使用
'''

def getUrl(url):
    try:
        r = requests.get(url)
        r.raise_for_status
    except:
        print("無法獲取主網頁,請確認主網頁")
    html = r.text
    soup = BeautifulSoup(html,'html.parser')
    td = soup.find_all('td',class_ = "td_0")
    for each in td:
        url_  = 'http:' + each.a.attrs['href']
        url_list.append(url_)
    
    return url_list


'''定義一個獲取章節文字的函式
這個函式的作用是將每一章的文字內容提取出來並放到txt檔案中去
'''
def getContent(list,path): 
    if not os.path.exists(path):
        with open(path,'a',encoding = 'utf-8') as f:         #這裡將open()放在for迴圈之外是為了提高效率,避免重複地開啟檔案。並將編碼方法改為utf-8,使其能識別特殊字元。如果不加這個encoding會報編碼錯誤,因為windows系統預設的gbk編碼方式識別不了文中的特殊字元。
            for url in list:
                try:
                    r1 = requests.get(url)   #解析網頁    #檢查網頁能否正常訪問,不能則報錯
                    r1.raise_for_status
                except:
                    print("此"+item+"章節連結無法開啟,請確認網頁")
                html1 = r1.text           #獲取網頁html
                soup1 = BeautifulSoup(html1,'html.parser')   #用html.parser解析器解析html
                div = soup1.find_all("div",id = "content")[0]
                content = div.text.replace('  ','\n\n'+'  ')
                f.write(content)
        f.close
    else:
        print('"D://"位置已存在"與校花同居的大盜.txt",請確認')

getContent(getUrl(main_url),path)#呼叫函式

好了,至此,我們就完成了爬取一本書的工作。

但是,我們的程式碼還有很多要優化的地方,比如:

· 沒有章節名

· 沒有程式執行進度的提示。我們這次爬取的書比較小,如果是一本內容特別多地小說,python爬取所需要的時間會大大增加,沒有進度提示的話會影響到使用者的使用體驗


那麼,這些就是我們下一次要來完善的地方。

【未完待續】


四:優化