网页小说抓取 ios( soup就是docx文档的必要语法及必要性分析(图))
优采云 发布时间: 2021-11-11 19:19网页小说抓取 ios(
soup就是docx文档的必要语法及必要性分析(图))
完全小白篇-使用Python爬取网络小说
一、找一个你要爬取的小说二、分析网页网页的展示方式需要用到的库文件
三、向网站发送请求四、正则提取五、跳转的逻辑六、后续处理七、保存信息进入docx文件八、新的问题:超时重传
<a id="_2"></a>一、找一个你要爬取的小说
<p>作为python小白,这篇博客仅作为我的一个学习记录。<br /> 本篇我就拿一个实际案例来做吧,短短50行代码调试了一晚上,爬虫还得继续好好学啊!拿最近很火的《元龙》举例。<br /> (采用读书网的资源)
<a id="_8"></a>二、分析网页
<a id="_10"></a>网页的展示方式
打开最开始的那章,按F12看一下网页代码,首先需要注意的地方无外乎两点:
从目录的网址后面添加了一个什么编号这个网站的网页编码格式是什么(在head标签里都能找到)各个章节之间具有怎样的跳转关系<br /> 跳转关系这一块,现在的小说网站已经不是按照章节+1编号也+1的方式了,所以我们可以考虑利用 a 标签里的 href="" 直接跳转我们要提取的信息有着怎样的风格<br /> 在下图中我们可以看到,每章标题、正文等我们要爬取的东西全部在p标签中<br />
<br /> <br /> 非常简单的风格!(所以我才先选这个网站试手 /滑稽)<a id="_22"></a>需要用到的库文件
在开始之前,先简单介绍一下这次使用到的库文件:
from bs4 import BeautifulSoup #网页解析,数据获取
from docx import Document #操作Word的.docx文档
import re #正则表达式,文字匹配
import requests #根据指定url获取网页数据
from requests.adapters import HTTPAdapter #设置重传时有用
import os #最后用来暂停一下
</p>
emm,如果有些还没有安装,那么pip就可以了。
在任意 cmd 窗口中输入:
pip3 install Beautifulsoup4
pip3 install docx
pip3 install re
pip3 install requests
三、向网站发送请求
接下来我们开始一步步细化我们的思路:
def main():
#目录的网址
baseurl = input("请输入目录列表的那个网址(例如https://www.dusuu.com/ml/1033/)\n")
number = input("请打开该小说第一章,输入一下网址新增加的那个数字(例如2688178)\n")
#试手,先开一下第一章试试
url = baseurl+str(number)+".html"
#模拟浏览器身份头向对方发送消息,不过一般的小说网站没什么反爬机制,头的话可有可无
head = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"}
print("已完成爬取的章节:")
req = requests.get(url = url, headers = head)
#上文我们已经看到是UTF-8的编码格式,这里照搬按此解析即可
req.encoding = 'UTF-8'
#解析得到网站的信息
soup = BeautifulSoup(req.text, 'html.parser')
print(soup)
os.system("pause")
if __name__ == "__main__":
main()
很好的做出了我们想要的结果。汤是完全一样的网站信息
四、正则摘录标题
提取方法:在div class="bookname"中找到h1标签的content body
提取方法:div id="content" style="font-size: 24px;" 里面的所有p标签
这里我们将使用bs4库中的搜索函数find_all(),re库中的提取函数.findall()
我们首先搜索所有必需的项目:
for item in soup.find_all('div',class_="bookname"):
item = str(item)
title = re.findall(findTitle, item)[0]
for item in soup.find_all('div',id="content"):
item = str(item)
end = re.findall(findEnd, item)
让我们定义提取方法:
#创建正则表达式对象,r是为了避免对'/'的错误解析
findTitle = re.compile(r'(.*?)',re.S)
findEnd = re.compile(r'<p>(.*?)',re.S)
</p>
这样就可以提取出title和body的所有内容
五、 跳转逻辑
既然我们可以完全处理一个网页的信息,那我们如何跳转到其他章节呢?
只需使用a标签“下一章”的跳转链接
同样,仍然
for item in soup.find_all('a',id="pager_next"):
item = str(item)
link = re.findall(findLink, item)[0]
url = "https://www.dusuu.com" + str(link)
常规对象(规则)是:
findLink = re.compile(r'下一章')
六、后续处理
当前的代码片段是:
from bs4 import BeautifulSoup #网页解析,数据获取
from docx import Document #操作Word的.docx文档
import re #正则表达式,文字匹配
import requests #根据指定url获取网页数据
from requests.adapters import HTTPAdapter #设置重传时有用
import os #最后用来暂停一下
findTitle = re.compile(r'(.*?)',re.S)
findEnd = re.compile(r'<p>(.*?)',re.S)
findLink = re.compile(r'下一章')
def main():
baseurl = input("请输入目录列表的那个网址(例如https://www.dusuu.com/ml/1033/)\n")
number = input("请打开该小说第一章,输入一下网址新增加的那个数字(例如2688178)\n")
url = baseurl+str(number)+".html"
link = ""
head = { #模拟浏览器身份头向对方发送消息
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
print("已完成爬取的章节:")
#最后一章中,点击“下一章”会回到目录那里
while(link!="/ml/10942/"):
req = requests.get(url = url, headers = head)
req.encoding = 'UTF-8'
soup = BeautifulSoup(req.text, 'html.parser')
for item in soup.find_all('div',class_="bookname"):
item = str(item)
title = re.findall(findTitle, item)[0]
print(title)
for item in soup.find_all('div',id="content"):
item = str(item)
end = re.findall(findEnd, item)
#每章最后一句正文都是网站的广告,我们不要那个
for i in range(len(end)):
if(i==(len(end)-1)):
end[i]="\n"
print(end)
#跳转到下一页
for item in soup.find_all('a',id="pager_next"):
item = str(item)
link = re.findall(findLink, item)[0]
url = "https://www.dusuu.com" + str(link)
os.system("pause")
if __name__ == "__main__":
main()
</p>
程序本身已经可以打印每一章
七、保存信息并进入docx文件
其实,每得到一个标题,每得到一个结尾,就可以为一个docx文档写一个标题和一个段落。
以下是多个操作所需的 docx 文档语法:
库函数: from docx import Document 创建文档对象: Doc = Document() 写标题操作: Doc.add_heading(title, level = 0)
注意0到5级为一级标题->第六级标题写段落操作:Doc.add_paragraph() 八、 新问题:重传超时
完成一系列操作后,我在运行的时候,前几章完全没问题。但是随着章节的增加和访问量的增加,新的问题出现了:无限访问超时。可能每部小说网站都有这个问题,连续的高频访问可能在某次访问中突然“掉线”。
查了很多方法,这里总结一下比较常用的方法和效果:
全局设置 Socket 超时持续时间:
在全局设置中:
import socket
socket.setdefaulttimeout(time_len)
但确实,效果并不明显。当有更多章节时,它仍然会无限期超时。
设置 DNS
比如将本地DNS优先级设置为阿里的,或者腾讯、百度的公共DNS,效果是肯定的,但实际上已经减少了超时的发生,超时时也无法解析超时。
超时重传
以上两种方法的结合。我检查了很多,但它可能需要一些基础知识,例如 retry()。
这里我用了最基本的try:
首先添加一个库: from requests.adapters import HTTPAdapter
在我们的函数中,变量 req 有一些新的设置:
req=requests.Session()
#访问https协议时,设置重传请求最多3次
req.mount('https://',HTTPAdapter(max_retries=3))
另外,设置 req 的超时时间:
#5s的超时时长设置
req = requests.get(url = url, headers = head, timeout=5)
如果超时,打印错误:
except requests.exceptions.RequestException as e:
print(e)
总代码如下:
from bs4 import BeautifulSoup #网页解析,数据获取
from docx import Document
import os
import re #正则表达式,文字匹配
import requests
from requests.adapters import HTTPAdapter
findTitle = re.compile(r'(.*?)',re.S)
findEnd = re.compile(r'<p>(.*?)',re.S)
findLink = re.compile(r'下一章')
def main():
baseurl = input("请输入目录列表的那个网址(例如https://www.dusuu.com/ml/1033/)\n")
# https://www.dusuu.com/ml/10942/
Doc = Document()
number = input("请打开该小说第一章,输入一下网址新增加的那个数字(例如2688178)\n")
#2622647
savepath = "./"+input("请为你的docx文档命名:")+".docx"
url = baseurl+str(number)+".html"
link = ""
req=requests.Session()
req.mount('https://',HTTPAdapter(max_retries=3))
head = { #模拟浏览器身份头向对方发送消息
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
print("已完成爬取的章节:")
while(link!="/ml/10942/"):
try:
req = requests.get(url = url, headers = head, timeout=5)
req.encoding = 'UTF-8'
soup = BeautifulSoup(req.text, 'html.parser')
for item in soup.find_all('div',class_="bookname"):
item = str(item)
title = re.findall(findTitle, item)[0]
print(title)
Doc.add_heading(title, level = 0)
for item in soup.find_all('div',id="content"):
item = str(item)
end = re.findall(findEnd, item)
for i in range(len(end)):
if(i==(len(end)-1)):
end[i]="\n"
Doc.add_paragraph(end[i])
Doc.save(savepath)
#跳转到下一页
for item in soup.find_all('a',id="pager_next"):
item = str(item)
link = re.findall(findLink, item)[0]
url = "https://www.dusuu.com" + str(link)
except requests.exceptions.RequestException as e:
print(e)
os.system("pause")
if __name__ == "__main__":
main()
</p>
好吧,我免费得到了一个4.5MB .docx 文件,这样我以后就不用上网看这本小说了!
当然,对于这个程序,书书网的所有小说都可以爬取。
(其实还是得去网上看,800多章还是直接用目录轻松跳转)
但是,学习是中流砥柱,我又获得了一项技能,可以用50行代码在别人面前炫耀。