赞
踩
本篇博客介绍一下通过Python爬取小说的一个案例:
首先我们选定一个网站的小说,这里我们选择的目标小说域名:http://m.ppxs.net/
我们的目标书籍是:《规则怪谈,欢迎来到甜蜜的家》
(备注:现在需要安装有requests模块)
首先打开小说的首页:
观察小说的首页
步骤:鼠标右键 -> 检查
网页的源代码
获取自己浏览器的User-Agent和Cookie属性
其中的User-Agent和Cookie属性则填写上自己浏览器的内容
至于Host填写的是网站的域名,Connection是选择一种策略模式,在此不细讲
import requests
headers = {
'User-Agent': '......',
'Cookie': '......',
'Host': 'm.ppxs.net',
'Connection': 'keep-alive'
}
第一阶段剩下的代码如下:
# 小说主页的网站,用于获取书籍名称
main_url = "https://www.a1x.net/book/69664"
# 用get方法获取网页元素
main_resp = requests.get(main_url, headers=headers)
# 将网页元素按utf-8规范解码为文本形式
main_text = main_resp.content.decode('utf-8')
# 检查是否成功获取网站元素
print(main_text)
从现在开始,我们将使用lxml模块,请自行下载哦~
按照上图的步骤,复制指定内容的XPath
至于这里的XPath,你可以理解为信息的地址,you can try to 粘贴到一个文本框里,你会发现复制的是一串节点:/html/head/title
代码如下:
from lxml import etree
.................第一阶段代码...................
# 将文本内容创建为可解析元素
main_html = etree.HTML(main_text)
# main_html.xpath返回的是列表,这里用[0]来输出不带括号的纯净的元素
# 学习者可以去掉[0]来对比一下输出结果的差异
# 这里在/html/head/title后面添加了/text()指令,意思是获取文本,后同
bookTitle = main_html.xpath('/html/head/title/text()')[0]
# 输出结果以验证
print(bookTitle)
通过以上代码,就可以使用xpath方法获取书籍的名称了
import requests
from lxml import etree
# # 网络请求头,这里相当于模拟浏览器进行访问,不然绝大多数的网站拒绝你的访问
# # 这里的几种属性,User-Agent和Cookie是通过网页检查源代码来找出来的
headers = {
'User-Agent': '......',
'Cookie': '......',
'Host': 'm.ppxs.net',
'Connection': 'keep-alive'
}
# 小说主页网站
main_url = "https://www.a1x.net/book/69664"
# 使用get方法请求网页
main_resp = requests.get(main_url, headers=headers)
# 将网页内容按utf-8规范解码为文本形式
main_text = main_resp.content.decode('utf-8')
# 将文本内容创建为可解析元素
main_html = etree.HTML(main_text)
# main_html.xpath返回的是列表,因此需要加一个[0]来表示列表中的首个元素
bookTitle = main_html.xpath('/html/head/title/text()')[0]
# 输出结果以验证
print(bookTitle)
现在我们进入第三阶段,开始爬取正文部分了!!点击进入小说网站的第一章
代码如下:
import requests
from lxml import etree
# 请求头
headers = {
'User-Agent': '......',
'Cookie': '......',
'Host': 'm.ppxs.net',
'Connection': 'keep-alive'
}
# 更改网络地址为当前页面
url = 'http://m.ppxs.net/read/63769/1177002.html'
# 使用get方法请求网页
resp = requests.get(url, headers=headers)
# 将网页内容按utf-8规范解码为文本形式
text = resp.content.decode('utf-8')
# 将文本内容创建为可解析元素,获取章节名称
html = etree.HTML(text)
title = html.xpath('/html/body/div[3]/text()')[0]
contents = html.xpath('//*[@id="nr1"]/p[1]/text()')[0]
# 检查是否获取正确
print(title)
print(contents)
最后输出的效果如上
此处,我自己在写代码的时候发现一个重要的问题:这些正文都是分割成一段一段一行一行的了,我不可能给每一行都弄个Xpath出来
正文都是分割好了的
我尝试用正文的上方<div id=''nr1''>的XPath地址,却发现行不通,找不到正文(笔者能力有限对不起)
所以我没有多考虑,想到了课堂上教过的一种方法:正则表达式
我使用正则表达式对元素进行了匹配,具体原理请自行查阅资料学习哦~
(记得下载正则表达式re模块)
import requests
import re
from lxml import etree
# 浏览器请求头
headers = {
'User-Agent': '......',
'Cookie': '......',
'Host': 'm.ppxs.net',
'Connection': 'keep-alive'
}
# 小说主页,获取书籍名称
main_url = "http://m.ppxs.net/book/63769/"
main_resp = requests.get(main_url, headers=headers)
main_text = main_resp.content.decode('utf-8')
main_html = etree.HTML(main_text)
Title = main_html.xpath('//*[@id="content"]/div/div[1]/div[2]/p[1]/text()')[0]
print(Title)
# 正文页面链接,用XPath获取章节标题,用正则表达式获取章节正文
url = 'http://m.ppxs.net/read/63769/1177002.html'
resp = requests.get(url, headers)
text = resp.content.decode('utf-8')
html = etree.HTML(text)
title = html.xpath('/html/body/div[3]/text()')[0]
contents = re.findall('<p>(.*?)</p>', resp.text)
print(title)
print(contents)
# 创建并且把爬取到的东西写入文件,注意这里的策略是'a'而不能是'w'
# 否则后面每爬取新页面的正文时,就会覆盖原来已经爬取好的内容
# \n是用来换行的,保持页面美观整齐
with open(Title + '.txt', 'a', encoding='utf-8') as f:
f.write(title)
f.write('\n')
for content in contents:
f.write(content)
f.write('\n')
f.close()
实现效果如上图
我们现在需要写一个功能,让Python可以获取下一页的链接,然后自己翻页自动继续爬取
# 获取"下一页"按钮指向的链接
html = etree.HTML(text)
next_url_element = html.xpath('//*[@id="pt_next1"]/@href')[0]
但是这上面两行代码获取的网址缺少域名,比如下面这样的:
/read/63769/1177002_2.html
# 获取"下一页"按钮指向的链接
html = etree.HTML(text)
next_url_element = html.xpath('//*[@id="pt_next1"]/@href')[0]
print(next_url_element)
head = "http://m.ppxs.net"
new_url = head + next_url_element
因此咱们用time模块设置一下时间间隔,同时用random模块随机设定一下爬取的间隔时间,记得下载这两个模块哦~
import requests
from lxml import etree
import time
import random
import re
# 请求头,需要添加你的浏览器信息才可以运行
headers = {
'User-Agent': '......',
'Cookie': '......',
'Host': 'm.ppxs.net',
'Connection': 'keep-alive'
}
# 小说主页网址
main_url = "http://m.ppxs.net/book/63769/"
# 使用get方法请求网页
main_resp = requests.get(main_url, headers=headers)
# 将网页内容按utf-8规范解码为文本形式
main_text = main_resp.content.decode('utf-8')
# 将文本内容创建为可解析元素
main_html = etree.HTML(main_text)
Title = main_html.xpath('//*[@id="content"]/div/div[1]/div[2]/p[1]/text()')[0]
# 调试期间仅爬取六个页面
maxPages = 6
cnt = 0
# 爬取起点
url = 'http://m.ppxs.net/read/63769/1177002.html'
# 爬取终点
endurl = 'http://m.ppxs.net/read/63769/1177013.html'
while url != endurl:
cnt += 1 # 记录当前爬取的页面
if cnt > maxPages:
break # 当爬取的页面数cnt超过maxPages时停止
resp = requests.get(url, headers=headers)
text = resp.content.decode('utf-8')
html = etree.HTML(text)
title = html.xpath('/html/body/div[3]/text()')[0]
contents = re.findall('<p>(.*?)</p>', resp.text)
print(title)
print(contents)
with open(Title + '.txt', 'a', encoding='utf-8') as f:
f.write(title)
f.write('\n')
for content in contents:
f.write(content)
f.write('\n')
f.close()
# 获取"下一页"按钮指向的链接
html = etree.HTML(text)
next_url_element = html.xpath('//*[@id="pt_next1"]/@href')[0]
head = "http://m.ppxs.net"
new_url = head + next_url_element
# 传入函数next_url得到下一页链接
url = new_url
# 产生一个2~4之间的随机数
sleepTime = random.randint(2, 4)
# 暂停2~4之间随机的秒数
time.sleep(sleepTime)
print("爬取完毕")
实现的效果验证
爬取的txt文档
备注:
源代码基于文章:python爬虫实战——小说爬取_python爬取小说-CSDN博客
由笔者本人根据需求简化修改而来,原文并未使用正则表达式的方法
原文作者:Myster_KID
本文旨在传播Python爬虫知识,无任何收入,如有侵权请联系我删除
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。