之前在Python爬虫实战(2)中我们曾爬取过网络小说,本篇博客的爬取解析过程和之前几乎完全一样,不同的是数据存储方式,之前是存储到文件中(csv,txt,json,excel等),这次我们将提取的小说存储到MongoDB数据库中。下面是首页链接:
http://www.xbiquge.la/xiaoshuodaquan/
首先打开上面的网址,我们会发现是小说列表,选择其中一部小说,打开会是章节列表,打开某一章后才是文本。所以,我们要首先获取小说列表,然后打开某一部小说后,再获取章节列表,最后在爬取对应的内容。依旧是四部曲:
首先搭建起程序主体框架:
import os
import re
import time
import requests
from requests import RequestException
import pymongo
def get_page(url):
pass
def get_list(page):
pass
def get_chapter(novel_url):
pass
def get_content(chapter, name):
pass
if __name__ == '__main__':
#连接MongoDB
client = pymongo.MongoClient('mongodb://localhost:27017')
#指定数据库
db = client.novel
#指定集合
novel_col = db.novels #存储小说名和章节名
chapter_col = db.chapters #存储章节名和章节内容
# 首页url
url = 'http://www.xbiquge.la/xiaoshuodaquan/'
# 发送请求,获取响应
page = get_page(url)
# 获取小说列表 解析响应
novel_list = get_list(page)
print(novel_list)
for item in novel_list:
novel_chapter = get_chapter(item[0]) #得到章节列表
print(novel_chapter)
# 按小说章节 分别保存到文本文件
for chapter in novel_chapter:
get_content(chapter, item[1])
发送请求,获取响应:
def get_page(url):
try:
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
response = requests.get(url,headers=headers)
if response.status_code==200:
response.encoding = response.apparent_encoding
return response.text
return None
except RequestException:
return None
解析首页的响应,获取小说列表:
发现首页所有的小说都在li标签中,每个小说都包在一个a标签中,并有链接。
def get_list(page):
#我们可以只通过a标签来解析
pattern = re.compile('<a href="(.*?)">(.*?)</a>',re.S)
list = pattern.findall(page)
return list[10:] #只通过a标签来解析 前10个并不是小说,所以从第11个开始
获取小说的章节列表:
发现小说的所有章节都在dd标签中,每个章节都包在一个a标签中,并有链接。
def get_chapter(novel_url):
html = get_page(novel_url)
pattern = re.compile("<dd><a href='(.*?)' >(.*?)</a></dd>",re.S)
chapters = pattern.findall(html)
return chapters[:5] #取前5章 也可以取全部
获取章节内容:
章节内容在上图的div标签中。
def get_content(chapter, name):
chapter_url = 'http://www.xbiquge.la' + chapter[0]
html = get_page(chapter_url)
pattern = re.compile('<div id="content">(.*?)<p>', re.S) #获取章节内容
chapter_content = pattern.findall(html)
for content in chapter_content:
content = content.replace(" ", "").replace("<br />", "")
#插入mongodb
novel_col.insert_one({'name':name,'chapter':chapter[1]})
chapter_col.insert_one({'name':chapter[1],'content':content})
爬取效果,确保安装了mongodb和可视化管理工具Robo3T,打开Robo3T:
novels集合:存储小说名和章节名
chapters集合:存储章节名和章节内容
完整代码:
import os
import re
import time
import requests
from requests import RequestException
import pymongo
def get_page(url):
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
response.encoding = response.apparent_encoding
return response.text
return None
except RequestException:
return None
def get_list(page):
# 我们可以只通过a标签来解析
pattern = re.compile('<a href="(.*?)">(.*?)</a>', re.S)
list = pattern.findall(page)
return list[10:] # 只通过a标签来解析 前10个并不是小说,所以从第11个开始
def get_chapter(novel_url):
html = get_page(novel_url)
pattern = re.compile("<dd><a href='(.*?)' >(.*?)</a></dd>", re.S)
chapters = pattern.findall(html)
return chapters[:5] # 取前5章 也可以取全部
def get_content(chapter, name):
chapter_url = 'http://www.xbiquge.la' + chapter[0]
html = get_page(chapter_url)
pattern = re.compile('<div id="content">(.*?)<p>', re.S)
chapter_content = pattern.findall(html)
for content in chapter_content:
content = content.replace(" ", "").replace("<br />", "")
novel_col.insert_one({'name':name,'chapter':chapter[1]})
chapter_col.insert_one({'name':chapter[1],'content':content})
if __name__ == '__main__':
#连接MongoDB
client = pymongo.MongoClient('mongodb://localhost:27017')
#指定数据库
db = client.novel
#指定集合
novel_col = db.novels
chapter_col = db.chapters
# 首页url
url = 'http://www.xbiquge.la/xiaoshuodaquan/'
# 发送请求,获取响应
page = get_page(url)
# 获取小说列表 解析响应
novel_list = get_list(page)
print(novel_list)
for item in novel_list:
novel_chapter = get_chapter(item[0]) #得到章节列表
print(novel_chapter)
# 按小说章节 分别保存到文本文件
for chapter in novel_chapter:
get_content(chapter, item[1])