1 解析章节列表
1 设定章节列表所在页面url
2 检查列表所在的元素id或类名
3 取得所有列表a链接并写入列表中
带有分页的章节列表 - 有规律可循时
根据章节链接的规律来自定义列表,就不再解析列表页的请求了
from lxml import etree
import requests
# 网页访问
header = {
'User-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 Edg/100.0.1185.29'
}
mSession = requests.session()
aList = [] # 定义章节列表变量
def getList(url): # 根据章节列表url获取所有章节a链接
global aList # 声明全局使用变量
try:
mResponse = mSession.get(url, headers=header)
if (mResponse.ok):
# 格式化页面源码
mHtml = etree.HTML(mResponse.content)
# xpath 获取目标节点内容,返回结果为列表形式,通过索引进行访问
mTables = mHtml.xpath('//*[@id="list"]')
if (len(mTables) <= 0):
print("找不到章节列表")
return
mTable = mTables[0]
aList = mTable.xpath('.//a') # 取得所有 a 链接
except Exception as e:
print("获取章节列表失败:\n" + e)
2 循环列表
解析 a 链接
result = ""
baseUrl = "https://xxx.com"
getList("https://xxx.com/5/5552/1/")
for a in aList:
href = baseUrl + a.xpath('@href')[0] # 取得 a 链接的 URL
print(href) # 打印到控制台以便查看进行到第几章
txt = a.xpath('text()')[0] # 取得 a 链接的文本内容,一般为章节标题
print(txt) # 打印到控制台以便查看进行到第几章
# break # 通过首页来分析是否解析成功,解析成功后即可注释掉
# Sub
result += txt + "\n" # 将章节标题写入到结果中
getDetail(href=href) # 根据章节链接获取章节内容
# print(result) # 打印解析的单个章节内容分析是否成功
# break # 如果解析成功,则注释掉使其跑循环
如果列表中是自定义好的a链接列表,则直接执行sub块内容即可
setList()
for a in aList:
getDetail(href=a) # 根据章节链接获取章节内容
是否存在需要跳过的章节
根据需要进行添加启用
j = 1
for a in aList:
if (j <= 15):
j = j + 1
continue
写内容
result = ""
i = 1
def writeContent(str):
with open("temp.txt", 'a', encoding='utf-8') as f: # 以append的模式累加内容
f.write(str)
for a in aList:
# Sub
result += txt + "\n" # 将章节标题写入到结果中
getDetail(href=href) # 根据章节链接获取章节内容
''' 每 10 章写入一次文本 '''
if (i == 10):
writeContent(result)
i = 1
result = ""
continue
i = i + 1
''' 写入剩余文本 '''
if (result != ""):
writeContent(result)
3 获取单个章节内容
1 解析文章链接
def getDetail(href): # 参数传入待解析的文章链接
# Sub
try:
mResponse = mSession.get(href, headers=header)
if(mResponse.ok):
mHtml = etree.HTML(mResponse.content)
mContents = mHtml.xpath('//div[@id="chaptercontent"]') # 分析内容块,获取合适的path路径
if (len(mContents) <= 0):
print("找不到章节内容")
return # 如果解析不成功,则代表找不到内容块,可能链接有误,跳出
mContent = mContents[0]
getContent_div(content=mContent)
checkNextPage(html=mHtml)
except Exception as e:
print(e)
2 解析文章内容
def getContent_div(content): # 内容直接存放在 div 中
global result # 声明result是全局变量,以便在内部修改,外部调用
txts = content.xpath("./text()")
for txt in txts:
result += txt + "\n"
def getContent_p(content): # 正文内容存放于 p 标签中
global result # 声明result是全局变量,以便在内部修改,外部调用
pList = content.xpath('.//p')
for p in pList:
result += p.xpath('text()')[0]
def getContent_divAll(content): # 获取整个 div 内容
global result # 声明result是全局变量,以便在内部修改,外部调用
txt = etree.tounicode(mTable)
# # 替换掉 html 标签 import re
# txt = re.sub('(<p.*?>)|(</p>)|( )|(<strong.*?>)|(</strong>)', "", txt)
result += txt + "\n"
检查是否包含下一页
def checkNextPage(html):
''' 检查是否包含下一页 '''
mNextPages = html.xpath('//div[@class="section-opt m-bottom-opt"]')
if (len(mNextPages) <= 0):
return # 不包含下一页标签,直接跳出
mNextPage = mNextPages[0]
aAll = mNextPage.xpath('.//a')
for a in aAll:
txt = a.xpath('text()')[0]
if (txt == "下一页"):
nextPage = a.xpath('@href')[0]
getDetail(href=nextPage)
完整模板代码
from lxml import etree
import requests
# 网页访问
header = {
'User-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 Edg/100.0.1185.29'
}
mSession = requests.session()
aList = [] # 定义章节列表变量
result = "" # 定义解析到的章节内容
def getList(url): # 根据章节列表url获取所有章节a链接
global aList # 声明全局使用变量
try:
mResponse = mSession.get(url, headers=header)
if (mResponse.ok):
# 格式化页面源码
mHtml = etree.HTML(mResponse.content)
# xpath 获取目标节点内容,返回结果为列表形式,通过索引进行访问
mTables = mHtml.xpath('//*[@id="list"]')
if (len(mTables) <= 0):
print("找不到章节列表")
return
mTable = mTables[0]
aList = mTable.xpath('.//a') # 取得所有 a 链接
except Exception as e:
print("获取章节列表失败:\n" + e)
def writeContent(str):
with open("temp.txt", 'a', encoding='utf-8') as f: # 以append的模式累加内容
f.write(str)
def getContent_div(content): # 内容直接存放在 div 中
global result # 声明result是全局变量,以便在内部修改,外部调用
txts = content.xpath("./text()")
for txt in txts:
result += txt + "\n"
def getContent_p(content): # 正文内容存放于 p 标签中
global result # 声明result是全局变量,以便在内部修改,外部调用
pList = content.xpath('.//p')
for p in pList:
result += p.xpath('text()')[0]
def getContent_divAll(content): # 获取整个 div 内容
global result # 声明result是全局变量,以便在内部修改,外部调用
txt = etree.tounicode(content)
result += txt + "\n"
def getDetail(href): # 参数传入待解析的文章链接
# Sub
try:
mResponse = mSession.get(href, headers=header)
if (mResponse.ok):
mHtml = etree.HTML(mResponse.content)
mContents = mHtml.xpath(
'//div[@id="chaptercontent"]') # 分析内容块,获取合适的path路径
if (len(mContents) <= 0):
print("找不到章节内容")
return # 如果解析不成功,则代表找不到内容块,可能链接有误,跳出
mContent = mContents[0]
getContent_div(content=mContent)
checkNextPage(html=mHtml)
except Exception as e:
print(e)
def checkNextPage(html):
''' 检查是否包含下一页 '''
mNextPages = html.xpath('//div[@class="section-opt m-bottom-opt"]')
if (len(mNextPages) <= 0):
return # 不包含下一页标签,直接跳出
mNextPage = mNextPages[0]
aAll = mNextPage.xpath('.//a')
for a in aAll:
txt = a.xpath('text()')[0]
if (txt == "下一页"):
nextPage = a.xpath('@href')[0]
getDetail(href=nextPage)
#################################################################################
# 自定义章节列表时使用
# setList()
# for a in aList:
# getDetail(a) # 根据章节链接获取章节内容
baseUrl = "https://xxx.com"
getList("https://xxx.com/5/5552/1/")
i = 1 # 分批写入文件
j = 1 # 跳过章节的起始页
for a in aList:
# # 跳过前面章节
# if (j <= 15):
# j = j + 1
# continue
# 解析 a 链接
href = baseUrl + a.xpath('@href')[0] # 取得 a 链接的 URL
print(href) # 打印到控制台以便查看进行到第几章
txt = a.xpath('text()')[0] # 取得 a 链接的文本内容,一般为章节标题
print(txt) # 打印到控制台以便查看进行到第几章
# break # 通过首页来分析是否解析成功,解析成功后即可注释掉
# Sub
result += txt + "\n" # 将章节标题写入到结果中
getDetail(href) # 根据章节链接获取章节内容
# print(result) # 打印解析的单个章节内容分析是否成功
# break # 如果解析成功,则注释掉使其跑循环
''' 每 10 章写入一次文本 '''
if (i == 10):
writeContent(result)
i = 1
result = ""
continue
i = i + 1
''' 写入剩余文本 '''
if (result != ""):
writeContent(result)