既然我們之前已經講了BeautifulSoup的使用,那麼我們今天就來實戰下,用BeautifulSoup解析小說網站,做一個小說下載器;
首先,先分析一下網站:
- 我們的目標是一個叫全小說的網站:https://qxs.la/
我們可以看見右上角的位置有一個搜索框,我們可以將想要搜索的關鍵詞鍵入,然後搜索我們想要的內容,我們來分析下這個網站的結構; - 我們在搜索框輸入“唐家三少”,看看網頁會發生怎麼樣的變化:
網頁把站內所有唐三的小說都搜索出來了,最新的小說都有,看來這個網站還是更新挺勤的;回過頭來分析下頁面,沒有打開新的網頁,但是打開了一個新的頁面:我們發現變化的是在原網址後面加上了 "/s_***"
我們搜索另外一個,看看這個發現成不成立:
我們發現這個想法貌似是對的,搜索的內容頁面就是在原址的基礎上加上了 "/s_***" - 我們隨便點開一個,看看對應的頁面內容是怎麼樣的:
我們發現小說的所有章節都在這裏面了,我們來檢查一下源碼,看下網頁的結構是怎麼設計的:
發現所有的章節都在 <div class="chapters"> 標籤下面,但是客氣的是竟然有幾章湊數的章節,這個我們先不管,我們打開第一章,看看裏面的分佈; - 小說的內容已經有了,我們可以看見最下面有下一章,那麼我們是不是可以通過這個下一章鏈接進行翻頁,這樣就不用獲取所有頁面的網址了
好了,我們現在已經分析好了,接下來就是開始來寫代碼了,既然是小說下載器,那麼肯定要有一個界面是不是:
- 有一個輸入框,接收我們想要搜索的關鍵字
- 要有一個列表框,顯示我們搜索出來的結果
- 當我們選擇小說,單擊下載按鈕的時候,就開始下載這本小說,生成txt文檔
設計小說下載器界面:
from tkinter import *
window = Tk()
window.geometry('300x500')
window.title('小說下載器')
Label(window,text='請輸入你想搜索的內容:',font=('楷體',12)).place(x=10,y=10)
# 輸入框
key_word = Entry(window,font=('楷體',16),width=25)
key_word.place(x=10,y=35)
# 顯示列表
show = Listbox(window,width=25,height=15,font=('楷體',16))
show.place(x=10,y=80)
# 搜索按鈕
def seek():
print('')
Button(window,text='搜索',font=('楷體',16),command=seek).place(x=10,y=430)
# 下載按鈕
def download():
print('')
Button(window,text='下載',font=('楷體',16),command=download).place(x=120,y=430)
# 退出按鈕
Button(window,text='退出',font=('楷體',16),command=quit).place(x=228,y=430)
window.mainloop()
第二步,實現小說搜索的功能
def seek():
global info
book = []
author = []
add = []
word = key_word.get() # 獲取輸入框的內容
url = 'https://qxs.la/s_' + word # 拼接搜索地址
bs = get_html_bs(url) # 獲取源碼並返回bs對象
data_all = bs.find_all('ul',class_='list_content') # 搜索所有的小說
for data in data_all: # 遍歷提取信息
book.append(data.find_all('a')[0].string) # 提取小說名字
add.append(data.find_all('a')[0]['href']) # 提取小說地址
author.append(data.find_all('a')[2].string) # 提取小說作者
info = list(zip(book,author,add)) # 將提取出來的信息打包
for i in range(show.size()): # 清空所有的列表項
show.delete(0)
for data in info: # 將信息插入到列表中,顯示內容
show.insert('end','{}({})'.format(data[0],data[1]))
Button(window,text='搜索',font=('楷體',16),command=seek).place(x=10,y=430)
第三步,實現小說下載功能:
def download():
global info # 導入全局變量
txt = '' # 存放小說內容
index = show.curselection()[0] # 獲取選中列表項的下標
book_name = info[index][0] # 提取書名
url = 'https://qxs.la' + info[index][2] # 合成小說詳情頁面地址
bs = get_html_bs(url) # 獲取源碼並返回bs對象
first = bs.find('div',class_="chapter") # 提取出第一篇小說的地址
url = 'https://qxs.la' + first.find('a')['href'] # 合成地址
while True:
try:
bs = get_html_bs(url) # 獲取小說內容頁面
txt = txt + bs.find('div',class_="text t_c").h1.text + '\n' # 保存章節題目
data = bs.find('div', id="content") # 提取小說內容
data = data.find_all(text=True) # 因爲這個頁面比較特殊,大標籤內包括小標籤和文本內容
# 所以要經過進一步的處理,先獲取全部文本內容
for d in data: # 遍歷所有獲取到的內容
if d[0:2] == u'\u3000\u3000': # 發現小說內容都有兩個空格開頭
txt = txt + d.strip() + '\n' # 將小說內容拼起來
print('{}下載完畢!'.format(url)) # 輸出下載結果
next_url = bs.find('a', id="nextLink")['href'] # 獲取下一章的地址
if next_url[0:5] == '//qxs': # 發現最後一張還是有下一章的,但是下一章的地址是以“//qxs”開頭
print('下載完畢!')
break
url = 'https://qxs.la' + next_url # 拼接下一章的地址
except:
print('下載錯誤!')
txt.encode('utf-8') # 設置文字編碼
with open('{}.txt'.format(book_name),'w') as f: # 保存小說,生成txt文檔
f.write(txt)
Button(window,text='下載',font=('楷體',16),command=download).place(x=120,y=430)