python 爬虫-爬取小说网站-小白级

第一次编写爬虫网站。(感觉有点较凌乱)

各位大神,如果有更好的意见,欢迎指点建议。谢谢。

目前代码基本上能按照正常的思路扒取小说内容。

思路如下:首先进入小说网站首页---》然后选取要下载的系列----》然后开始下载当前系列的所有书本链接,并存放json----》然后读取json文件内的数据进行下载。

目前代码能够按照思路进行下载,但是下载速度太慢了 ,没有进行多线程下载(持续更新这部分功能)。
我反爬机制没做好,如果在同一个局域网,两台不同的电脑&不同的请求头,同时运行,会处罚到网站的反爬机制,导致页面返回出错。还需要优化。

在头文件处,添加浏览器本身的cookie信息,可以解决出错这个问题。

以下是效果图。

源码在文末。

#这是链接文件。

# -*- encoding=utf8 -*-

#zj为章节的意思

from bs4 import BeautifulSoup
import requests
import json          #存储书本链接文件
import pandas as pd  #清洗数据,去掉重复的链接需要用到
import os            #检查当前目录下是否有对应的文件需要用到

#导入这个urllib3 这个库是为了屏蔽报错信息
from requests.packages.urllib3.exceptions import InsecureRequestWarning


html_base = 'http://www.qu.la/'
HEADERS= {
          'User-Agent':'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36',
          'Referer': 'https://www.qu.la/book/68/',
          'Host': 'www.qu.la',
          'Cookie': '【这里添加自己的cookie信息】'}
xl = {}
xl_link = {}
zj_list_links = []       #收集书本的所有链接
zj_list_html_dict = {}   # total(int):小说总数   next_href:下一页的链接
storyinfo = {}           # 收集小说的书名、作者、简介、等信息

over_mark = True
over_mark1 = True
over_mark_getlinks = True

#下载正文 ,下载完成后打开下一章继续下载,直至到完成一本书的下载
def get_story(soup):
    #下载第几章
    storyinfo["第N章"] = soup.select(".reader-main .title")[0].text
    storyinfo["正文"] = soup.select(".container .content")[0].text  # 如果不加.text 就回出现<br/>符号。加上后就回只留下文本。
    storyinfo["下一页link"] = soup.select(".section-opt a")[2]['href']

#每本书的基本信息zjnum = -20
def story_info(soup):
    #小说名称
    storyinfo["书名"] = soup.select(".top h1")[0].text
    # 小说系列
    storyinfo["系列"] = soup.select(".xs-show")[0].text
    # 小说更新日期
    storyinfo["更新时间"] = soup.select(".fix p")[4].text
    # 小说作者l
    storyinfo["作者"] = soup.select(".fix p")[0].text
    #小说简介
    storyinfo["简介"] = soup.select(".info .desc.xs-hidden")[0].text
    #书本第一章
    storyinfo["第一章link"] = soup.select(".container .section-box li a")[-20]['href']

#收集小说总数,以及20本之后的下一页链接
def zj_list_html(soup):
    #当前系列中所有小说的总数
    total_story = soup.select(".pagination.pagination-mga .hd strong")[0].text
    #"最近更新小说页面的#下一页#"
    zj_list_nextpage = soup.select(".pagination.pagination-mga li a")[0]['href']
    zj_list_html_dict["书本总数"] = int(total_story)
    zj_list_html_dict["下一页link"] = zj_list_nextpage
    for i in range(20):
        zj_links = soup.select(".layout.layout2.layout-col2 .txt-list.txt-list-row5 li .s2 a")[i]['href']
        zj_list_links.append(zj_links)

#打开网页
def open_html(href):
    #randomnum = random.randrange(1, 35)
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
    res = requests.get(html_base + href,verify= False,headers=HEADERS)
    soup = BeautifulSoup(res.text, "lxml")
    return soup

#新建txt,并追加内容。可在这个方法里进行数据清洗,和小说排版等工作
def download_newfile(file_text,filename,zjname):
    #创建文件夹
    zj_file = open(filename+'.txt',"ab+")    #这里 ab+ 标记出了使用二进制打开txt
    # 数据清洗
    newfile = str(file_text)
    newfile = newfile.replace("章节错误,点此举报(免注册),举报后维护人员会在两分钟内校正章节内容,请耐心等待,并刷新页面。",'\n')#文本格式整理#文本格式整理
    newfile_encode = newfile.encode("utf-8")  #这里必须转换成UTF-8再写入txt  否则回报错
    zjname_encode = str(zjname).encode("utf-8")
    #数据写入
    zj_file.write(zjname_encode)
    zj_file.write(newfile_encode)
    zj_file.close()

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
res = requests.get(html_base,verify = False)
res.encoding = "utf-8"
soup = BeautifulSoup(res.text,"lxml")
#收集系列名称并写入dict(xl)
for i in range(1,7):
    xl[i] = soup.select(".nav li a")[i+1].text
#收集系列名称并写入dict(xl_link)
for i in range(1,7):
    xl_link[i] = soup.select(".nav li a")[i+1]['href']

# 显示选项,并选择需要下载的系列
print(xl)
num = input("Please input your choose:")

if __name__ == '__main__':

    if bool(num) == True:
        # 打开这个链接可以获取当前页面20本书的链接和下一页的链接
        zj_list_html(open_html(xl_link[int(num)]))
        # 检索目前路径数据库
        if os.path.exists('xl_all_links' + '_' + xl[int(num)] + '.json') == True :
            print("书本链接文件已存在,正在读取链接文件...")
            with open('xl_all_links' + '_' + xl[int(num)] + '.json','r') as f:
                zj_list_links = json.load(f)
            print(zj_list_links)
            alllinks = len(zj_list_links)
            print("书本总数:"+str(alllinks))

            while over_mark:
                for i in range(alllinks):
                    print("当前下载:第"+str(i+1)+"本")
                    # 从story_info获取第一章的链接并打开
                    story_info(open_html(zj_list_links[i]))
                    print(storyinfo["书名"])

                    over_mark1 = True
                    while over_mark1:
                        get_story(open_html(storyinfo["第一章link"]))
                        while zj_list_links[i] != storyinfo["下一页link"]:
                            download_newfile(storyinfo["正文"], storyinfo["书名"], storyinfo["第N章"])
                            try:
                                get_story(open_html(storyinfo["下一页link"]))
                                #当收集到最后一页的时候,返回就会出错,首先返回出错网页,再返回书本列表。这里检测到这个信息后,就表示已收集完成了。
                                #现在在头文件增加了cookie 后,这里已经大幅度减少报错了。
                                if storyinfo["下一页link"] == "javascript:void(0);":
                                    if 0==alllinks-1:
                                        print("当前书籍收集完成。")
                                        break
                                    storyinfo["下一页link"] = zj_list_links[i]
                            except:
                                print("这里出错了,出错内容:")
                                print(storyinfo["第N章"])
                                print("出错链接:"+storyinfo["下一页link"])
                                print("正重新尝试")
                                continue
                            over_mark1 = False
                            #print("当前章节链接:"+storyinfo["下一页link"])  #打印出当前章节链接
                            print("正在下载:"+ storyinfo["第N章"])   # 当前下载的章节
                            continue

                    alllinks = alllinks-1  #下载完成后,总链接 -1
        else:
            print("当前目录未发现链接文件,请先下载书本链接...")
            # 选中系列打开网址
            print("正在下载" + xl[int(num)] + "书本链接...")
            print("当前系列书本总数:"+str(zj_list_html_dict["书本总数"]))
            # 这里开始收集书本中的所有链接
            # 并开始清洗收集到的数据#使用pandas unique 进行清除重复值
            # 最终保存数据文件为json

            while over_mark_getlinks:
                getlinks = open_html(zj_list_html_dict["下一页link"])
                try:
                    zj_list_html_dict["下一页link"] = getlinks.select(".pagination.pagination-mga li a")[1]['href']
                    for i in range(20):
                        zj_links = getlinks.select(".layout.layout2.layout-col2 .txt-list.txt-list-row5 li .s2 a")[i]['href']
                        zj_list_links.append(zj_links)
                    print("已下载链接:"+str(len(zj_list_links)))
                except:
                    print("页面异常!停止收集,已收集:")
                    print(len(zj_list_links))
                    print(zj_list_html_dict["下一页link"])
                    print("收集完毕,正在清洗整理文件并保存....")
                    zj_list_links = pd.unique(zj_list_links)
                    print(len(zj_list_links))
                    with open('xl_all_links' + '_' + xl[int(num)] + '.json', 'w') as file:
                        json.dump(list(zj_list_links), file)
                    print("存储文件:" + 'xl_all_links' + '_' + xl[int(num)] + "-->保存完毕!")
                    print("下载完毕请重新运行软件。")
                    break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

危机时刻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值