python爬虫爬取网络小说

-------------------------------------支持正版小说,本文仅供技术交流----------------------------------------

因为以前喜欢看网络小说,就写了一只网络小说爬虫,放在这里以供记录。

这次爬取,选择的是大名鼎鼎的www.biquge.com

使用的技术路线呢?本次选用了速度较慢,同时比较基础的requests-bs4-re的技术路线。

大概的思路是:

1.输入要爬取的小说名字

2.请求搜索界面,利用bs4解析标签树,找到最吻合的小说。

3.进入小说目录页面,,获得各个章节的url

(因为网络小说大部分都有好几千章,放在同一个文件夹里影响阅读,所以还要按照第X篇再次进行划分,存放到不同的子目录下)

4.查看各个章节,在存储目录下是否存在?如果不存在,爬取该章节

5.进行文本清洗和排版,去掉广告、过多的空格,等等

6.保存,并且显示爬取进度(%)。

import time,os,traceback,random
import requests,re
from bs4 import BeautifulSoup
#define
Agent =['Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1'
        ,'Opera/9.27 (Windows NT 5.2; U; zh-cn)'
        ,'Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0'
        ]
def ProcName(name):#清洗目录名
    pat = r'[<|>|/|\|||:|"|*|?]+|(提示:已启用缓存技术,最新章节可能会延时显示,登录书架即可实时查看。)'
    pat = re.compile(pat)
    return pat.sub('',name)

def log(url):
    path = "\home\Rullec\log.txt"
    with open(path,'w') as f:
        f.write(str(url))
        f.close()

def GetHtmlText(url):#获得HTML页面内容 此处可以增加proxies代理服务器,只不过目前还没有
    try:
        r = requests.get(url,headers={'User-Agent':Agent[random.randint(0,Agent.__len__()-1)]},timeout = 20)
        r.raise_for_status()
        r.encoding = 'utf-8'
        return r.text
    except requests.exceptions.ReadTimeout|requests.exceptions.ConnectTimeout:
        traceback.print_exc() #如果出现超时错误
        #log(url)
        waittime = random.randint(10, 20)
        print("出现超时错误!等待"+str(waittime)+"秒!\n")
        time.sleep(waittime)
        return None

def FindIndex(name):#获得目标小说目录页
    url = "http://zhannei.baidu.com/cse/search?&s=287293036948159515&q="+str(name)+"&click="+str(random.randint(1,3))+'&nsid='
    text = GetHtmlText(url)
    if text==None:
        print("文本为空,无法解析")
        return None
    soup = BeautifulSoup(text.encode('utf-8'),'html.parser')
    list = soup.find_all(name = 'a',attrs = {"cpos" :"title","title":name})#一个list
    url = []
    for i in list:
        url.append(i["href"])
    return url

def ProcTxt(text):
    text = text[9:]
    pat = r'    '
    pat = re.compile(pat)
    return pat.sub("\n",text)

def Write(storpath,tag):#进行小说的存储
    if None==tag:
        print('小说写入失败,原因是小说最后一层超链接无法获取')
        return 1
    a = tag.a#标签的属性使用tag['title']来获得,标签下的搜索使用tag.children来实现
    storpath += "/"+ProcName(a.string)+".txt"
    while os.path.exists(storpath):
        if time.time()-os.path.getctime(storpath)<100 :
            newpath = storpath.split('.')
            storpath = newpath[0] + "#.txt"
        else:
            return 1
    url = 'http://www.biquge.com/'+a['href']
    text = GetHtmlText(url)
    if text==None or len(text)==0:
        print("最后一层文本获取失败!")
        return 1
    soup = BeautifulSoup(text.encode('utf-8'),'html5lib')
    novel = soup.find_all("div",attrs={"id":"content"})
    text = novel[0].text
    #开始写入
    with open(storpath,'w',encoding='utf-8') as f:
        text = ProcTxt(str(text))
        f.write(text)
        f.close()
    return 0

def Spider(url,path):#爬取小说目录页
    text = ""
    #while len(text) or text==None:
    text = GetHtmlText(url)
    num = 0
    soup = BeautifulSoup(text,'html5lib')
    list = soup.find_all(["dd","dt"])
    nowpath = ""
    flag = 0
    for i in list:
        if i.name == "dt":
            nowpath = path+"/"+ProcName(i.string)
            if os.path.exists(nowpath):
                pass
            else:
                os.mkdir(nowpath)
        else:
            flag = Write(nowpath,i)
            num+=1
            if num%10==0 and (not flag):
                time.sleep(random.randint(3,10))#爬虫每爬几个就休眠
        print("\r当前进度: {:.2f}%".format(num * 100 / len(list)), end="")
    return ""

def main():#主函数
    name = ProcName(input("请输入要爬取的小说的名字:"))
    url = FindIndex(name)#爬取搜索结果,在其中查找目录页,并且返回
    if 0==len(url):
        print("查无此小说")
        exit()
    path = "E:\小说\\"
    #path = "\home\Rullec\小说\\"
    if os.path.exists(path):
        pass
    else:
        os.mkdir(path)
    path = path +name
    if os.path.exists(path):
        pass
    else:
        os.mkdir(path)
    Spider(url[0],path)
main()

这是最初最初的构想代码,接下来还有很多需要改善的地方,大概的想法是:
1.增加IP代理的过程,对抗反扒机制

2.支持模糊查询,支持输入作者姓名—>下载该作者所有小说

3.增强数据清洗,去除无意义的广告

4.改善目前混乱的架构

5.使用scrapy框架实现

晚安!

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值