网站开发推进计划表,新网互联的网站,北京商场购物中心,wordpress 极简 h5整本小说的爬取保存 目标大致思路页面的爬取解析—XPath请求网页内容解析网页内容正文爬取与解析单个页面数据获取爬取所有页面 数据清洗 经过学习基础#xff0c;我们学以致用一下子#xff0c;爬取小说#xff0c;注意这个小说本身是免费的哦#xff0c;以后再进阶。 本次… 整本小说的爬取保存 目标大致思路页面的爬取解析—XPath请求网页内容解析网页内容正文爬取与解析单个页面数据获取爬取所有页面 数据清洗 经过学习基础我们学以致用一下子爬取小说注意这个小说本身是免费的哦以后再进阶。 本次为实战记录笔者很多碎碎念可忽略 目标
基于requests库和lxml中的xpath编写的爬虫目标小说网站域名http://www.365kk.cc/ 这是网上找的小说网址很多而且没有很多反扒机制新手友好 大致思路 其实也可以不写梳理一下吧虽然是空话 主要分三步如同大象进冰箱hh
获取网页内容通过requests库实现解析网页内容得到其中我们想要的部分通过xpath实现将解析出的内容储存到文本文档中
我们把要做的具体化首先选取一本自己喜欢的小说笔者以此为例是的就是这么重口。 《我是一具尸体》 页面的爬取解析—XPath
要干嘛明确一下
获取目标书籍的基本信息包括书籍的书名、作者、简介——这些信息应该都在同一个页面中获取即上面展示的页面获取目标书籍每一章节的标题和内容——不同章节在不同的页面不同页面之间可以通过下一页按序跳转正文部分的存储格式应便于阅读不能把所有文字都堆积在一起也不能包括除了正文之外的其他无关内容
因此我们首先尝试请求书籍的主页获取基本信息紧接着再从书籍的第一章开始不断地请求“下一页”直到爬取整本书并将它们以合适的格式储存在文本文档中。
笔者是用Google Chrome在首页点击右键 — 检查 可以看出浏览器下方弹出了一个窗口这里显示的就是该页面的源代码我们选中的内容位于一个h1标签中。点击右键 - 复制 - 复制 XPath即可得到书名的XPath路径也就是书名在网页中的位置。
书名/html/body/div[4]/div[1]/div/div/div[2]/div[1]/h1从书籍的首页中同理我们可以获取的信息主要包括
书名 作者 最后更新时间
作者/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[1]
最后更新时间/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[5]
简介/html/body/div[4]/div[1]/div/div/div[2]/div[2]请求网页内容
使用基础的python爬虫网页请求方法 requests 库直接请求。 在请求网页时我们需要将我们的爬虫伪装成浏览器具体通过添加请求头 headers 实现。 请求头以字典的形式创建可以包括很多内容这里只设置四个字段User-Agent, Cookie, Host 和 Conection。
在刚才打开的页面中点击 网络英文版是Network刷新页面找到其中的第一个文件 1053/ 打开 标头 - 请求标头 即可得到想要的字段数据。
import requests# 请求头添加你的浏览器信息后才可以正常运行
headers {User-Agent: ...,Cookie: ...,Host: www.365kk.cc,Connection: keep-alive
}
# 小说主页
main_url http://www.365kk.cc/1/1053/
# 使用get方法请求网页
main_resp requests.get(main_url, headersheaders)
# 将网页内容按utf-8规范解码为文本形式
main_text main_resp.content.decode(utf-8)
print(main_text)
可以看出我们成功请求到了网站内容接下来只需对其进行解析即可得到我们想要的部分。
解析网页内容
我们使用 lxml 库来解析网页内容具体方法为将文本形式的网页内容创建为可解析的元素再按照XPath路径访问其中的内容代码如下
import requests
from lxml import etree# 请求头
headers {User-Agent: ...,Cookie: ...,Host: www.365kk.cc,Connection: keep-alive
}# 小说主页
main_url http://www.365kk.cc/1/1053/
# 使用get方法请求网页
main_resp requests.get(main_url, headersheaders)
# 将网页内容按utf-8规范解码为文本形式
main_text main_resp.content.decode(utf-8)# 将文本内容创建为可解析元素
main_html etree.HTML(main_text)# 依次获取书籍的标题、作者、最近更新时间
# main_html.xpath返回的是列表因此需要加一个[0]来表示列表中的首个元素
# /text() 表示获取文本
bookTitle main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/h1/text())[0]
author main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[1]/text())[0]
update main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[5]/text())[0]
introduction main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[2]/text())[0]
# 输出结果以验证
print(bookTitle)
print(author)
print(update)
print(introduction)输出结果如下
至此使用基本的网页请求get方法获取目标页面中的特定内容结束接下来就是正文解析了 go go go 正文爬取与解析
开始爬取正文。首先尝试获取单个页面的数据再尝试设计一个循环依次获取所有正文数据
单个页面数据获取
打开第一章获取章节标题和正文的XPath路径如下
书名//*[idcontainer]/div/div/div[2]/h1
内容//*[idcontent]按照与上文一致的方法请求并解析网页内容代码如下 注意到在用这个xpath路径的时候我们是只要里面的文字部分所以要多加一个/text()
import requests
from lxml import etree# 请求头
headers {User-Agent: ...,Cookie: ...,Host: www.365kk.cc,Connection: keep-alive
}# 当前页面链接
url http://www.365kk.cc/1/1053/10094192.html
resp requests.get(url, headers)
text resp.content.decode(utf-8)html etree.HTML(text)title html.xpath(//*[idcontainer]/div/div/div[2]/h1/text())[0]
contents html.xpath(//*[idcontent]/text())print(title)
for content in contents:print(content)可以看出我们成功获取了小说第一章第一页的标题和正文部分 接下来我们将它储存在一个txt文本文档中关于文件读取类型主要有并不全只是本代码用到的
w 清空原文档重新写入文档 open(filename, ‘w’)r 仅读取文档不改变其内容 open(filename, ‘r’)a 在原文档之后追加内容 open(filename, ‘a’)
文档命名为之前获取的书名 bookTitle.txt完整的代码如下
import requests
from lxml import etree# 请求头
headers {User-Agent: ...,Cookie: ...,Host: www.365kk.cc,Connection: keep-alive
}# 小说主页
main_url http://www.365kk.cc/1/1053/# 使用get方法请求网页
main_resp requests.get(main_url, headersheaders)# 将网页内容按utf-8规范解码为文本形式
main_text main_resp.content.decode(utf-8)# 将文本内容创建为可解析元素
main_html etree.HTML(main_text)bookTitle main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/h1/text())[0]
author main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[1]/text())[0]
update main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[5]/text())[0]
introduction main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[2]/text())[0]# 第一章页面链接
url http://www.365kk.cc/1/1053/10094192.htmlresp requests.get(url, headers)
text resp.content.decode(utf-8)
html etree.HTML(text)
title html.xpath(//*[idcontainer]/div/div/div[2]/h1/text())[0]
contents html.xpath(//*[idcontent]/text())with open(bookTitle .txt, w, encodingutf-8) as f:f.write(title)for content in contents:f.write(content)# 在储存文件时每储存一段就写入两个换行符 \n避免大段文字堆积使格式更便于阅读f.write(\n\n)f.close()运行结束后可以看到在代码文件的同路径中已经生成了一个文本文档。至此我们已经完成了单个页面的数据爬取和存储接下来只要设计循环实现顺序爬取所有页面即可。
爬取所有页面
我们注意到正文的每个页面底部都有一个按钮下一页其在网页中的结构为 在XPath路径的末尾添加 href 用于获取属性 href 的值
//*[idcontainer]/div/div/div[2]/div[3]/a[3]/href注意到如果一章结束下一页和下一章的链接就会有些差别 观察不同页面的链接可以看出前缀是一致的区别仅在后缀上比如第一章第一页和第一章第二页的链接分别为
http://www.365kk.cc/1/1053/10094192.html
http://www.365kk.cc/1/1053/10094192_2.html因此我们只需要获取下一页的链接后缀再与前缀拼接即可获得完整的访问链接。代码如下
# 获取下一页链接的函数
def next_url(next_url_element):nxturl http://www.365kk.cc/1/1053/# rfind(/) 获取最后一个/字符的索引index next_url_element.rfind(/) 1nxturl next_url_element[index:]return nxturlurl1 /1/1053/10094192_2.html
url2 10094193.htmlprint(next_url(url1))
print(next_url(url2))
在爬取某一页面的内容后我们获取下一页的链接并请求该链接指向的网页重复这一过程直到全部爬取完毕为止即可实现正文的爬取。 在这一过程中需要注意的问题有
某一章节的内容可能分布在多个页面中每个页面的章节标题是一致的这一标题只需存储一次 请求网页内容的频率不宜过高频繁地使用同一IP地址请求网页会触发站点的反爬虫机制禁止你的IP继续访问网站 爬取一次全文耗时较长为了便于测试我们需要先尝试爬取少量内容代码调试完成后再爬取全文 爬取的起点为第一章第一页爬取的终点可以自行设置 按照上述思想爬取前4个页面作为测试完整的代码如下
import requests
from lxml import etree
import time
import random# 获取下一页链接的函数
def next_url(next_url_element):nxturl http://www.365kk.cc/1/1053/# rfind(/) 获取最后一个/字符的索引index next_url_element.rfind(/) 1nxturl next_url_element[index:]return nxturl# 请求头需要添加你的浏览器信息才可以运行
headers {User-Agent: ...,Cookie: ...,Host: www.365kk.cc,Connection: keep-alive
}# 小说主页
main_url http://www.365kk.cc/1/1053/# 使用get方法请求网页
main_resp requests.get(main_url, headersheaders)# 将网页内容按utf-8规范解码为文本形式
main_text main_resp.content.decode(utf-8)# 将文本内容创建为可解析元素
main_html etree.HTML(main_text)bookTitle main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/h1/text())[0]
author main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[1]/text())[0]
update main_html.xpath(/html/body/div[4]/div[1]/div/div/div[2]/div[1]/div/p[5]/text())[0]# 调试期间仅爬取4个页面
maxPages 4
cnt 0
# 记录上一章节的标题
lastTitle # 爬取起点
url http://www.365kk.cc/1/1053/10094192.html
# 爬取终点
endurl http://www.365kk.cc/1/1053/10094194.htmlwhile url ! endurl:cnt 1 # 记录当前爬取的页面if cnt maxPages:break # 当爬取的页面数超过maxPages时停止resp requests.get(url, headers)text resp.content.decode(utf-8)html etree.HTML(text)title html.xpath(//*[classtitle]/text())[0]contents html.xpath(//*[idcontent]/text())# 输出爬取进度信息print(cnt: {}, title {}, url {}.format(cnt, title, url))with open(bookTitle .txt, a, encodingutf-8) as f:if title ! lastTitle: # 章节标题改变f.write(title) # 写入新的章节标题lastTitle title # 更新章节标题for content in contents:f.write(content)f.write(\n\n)f.close()# 获取下一页按钮指向的链接next_url_element html.xpath(//*[classsection-opt m-bottom-opt]/a[3]/href)[0]# 传入函数next_url得到下一页链接url next_url(next_url_element)sleepTime random.randint(2, 5) # 产生一个2~5之间的随机数time.sleep(sleepTime) # 暂停2~5之间随机的秒数print(complete!)运行结果如下
数据清洗
观察我们得到的文本文档可以发现如下问题
缺乏书籍信息如之前获取的书名、作者、最后更新时间切换页面时尤其是同一章节的不同页面之间空行过多每章节第一段缩进与其他段落不一致不同章节之间缺乏显眼的分隔符
为了解决这些问题我们编写一个函数 clean_data() 来实现数据清洗清洗后的文档中每段段首无缩进段与段之间仅空一行不同章节之间插入20个字符 - 用以区分问题得以解决。 完整代码需要自取哦 小说爬虫