1.背景
一般我們進行小說網的爬取,大致思路都是先獲取小說網頁的html內容,然后使用正則表達式找到對應的章節以及其對應的url。BeautifulSoup是用Python寫的一個HTML/XML的解析器,它可以很好的處理不規范標記並生成剖析樹(parse tree)。 它提供簡單又常用的導航(navigating),搜索以及修改剖析樹的操作。使用BeautifulSoup來爬取小說網,將大大減少正則表達式的使用,提高效率。
2.代碼解析
2.1導包
2.2函數獲取html頁面的內容
向函數傳入一個url,函數會構造一個url請求,向目標url發送請求並獲取響應對象,然后讀取獲得的內容,再返回。
2.3函數獲取小說的章節目錄
向函數傳入一個html頁面的內容,這里傳入應該是具體小說的首頁,也就是有章節目錄的那個頁面,函數獲取章節目錄頁面的內容后,先構建一個soup對象,緊接着運用soup對象里面的方法,分別獲取小數的標題和章節名稱以及其對應的url,最后以字典的形式返回。
2.4函數獲取小說的文本內容
向函數傳入以章節名稱和對應的url為鍵值對的字典和小說標題,函數遍歷這個字典,調用gain_html_content 函數獲得小說的html頁面的內容,然后構建soup對象,並直接找到小說文章內容的標簽,並獲取其中的文本信息,最后調用write2file函數,寫入本地txt文件。
2.5將小說內容寫入本地文件
這個就沒啥好說的了,直接將小說文本內容,寫入本地。
2.6代碼總覽
-
# -*- coding: utf-8 -*-
-
# @Time : 2018/5/21 09:08
-
# @Author : daigua
-
# @File : 12-筆趣閣-beautifulsoup.py
-
# @Software: PyCharm
-
-
-
from bs4 import BeautifulSoup
-
import re
-
import urllib.request
-
import os
-
-
-
def gain_html_content(url):
-
"""獲取網頁的html內容
-
url:目標url地址
-
content:返回的頁面內容
-
"""
-
# 構建請求對象
-
headers = {
-
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
-
}
-
request = urllib.request.Request(url, headers=headers)
-
# 發送請求
-
response = urllib.request.urlopen(request)
-
# 讀取文件
-
content = response.read().decode('utf-8')
-
return content
-
-
-
def get_chapter(content):
-
# 先構建一個soup對象
-
soup = BeautifulSoup(content, "lxml")
-
# 獲取小說的標題
-
title = soup.title.string
-
# 找到小說的內容(是在div標簽里面,並且這個div標簽的id為"list")
-
content = soup.find("div", id="list")
-
# 獲取章節列表,列表里面的內容都是標簽對象
-
chapter_list = content.find_all("a", attrs={"style": "", "href": re.compile(r"/.*\.html")})
-
# 定義一個空的字典,用於存放章節名稱和對應url的鍵值對
-
chapter_dict = dict()
-
for x in chapter_list:
-
file_name = x.string
-
file_url = x.attrs["href"] # 獲取a標簽中href屬性里面的值
-
chapter_dict[file_name] = "https://www.xs.la" + file_url
-
# 將章節字典,和標題返回
-
return chapter_dict, title
-
-
-
def get_text(chapter_dict, title):
-
for name, url in chapter_dict.items():
-
# 獲取頁面內容
-
content = gain_html_content(url)
-
soup_text = BeautifulSoup(content, "lxml")
-
new_content = soup_text.find("div", id="content")
-
-
# 獲取soup對象中的文本信息text
-
new_content = new_content.get_text()
-
# 調用寫入本地的函數
-
write2file(title, name, new_content)
-
-
-
def write2file(title, file_name, content):
-
"""將小說寫入本地文件"""
-
print("%s下載中。。。" % file_name)
-
direction = title + "/" + file_name
-
if not os.path.exists(title):
-
os.mkdir(title)
-
with open(direction + ".txt", 'w') as f:
-
f.write(content)
-
print("%s下載完畢!" % file_name)
-
-
-
def main():
-
# 獲取頁面內容
-
tar_url = input("請輸入小說網址:")
-
content = gain_html_content(tar_url)
-
# 獲取 章節名字:url 字典和小說標題
-
dict1, title = get_chapter(content)
-
# 獲取小說內容,並寫入本地txt文件
-
get_text(dict1, title)
-
-
-
if __name__ == "__main__":
-
main()
4.一些說明
- 本例中用到一些BeautifulSoup的方法,都可以在網上查得到,所以本例並未對其具體用法進行說明;
- 本例只是一個小測試,所以還存在一些問題,比如爬到一半斷網,重新爬取的時候又得從頭開始,還有本例使用的是單任務,效率沒有多任務高,這些問題改進就由各位去做了,本例主要目的只是展現爬取小說網的思路。