再写一个用BeautifulSoup抓站的工具,体会BeautifulSoup的强大。

根据小说索引页获取小说全部章节内容并在本地整合为小说全文。不过不是智能的,不同的站点对代码需要做相应的修改。

#!/usr/bin/env python

import os
import sys
import re
import time
import chardet
import urllib.request as ur
from urllib.parse import urljoin,urlparse
from bs4 import BeautifulSoup
from threading import Thread class Download(Thread): #为每个章节分配多线程
def __init__(self,filepath,info):
Thread.__init__(self)
self.filepath = filepath
(self.link,self.chapter) = info def run(self):
print('开始下载: '+self.chapter)
section(self.filepath,self.chapter,self.link)
print('完成下载: '+self.chapter) def getData(url): #主要用于判断页面编码,但是发现BeautifulSoup自带判定能力,故废弃此函数
charsets = 'utf8'
response = ur.urlopen(url,timeout = 10)
html = response.read()
charinfo = chardet.detect(html)
charsets = charinfo['encoding']
data = html.decode(charsets)
return data def merge(tmpFiles,targetFile): #将下载的章节合并
for tmpFile in tmpFiles:
with open(targetFile,'a+') as wfile:
wfile.write(open(tmpFile,'r').read())
os.remove(tmpFile) def content(link): #获取章节页面的小说内容。对于不同的站点,在此函数内修改获取章节内容的代码
html = ur.urlopen(link,timeout = 10)
soup =BeautifulSoup(html)
contents = soup.find(id = 'readtext').p.span.text.replace('  ','\n') #BeautifulSoup会自动将&nbsp;转换为空格,<br/>转换为特殊符号
return contents def section(filepath,chapter,link): #下载章节内容
while True: #反复请求页面
try:
with open(filepath,'w') as nfile:
nfile.write(chapter+'\n'+content(link)+'\n')
break
except:
pass def index(url): #获取章节索引
indexs = []
while True: #反复请求页面
try:
html = ur.urlopen(url,timeout = 10)
#html = html.read().decode('gb2312')
#html = getData(url)
soup = BeautifulSoup(html,from_encoding = 'gbk')#BeautifulSoup能自动识别编码,但是会将gbk页面识别为gb2312页面,可能导致页面内部分数据获取失败,故显式指定
break
except:
pass
title = soup.find(name = 'div',attrs = {'class':'booktext'}).text
indexDiv = soup.find(name = 'div',attrs = {'class':'booktext'})
indexUl = [ul for ul in indexDiv.find_all('ul') if ul][1:]
for ul in indexUl:
indexList = [li.a for li in ul.find_all('li') if li]
index = [(urljoin(url,a.get('href')),a.text) for a in indexList if a]
indexs +=index
return indexs def novel(url):
tmpFiles = []
tasks = []
try:
indexs = index(url)
tmpDir = os.path.join(os.getcwd(),'tmp')
if not os.path.exists(tmpDir): #创建章节片段存放的临时目录
os.mkdir(tmpDir)
for i,info in enumerate(indexs):
tmpFile = os.path.join(tmpDir,str(i))
tmpFiles.append(tmpFile)
task = Download(tmpFile,info) #开启新线程下载章节内容
task.setDaemon(True)
task.start()
tasks.append(task)
if len(tasks) >= 20: #将线程总数控制在20个以内,如果线程过多会导致程序崩溃
while len([task for task in tasks if task.isAlive()]):
print( '进度: {} / {}'.format(i+1-len([task for task in tasks if task.isAlive()]),len(indexs))) #显示下载进度
time.sleep(2)
tasks = []
if i == len(indexs) - 1:
while len([task for task in tasks if task.isAlive()]):
print( '进度: {} / {}'.format(len(indexs) - len([task for task in tasks if task.isAlive()]),len(indexs)))
time.sleep(2)
print( '进度: {} / {}'.format(len(indexs),len(indexs)))
print('开始整合......')
merge(tmpFiles,os.path.join(os.getcwd(),title+'.txt'))
print('下载成功!')
except Exception as ex:
print(ex)
print('下载失败!')
sys.exit()
def main(argv):
try:
novel(argv[0])
except KeyboardInterrupt as kbi: #使用<C-c>中断下载后仍然能将已下载的章节合并
tmpDir = os.path.join(os.getcwd(),'tmp')
if os.path.exists(tmpDir):
tmpFiles = [os.path.join(tmpDir,tfile) for tfile in os.listdir(tmpDir) if os.path.isfile(os.path.join(tmpDir,tfile))]
print('开始整合不完整的下载......')
try:
merge(tmpFiles,os.path.join(os.getcwd(),'不完整文档.txt'))
if os.path.exists(os.path.join(os.getcwd(),'不完整文档.txt')):
print('部分章节下载成功!')
else:
print('下载失败!')
except:
print('下载失败!')
sys.exit()
os.rmdir(tmpDir)
else:
print('下载失败!')
sys.exit()
if os.path.exists(os.path.join(os.getcwd(),'tmp')):
os.rmdir(os.path.join(os.getcwd(),'tmp')) if __name__ == "__main__":
if len(sys.argv) > 1:
main(sys.argv[1:])
#http://www.lueqiu.com/

截图:

Python3利用BeautifulSoup4抓取站点小说全文的代码的更多相关文章

  1. python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容

    python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容 Beautiful Soup 是用Python写的一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖 ...

  2. 对比使用Charles和Fiddler两个工具及利用Charles抓取https数据(App)

    对比使用Charles和Fiddler两个工具及利用Charles抓取https数据(App) 实验目的:对比使用Charles和Fiddler两个工具 实验对象:车易通App,易销通App 实验结果 ...

  3. 利用Crowbar抓取网页异步加载的内容 [Python俱乐部]

    利用Crowbar抓取网页异步加载的内容 [Python俱乐部] 利用Crowbar抓取网页异步加载的内容 在做 Web 信息提取.数据挖掘的过程中,一个关键步骤就是网页源代码的获取.但是出于各种原因 ...

  4. 利用Fiddler抓取websocket包

    一.利用fiddler抓取websockt包 打开Fiddler,点开菜单栏的Rules,选择Customize Rules... 这时会打开CustomRules.js文件,在class Handl ...

  5. Python3.x:抓取百事糗科段子

    Python3.x:抓取百事糗科段子 实现代码: #Python3.6 获取糗事百科的段子 import urllib.request #导入各类要用到的包 import urllib import ...

  6. Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺

    更新 其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个. 可就在今天,淘宝把所有的账号设置成了匿名显示,SO,获取非匿名旺旺号已经 ...

  7. 利用wireshark抓取远程linux上的数据包

    原文发表在我的博客主页,转载请注明出处. 前言 因为出差,前后准备总结了一周多,所以博客有所搁置.出差真是累人的活计,不过确实可以学习到很多东西,跟着老板学习做人,学习交流的技巧.入正题~ wires ...

  8. 利用wget 抓取 网站网页 包括css背景图片

    利用wget 抓取 网站网页 包括css背景图片 wget是一款非常优秀的http/ftp下载工具,它功能强大,而且几乎所有的unix系统上都有.不过用它来dump比较现代的网站会有一个问题:不支持c ...

  9. Python3利用BeautifulSoup4批量抓取站点图片的代码

    边学边写代码,记录下来.这段代码用于批量抓取主站下所有子网页中符合特定尺寸要求的的图片文件,支持中断. 原理很简单:使用BeautifulSoup4分析网页,获取网页<a/>和<im ...

随机推荐

  1. 二模14day2解题报告

    T1.砍树(cuttree) 给出n棵树,要锯下m米木材,现在有一个高度h,h以上所有木头都砍下来,求满足m米的最小h 很简单的二分答案判断可行性. T2.快速求和(quicksum) 给出数字串s, ...

  2. loadrunner录制脚本如何选择使用get请求和post请求的方式

    在loadrunner工具里录制脚本时常常会用到get请求和post请求,有关loadrunner常用的这两类的请求主要有: get请求: web_url 和 web_link post请求: web ...

  3. Servlet--表单、超链接、转发、重定向4种情况的路径

    Servlet中相对路径总结 假设web工程使用如下目录结构: 在介绍相对路径和绝对路径前需要先了解几个概念: 服务器的站点根目录:以tomcat服务器为例,tomcat服务器站点根目录就是apach ...

  4. ARCGIS如何进行可视域分析

    可视域分析在不同的领域有着广泛的应用,如火灾监控点的设定,观察哨所的设定等等.军事领域是可视域分析技术应用最广的领域.例如为了设计巡航导弹的航线,就必须对发射点到目标的地形进行分析,包括地形特征优劣分 ...

  5. java二

    一,面向对象 面向对象,似乎是太抽象了点,没人敢拍着胸脯说我面向对象学到了100%,纵然如此,了解面向对象的思想对于学好java等面向对象编程语言有着莫大的好处,因为一通百通,同样是面向对象,等你精通 ...

  6. SQL SERVER中求上月、本月和下月的第一天和最后一天 DATEADD DATEDIFF

    SQL SERVER中求上月.本月和下月的第一天和最后一天   1.上月的第一天 SELECT CONVERT(CHAR(10),DATEADD(month,-1,DATEADD(dd,-DAY(GE ...

  7. ubuntu 14.4 中文语言包安装问题

    1.安装前,请选择更新源,在系统设定 system setting 里,选择software and updates 里,选择中国的源,用于快速更新语言包 2.在language support里选择 ...

  8. CSS3 04

    animate.css库的使用 官网:https://daneden.github.io/animate.css/ 作用:将一切常见的动画直接封装,开发者不需要考虑实现过程,只需要添加对应的类就能实现 ...

  9. 【java基础学习二】 数组相互转换,转成用逗号隔开的字符串等

    /** * int[],Integer[],List,List<Integer>,HashSet<Integer>相互转换,转成用逗号隔开的字符串 */ public stat ...

  10. React Native 实现页面动态切换

    第一步. 初始化子View constructor(props){ super(props); this.state = { isChange : true, itemView : (<Text ...