近来闲的无聊,天天逛CSDN看到python多火热多火热,就自己根据教程学习爬虫,参考了好几个博文,忘了地址是啥就不贴出来了
开发工具:PcCharm
开发环境:Python3.8
这次爬取的小说网站是:http://www.xiaoshuo240.cn/cbxs240/1230/ ,因为网页结构简单好爬取!!话不多说上代码!!
(1).先观察一下页面结构,我们需要的是 a标签里的href链接,但是这里的链接不全,需要拼接上网站的域名
查找连接的正则可以这么写 r"<dd><a href='(.*?)'>(.*?)</a></dd>" ; .*?代表匹配所有;(.*?)加上括号代表这个值是我们需要的会出现在结果集中
写法:
# 正则
charpet_reg = r"<dd><a href='(.*?)'>(.*?)</a></dd>"
#编译一下执行更快
charpet_reg = re.compile(charpet_reg)
#findall会匹配到页面中所有符合正则的内容
urls = re.findall(charpet_reg,charpet_html)
再来看看每个章节的正文,他们都是包在<div id="content"></div>中,文中有许多<br>换行,所以正则要这么写
r'<br/>([\s\S]*?)</div>' 其中 [\s\S]代表换行
话不多说上代码,可以直接运行的
import urllib.request
import re
#Reptile.Util 是我自己写的一个工具包
import Reptile.Util
import time
def getContent():
# hearders是为了伪装自己,假装成浏览器去访问页面,可以降低被封ip的几率
headers = {'User-Agent': 'User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0'}
#这是本次爬取得目标
url = "http://www.xiaoshuo240.cn/cbxs240/1230/";
charpet_html = urllib.request.Request(url,headers=headers);
charpet_html = urllib.request.urlopen(charpet_html).read()
#对页面的内容进行转码,不然是乱码
charpet_html = charpet_html.decode('utf-8','ignore')
# 正则
charpet_reg = r"<dd><a href='(.*?)'>(.*?)</a></dd>"
#re.compile编译一下 执行快
charpet_reg = re.compile(charpet_reg)
#re.findall就查找到我们需要的内容了
urls = re.findall(charpet_reg,charpet_html)
#查看工作日志 看上次下载到第几条了
file_content = Reptile.Util.getWorkLog()
if file_content != '':
print('上次下载到:',file_content)
x = 0
y = 0
for url in urls:
novel_url = url[0]
#从href取出的url不能直接用,需要拼接上笔趣阁的域名
novel_url = 'http://www.xiaoshuo240.cn%s'%novel_url
#把英文的:和英文的?替换成中文的了,因为之前碰到报错了
novel_name = url[1].replace(':', ':').replace('?', '?')
if y == 0 and x == 0 :
#如果日志是空的就进行章节判断
if file_content == '':
# 因为笔书阁会把最近更新的章节放到前面,所以要过滤一下,从第一章开始爬取
if novel_url[-7::] != '/1.html' and x == 0:
continue
else:
x=1
else:
#如果日志不是空的,就要判断上次爬到哪个章节,接着爬取
if novel_url == file_content:
y = 1
continue
else:
continue
print('tite:', novel_name, ';address:', novel_url)
#获取每个章节的页面
novel_html = urllib.request.Request(novel_url,headers=headers)
novel_html = urllib.request.urlopen(novel_html).read()
novel_html = novel_html.decode('utf-8','ignore')
# 正则 文章中很多换行符 要使用[\s\S]。([\s\S]*?)这里获取到的就是正文了
novel_reg = re.compile(r'<br/>([\s\S]*?)</div>')
novels = re.findall(novel_reg,novel_html)
for novel in novels:
#把正文里面的空格换行给替换掉
novel = novel.replace(' ','').replace('<br/>','\n\t').replace('<br />','\n\t').replace('<p>笔趣阁(m.xiaoshuo240.cn)希望你喜欢书迷们第一时间分享的尘骨最新章节内容,如果有错误内容和字体欢迎点击章节报错!喜欢请收藏我们官网:m.xiaoshuo240.cn</p>','')
novel_save = open('尘骨/%s.txt'%novel_name,'w')
novel_save.write(novel)
#记录本次执行到哪一章节
Reptile.Util.saveWorkLog(novel_url)
#休息3秒 访问太频繁会被封ip的
time.sleep(3)
novel_save.close()
getContent()
还有一个简单的工具类
import os
# 判断文件路径是否存在,不存在则创建
def checkPath(path):
isExists = os.path.exists(path)
if not isExists:
os.makedirs(path)
# 保存工作日志
def saveWorkLog(workLog):
checkPath('尘骨')
file = open('尘骨/log.txt','w+')
# 定位到文件开头
file.seek(0,0)
#清空文件
file.truncate()
file.write(workLog)
file.close()
# 获取工作日志
def getWorkLog():
isExists = os.path.exists('尘骨/log.txt')
if True == isExists:
file = open('尘骨/log.txt','r')
file_content = file.read()
file.close()
return file_content
else:
return ''
需要注意的就是我这两个文件都是在项目下的Reptile文件下,所以引入Util的时候,写的是 import Reptile.Util,大家根据自己的路径自行修改!!