目录

  • 1. 工具
  • 2. 正文
    • 2.1 URL
    • 2.2 思路
    • 2.3 实现
      • 2.3.1 获取各个章节URL
      • 2.3.2 获取一章内容
      • 2.3.3 写入内容
      • 2.3.4 完整代码
  • 3. 小结
    • 3.1 html基础知识
    • 3.2 Requests库方法
    • 3.3 BeauifulSoup库
    • 3.4 文件写入
    • 3.5 各个章节URL
  • 4. 参考

1. 工具

  1. 开发环境:Python3.7 + Visual Studio Code
  2. 浏览器:谷歌浏览器
  3. 安装Python库:requests——用来获取HTML、BeautifulSoup——用来解析HTML文档

2. 正文

2.1 URL

目标:在新笔趣阁网站上爬取烽火戏诸侯的《雪中悍刀行》(此处安利一波,烽火大大的文笔很好,天不生我李淳罡。。。。。跑偏了)。
目录页地址:http://www.xbiquge.la/0/745/

2.2 思路

  1. 分析目录页源码,找到保存各个章节URL的标签:右击鼠标—>选择检查(N)或者按F12,网页的源码就出来了。 要找到目录的URL,将鼠标放在其中一章目录上右击鼠标,源码就会跳到对应的内容那里。可见各章节的URL存放在属性id=’'list"的div标签内,只需找到对应属性的div,再将其内包含的所有a标签找出,就是找齐所有章节的URL了。


  2. 分析章节页内容:在内容(正文)上右击鼠标—>检查,跳到源码对应的内容。发现内容被存放在属性id="content"的div标签上,所以需要找到相应的div标签,再输出内容。
  3. 总体思路:在目录页获取各个章节的URL—>通过各个章节的URL遍历各个章节的内容—>写入文本文件(txt)里面

2.3 实现

2.3.1 获取各个章节URL

    def __get_Link_chapter(self):'''在目录页获得各个章节的url.解析目录页,通过属性找到存放各个章节url的div标签,获取各个章节的url并且返回'''# 当请求发生异常:连接或者超时错误,等待1S再尝试for try_counter in range(10):try:req_lp = requests.get(self.__url_lp, timeout=10)breakexcept ConnectionError:print('尝试获取目录页ConnectionError:%d' % (try_counter+1))except TimeoutError:print('尝试获取目录页TimeoutError:%d' % (try_counter+1))except:print('尝试获取目录页OtherError:%d' % (try_counter+1))time.sleep(1)if try_counter >= 9:print('获取目录页失败')returnelse:try:req_lp.encoding = req_lp.apparent_encoding# 建立BeautifulSoup对象,指定解析器lxmlbs_lp = BeautifulSoup(req_lp.text, 'lxml')# 找到所有对应属性的div标签div_list = bs_lp.find_all('div', attrs=self.__attrs_div_lp)# 找到所有的a标签link_chapter = []for div in div_list:link_chapter += div.find_all('a')return link_chapterexcept TypeError:print('目录页解析异常:TypeError')returnexcept:print('目录页解析异常:OtherError')return

2.3.2 获取一章内容

    def __get_content_chapter(self, link):'''获取章节内容.:param link:在目录页解析后得到的a标签内含章节名和url'''name_chapter = link.stringurl_chapter = self.__url_ws + link['href']  # 拼接得到章节页url# 在链接和读取过程中,出现异常的处理方式# 这里出现异常的话循环10次,等待1S重新读取for try_counter in range(10):try:# 超时设置为10Sreq_ct = requests.get(url_chapter, timeout=10)breakexcept ConnectionError:print('尝试获取章节链接:ConnectionError%d' % (try_counter+1))except TimeoutError:print('尝试获取章节链接:TimeoutError%d' % (try_counter+1))except:print('尝试获取章节链接:OtherError%d' % (try_counter+1))time.sleep(1)if try_counter >= 9:print('获取链接失败:'+name_chapter)return name_chapter+'\n\n'else:try:req_ct.encoding = self.__encode# 建立BeautifulSoup对象bs_ct = BeautifulSoup(req_ct.text, 'lxml')# 将找到的div内容转换成文本格式,# 并且将里面的&nbsp(不间断空格)替换成空格# 将br标签替换成换行符content = bs_ct.find('div', attrs=self.__attrs_div_ct)content = str(content).replace('<br/>','\n').replace('\xa0',' ')content = BeautifulSoup(content,'lxml').get_text()return name_chapter + '\n\n' + content + '\n\n'except TypeError:print('章节页解析异常:TypeError '+name_chapter)return name_chapter+'\n\n'except:print('章节页解析异常:OtherError '+name_chapter)return name_chapter+'\n\n'

2.3.3 写入内容

    def write(self, path_save):'''写下载的文件到指定路径.:param path_save:指定的保存路径'''# 在指定的文件夹路路径之下新建与书名同名的文本文件path_save = path_save + '\\' + self.__name + '.txt'# 获取各个章节的URLlink_chapter = self.__get_Link_chapter()if link_chapter is None:passelse:# 打开文件with open(path_save, 'w+', encoding=self.__encode) as file:for chapter, link in enumerate(link_chapter):# 获取章节内容content_chapter = self.__get_content_chapter(link)file.write(content_chapter)sys.stdout.write('下载进度:%.1f%%' % float(chapter/len(link_chapter)*100)+'\r')print('<<'+self.__name+'>>下载完成')

2.3.4 完整代码

from bs4 import BeautifulSoup
import requests
import time
import sysclass fiction():def __init__(self, name, url_ws, url_lp, encode, attrs_div_lp={}, attrs_div_ct={}):self.__name = name  # 名字self.__url_ws = url_ws  # 网站urlself.__url_lp = url_lp  # 链接(目录)页的urlself.__attrs_div_lp = attrs_div_lp  # 链接(目录页)存放各个章节链接的div标签属性self.__attrs_div_ct = attrs_div_ct  # 章节页存放内容的div标签属性self.__encode = encode  # 指定编码格式def Update(self, name, url_ws, url_lp, encode, attrs_div_lp={}, attrs_div_ct={}):'''重置参数必须同时重置所有参数,否则可能出现错误'''self.__name = name  # 名字self.__url_ws = url_ws  # 网站urlself.__url_lp = url_lp  # 链接(目录)页的urlself.__attrs_div_lp = attrs_div_lp  # 链接(目录页)存放各个章节链接的div标签属性self.__attrs_div_ct = attrs_div_ct  # 章节页存放内容的div标签属性self.__encode = encodedef __get_Link_chapter(self):'''在目录页获得各个章节的url.解析目录页,通过属性找到存放各个章节url的div标签,获取各个章节的url并且返回'''# 当请求发生异常:连接或者超时错误,等待1S再尝试for try_counter in range(10):try:req_lp = requests.get(self.__url_lp, timeout=10)breakexcept ConnectionError:print('尝试获取目录页ConnectionError:%d' % (try_counter+1))except TimeoutError:print('尝试获取目录页TimeoutError:%d' % (try_counter+1))except:print('尝试获取目录页OtherError:%d' % (try_counter+1))time.sleep(1)if try_counter >= 9:print('获取目录页失败')returnelse:try:req_lp.encoding = req_lp.apparent_encoding# 建立BeautifulSoup对象,指定解析器lxmlbs_lp = BeautifulSoup(req_lp.text, 'lxml')# 找到所有对应属性的div标签div_list = bs_lp.find_all('div', attrs=self.__attrs_div_lp)# 找到所有的a标签link_chapter = []for div in div_list:link_chapter += div.find_all('a')return link_chapterexcept TypeError:print('目录页解析异常:TypeError')returnexcept:print('目录页解析异常:OtherError')returndef __get_content_chapter(self, link):'''获取章节内容.:param link:在目录页解析后得到的a标签内含章节名和url'''name_chapter = link.stringurl_chapter = self.__url_ws + link['href']  # 拼接得到章节页url# 在链接和读取过程中,出现异常的处理方式# 这里出现异常的话循环10次,等待1S重新读取for try_counter in range(10):try:# 超时设置为10Sreq_ct = requests.get(url_chapter, timeout=10)breakexcept ConnectionError:print('尝试获取章节链接:ConnectionError%d' % (try_counter+1))except TimeoutError:print('尝试获取章节链接:TimeoutError%d' % (try_counter+1))except:print('尝试获取章节链接:OtherError%d' % (try_counter+1))time.sleep(1)if try_counter >= 9:print('获取链接失败:'+name_chapter)return name_chapter+'\n\n'else:try:req_ct.encoding = self.__encode# 建立BeautifulSoup对象bs_ct = BeautifulSoup(req_ct.text, 'lxml')# 将找到的div内容转换成文本格式,# 并且将里面的&nbsp(不间断空格)替换成空格# 将br标签换成换行符content = bs_ct.find('div', attrs=self.__attrs_div_ct)content = str(content).replace('<br/>','\n').replace('\xa0',' ')content = BeautifulSoup(content,'lxml').get_text()return name_chapter + '\n\n' + content + '\n\n'except TypeError:print('章节页解析异常:TypeError '+name_chapter)return name_chapter+'\n\n'except:print('章节页解析异常:OtherError '+name_chapter)return name_chapter+'\n\n'def write(self, path_save):'''写下载的文件到指定路径.:param path_save:指定的保存路径'''# 在指定的文件夹路路径之下新建与书名同名的文本文件path_save = path_save + '\\' + self.__name + '.txt'# 获取各个章节的URLlink_chapter = self.__get_Link_chapter()if link_chapter is None:passelse:# 打开文件with open(path_save, 'w+', encoding=self.__encode) as file:for chapter, link in enumerate(link_chapter):# 获取章节内容content_chapter = self.__get_content_chapter(link)file.write(content_chapter)sys.stdout.write('下载进度:%.1f%%' % float(chapter/len(link_chapter)*100)+'\r')print('<<'+self.__name+'>>下载完成')if __name__ == '__main__':start = time.time()f = fiction(name='雪中悍刀行',url_ws='http://www.xbiquge.la',url_lp='http://www.xbiquge.la/0/745/',attrs_div_lp={'id': 'list'},attrs_div_ct={'id': 'content'},encode='utf-8')f.write(r'C:\Users\HP\Desktop\pytxt')stop = time.time()print('用时:%ds' % (stop-start))

3. 小结

3.1 html基础知识

html基础知识:菜鸟教程——HTML教程

3.2 Requests库方法

  1. get():获取服务器响应的内容。注意:最好设置超时时间,否者如果服务器无响应则一直会发送请求,程序就会一直卡在那个地方,而且不会报异常或者错误。

  2. 关于编码问题:最好是指定编码方式,根据Requests猜测的编码可能不准,后面写入文本的时候可能会发生异常。具体的分析可以参考知乎

    html在源码head部分的charset就指定了编码,有时候说明的编码和实际使用的编码不一致,此时使用Response.apparent_encoding指定编码。
 req_lp.encoding = req_lp.apparent_encoding


3. Requests库更多更详细可以参考官方文档:快速上手、高级用法、开发接口

3.3 BeauifulSoup库

  1. 建立BeauifulSoup对象:
bs_lp = BeautifulSoup(req_lp.text, 'lxml')

第一个参数时需要解析的HTML文档,第二个参数时指定的文档解析器


2. find_all()方法:寻找当前tag标签下符合过滤条件的所有标签,返回一个bs4.element.ResultSet类型,其实可以像列表形式使用。

3. 编码:使用BeautifulSoup之后,无论原来的HTML文档是gbk编码还是utf-8编码亦或是其他编码,全都会转成Unicode编码,可能是因为Unicode编码兼容所有的语言吧。

3.4 文件写入

Python文件操作:菜鸟教程——Python3 File(文件) 方法

3.5 各个章节URL

目录页的各个章节的URL是不完整的,需拼接上网站的URL才算是完整的URL。

url_chapter = self.__url_ws + link['href']  # 拼接得到章节页url

4. 参考

  1. Python3网络爬虫快速入门实战解析
  2. python3爬虫中文乱码问题求解?(beautifulsoup4)

第一次修改:将br标签换成换行符

我的爬虫入门作(一)相关推荐

  1. python很全的爬虫入门教程

    python很全的爬虫入门教程 一.爬虫前的准备工作 首先,我们要知道什么是爬虫 1.什么是网络爬虫? 网络爬虫是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁 ...

  2. 爬虫入门学习(八)模拟登录丁香园论坛爬取用户信息

    爬虫入门学习(八)实战大项目模拟登录丁香园爬取信息 1 目标 2 思路 3 主要的技术点 3.1 模拟登录 3.2 抓取用户个人主页 4 完整代码 5 项目后期拓展 1 目标 模拟登录丁香园,并抓取页 ...

  3. Python 爬虫入门教程——社团授课型

    Python爬虫入门教程 基础知识 什么是HTML.CSS.JavaScript 网页往往采用html+css+js开发,html是一门标记语言 如下: <!- 将下面这句话放入html文件中, ...

  4. Python爬虫入门2(实战)

    文章目录 13.B站直播间弹幕爬取 代码: 运行结果: 14.xpath解析爬虫 入门: lxml安装: 基本格式: 15.xpath入门讲解 材料: py代码: 运行结果: 技巧: 16.xpath ...

  5. python爬虫入门教程(二):开始一个简单的爬虫

    2019/10/28更新 使用Python3,而不再是Python2 转载请注明出处:https://blog.csdn.net/aaronjny/article/details/77945329 爬 ...

  6. Python爬虫入门教程02:小说爬取

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 前文 01.python爬虫入门教程01:豆瓣Top电影爬取 基本开发环境 Python 3 ...

  7. python爬虫入门教程--优雅的HTTP库requests(二)

    requests 实现了 HTTP 协议中绝大部分功能,它提供的功能包括 Keep-Alive.连接池.Cookie持久化.内容自动解压.HTTP代理.SSL认证等很多特性,下面这篇文章主要给大家介绍 ...

  8. python爬虫入门教程--快速理解HTTP协议(一)

    http协议是互联网里面最重要,最基础的协议之一,我们的爬虫需要经常和http协议打交道.下面这篇文章主要给大家介绍了关于python爬虫入门之快速理解HTTP协议的相关资料,文中介绍的非常详细,需要 ...

  9. 爬虫入门到精通-HTTP协议的讲解

    HTTP协议的讲解 本文章属于爬虫入门到精通系统教程第三讲 什么是HTTP协议? 引用自维基百科 超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是互联网 ...

最新文章

  1. python opengl 入门
  2. oracle中更改列明和更改显示列长度
  3. java 生产者消费者_基于JAVA的生产者消费者问题
  4. unity3d连接数据库
  5. 文本格式化标签(HTML)
  6. 在lua中优雅的操作日期和时间
  7. web前端开发之微信小程序
  8. 编译原理 自底向上语法分析
  9. asp.net学习心得总结
  10. php trying to get,php 做微信认证登陆 返回错误 Trying to get property of non-object
  11. java项目视频22套
  12. 【题解】[Swerc2008]First Knight
  13. 模拟电子电路基础——放大器理解与梳理
  14. ORA-00937:不是单组分组函数 ORA-22818:这里不允许出现子查询表达式
  15. 受到人工智能发展的影响的,主要包括哪些行业?
  16. element el-dialog样式修改
  17. AMD GPU的断点指令
  18. 15天精读掌握《高德纳:具体数学》 第3天 2019.5.29
  19. 软件测试入门简单么?入行后如何做职业规划
  20. c语言编译数学公式器,公式编辑器 - 数学公式在线编辑器 - MathEditor

热门文章

  1. 导航栏 下拉菜单的制作
  2. php代码画表情包,canvas绘制表情包的示例代码
  3. 惊!西游记内幕竟是这样的。
  4. 第二次作业,制作调查问卷
  5. 7-15(查找) 航空公司VIP客户查询(25 分)
  6. 通信原理|Chapter1.绪论
  7. 安利一个小众又逆天的副业,轻松月入过万
  8. 下载安装cygwin/X
  9. 0202插入删除-算法第四版红黑树-红黑树-数据结构和算法(Java)
  10. 认知科学早期的计算机隐喻理论是什么,相对于认知科学,首先我们得从这六个问题着手...