一、背景:个人喜欢在网上看小说,但是,在浏览器中阅读小说不是很方便,喜欢找到小说的txt版下载到手机上阅读,但是有些小说不太好找txt版本,考虑自己从网页上爬一爬,自己搞定小说的txt版本。正好学习一下有关爬虫技术。
二、环境及爬取目标
1、linux centos7系统
2、小说网站:http://www.xbiquge.la/15/15158 ,小说名称《汉乡》。
三、爬取思路
1、爬取目录页面,生成小说章节标题和链接网址形成的字典。
2、根据上一步得到的字典中的章节链接网址,逐一爬取各章节内容,并写入预设的txt文件中。
四、代码实现(代码文件名称:test2.py)
#-*- coding:utf-8 -*-
import requests
from pyquery import PyQuery as pq
s = requests.session()
catalog_url="http://www.xbiquge.la/15/15158/" #小说目录页面链接
novelname="汉乡_test2.txt" #需要生成的小说文件名
count_begin=1 #爬取的起始章节号
count_end=1491 #爬取的结束章节号。在浏览器调试页面的console(控制台),使用命令$("dd").size()得到所有dd标签的数量为1491。
import requests
from pyquery import PyQuery as pq
s = requests.session()
catalog_url="http://www.xbiquge.la/15/15158/" #小说目录页面链接
novelname="汉乡_test2.txt" #需要生成的小说文件名
count_begin=1 #爬取的起始章节号
count_end=1491 #爬取的结束章节号。在浏览器调试页面的console(控制台),使用命令$("dd").size()得到所有dd标签的数量为1491。
#获取网页内容
def get_html(url):
headers = {
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0",
'Accept':"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
'Referer':"http://www.xbiquge.la/",
'Host':"www.xbiquge.la",
'Connection':"keep-alive"
} #headers字典内容从小说目录页面浏览器调试器中获取
r = s.get(url,headers=headers,verify=False)
r.encoding = 'utf-8'
return r.text
#解析目录页面,返回“标题:章节链接”字典
def parse_catalog(html):
doc=pq(html)
catalog={}
for i in range(count_begin, count_end+1): #range()为左闭右开,故括号右边界应设为count_end+1
def get_html(url):
headers = {
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0",
'Accept':"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
'Referer':"http://www.xbiquge.la/",
'Host':"www.xbiquge.la",
'Connection':"keep-alive"
} #headers字典内容从小说目录页面浏览器调试器中获取
r = s.get(url,headers=headers,verify=False)
r.encoding = 'utf-8'
return r.text
#解析目录页面,返回“标题:章节链接”字典
def parse_catalog(html):
doc=pq(html)
catalog={}
for i in range(count_begin, count_end+1): #range()为左闭右开,故括号右边界应设为count_end+1
url = "http://www.xbiquge.la" + str(doc("#list > dl > dd:nth-child(" + str(i) + ") > a").attr('href')) #“#list”表示名称为list的ID选择器。
title = doc("#list > dl > dd:nth-child(" + str(i) + ") > a").text()
catalog[title] = url
return catalog
#解析章节页面,获取页面文字内容
def parse_html(html):
doc=pq(html)
text=doc("#content").text() #获取ID选择器为content的文字内容
catalog[title] = url
return catalog
#解析章节页面,获取页面文字内容
def parse_html(html):
doc=pq(html)
text=doc("#content").text() #获取ID选择器为content的文字内容
return text
catalog_html=get_html(catalog_url)
catalog=parse_catalog(catalog_html)
#print(catalog)
'''
catalog_html=get_html(catalog_url)
catalog=parse_catalog(catalog_html)
#print(catalog)
'''
#调试用代码段,用于显示获取的小说章节内容
for title, url in catalog.items():
html=get_html(url)
text=parse_html(html)
print(text)
'''
with open(novelname, mode="a", encoding="utf-8") as f:
for title, url in catalog.items():
html=get_html(url)
text=parse_html(html)
print("正在下载-----------", title)
f.write(title)
f.write("\r\n")
f.write("\r\n")
f.write(text)
f.write("\r\n")
f.write("\r\n")
f.close()
for title, url in catalog.items():
html=get_html(url)
text=parse_html(html)
print(text)
'''
with open(novelname, mode="a", encoding="utf-8") as f:
for title, url in catalog.items():
html=get_html(url)
text=parse_html(html)
print("正在下载-----------", title)
f.write(title)
f.write("\r\n")
f.write("\r\n")
f.write(text)
f.write("\r\n")
f.write("\r\n")
f.close()
五、爬取测试
1、测试中发现,由于小说有1491个页面需要爬取,一次性全部爬取时,由于网络或其他原因,很难成功。会显示“requests.exceptions.ConnectionError”错误。
2、考虑进行分段爬取,可通过修改count_begin和count_end变量的值来实现分段爬取。
六、爬取程序运行显示(count_begin=6,count_end=10):
(base) [python@ELK ~]$ python test2.py
正在下载----------- 第六章破茧
正在下载----------- 第七章穿衣为礼?
正在下载----------- 第八章生死?小事耳!
正在下载----------- 第九章努力成为一个贱人
正在下载----------- 第十章徐夫人的手艺