书包网小说多线程爬虫[通俗易懂]

书包网小说多线程爬虫[通俗易懂]书包网是个很好的小说网站,提供了小说txt下载,并且网站后端高并发,不用担心随便抓一下把网站抓崩了既然如此,何不拿来练手爬虫项目呢。直接上代码把,此多线程爬虫支持爬取各种这样类似的网站,关键需要网站支持高并发,否则分分钟崩了。毕竟5分钟一本18mb的小说,属于超级快的那种了fromlxmlimportetreeimportrequestsfromthreadi…

大家好,又见面了,我是你们的朋友全栈君。

书包网是个很好的小说网站,提供了小说txt下载,并且网站后端高并发,不用担心随便抓一下把网站抓崩了

既然如此,何不拿来练手爬虫项目呢。

 

直接上代码把,此多线程爬虫支持爬取各种这样类似的网站,关键需要网站支持高并发,否则分分钟崩了。

毕竟5分钟一本18mb的小说,属于超级快的那种了

from lxml import etree
import requests
from threading import Thread,enumerate
import os
from time import sleep,time

headers={
# ':authority':'www.bookbao8.com',
# ':method': 'GET',
# ':path': '/book/201506/04/id_XNDMyMjA1.html',
# ':scheme': 'https',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'max-age=0',
'cookie': 'Hm_lvt_79d6c18dfed73a9524dc37b056df45ec=1577182135; Hm_lpvt_79d6c18dfed73a9524dc37b056df45ec=1577182135; Hm_lvt_9e424f40a62d01a6b9036c7d25ce9a05=1577182142; trustedsite_visit=1; bk_ad=2; __cm_warden_uid=840a745a752905060cd14982b4bbc922coo; __cm_warden_upi=MTE5LjQuMjI4LjE1Nw%3D%3D; Hm_lpvt_9e424f40a62d01a6b9036c7d25ce9a05=1577185720',
'referer': 'https://www.bookbao8.com/book/201506/04/id_XNDMyMjA1.html',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}

def thread_it(func,*args):
    t = Thread(target=func,args=args)
    t.setDaemon(True)
    t.start()

def getAll(url = "https://www.bookbao8.com/book/201506/04/id_XNDMyMjA1.html"):
    r = requests.get(url,headers=headers)
    print(r.text)
    if r.status_code == 200:
        r.encoding = r.apparent_encoding
        ret = r.text
        page_source = etree.HTML(ret)
        name = page_source.xpath('//*[@id="info"]/h1/text()')
        author = page_source.xpath('//*[@id="info"]/p[1]/a/text()')
        novel_type = page_source.xpath('//*[@id="info"]/p[2]/a/text()')
        title = page_source.xpath('/html/body/div[7]/ul/li/a/text()')
        link = page_source.xpath('/html/body/div[7]/ul/li/a/@href')
        link = map(lambda x: 'https://www.bookbao8.com'+x, link)  #向列表中每个元素都加入前缀
        novel_list = list(zip(title,link))  #将两个列表用zip打包成新的zip对象并转为列表对象
        if len(novel_list) > 0:
            return name[0], author[0], novel_type[0], novel_list
        else:
            return None,None,None,None

def getOne(link=('第0001章 绝地中走出的少年', 'https://www.bookbao8.com/views/201506/04/id_XNDMyMjA1_1.html')):
    r = requests.get(link[1], headers=headers)
    if r.status_code == 200:
        r.encoding = r.apparent_encoding
        ret = r.text
        page_source = etree.HTML(ret)
        node_title = link[0]
        node_content = page_source.xpath('//*[@id="contents"]/text()')
        node_content = "".join(node_content).replace("\n \xa0 \xa0","")
        if len(node_title) > 0:
            return node_title, node_content
        else:
            return None, None
def writeOne(title,content):
    txt = "\t\t"+title+"\n"+content+"\n\n"
    return txt
def runApp(novel_list,name,t1,cwd=''):
    article_num = len(novel_list)
    xc_num = article_num//20+1
    print(f"待开启线程数量为{xc_num}")

    def inter(link,f,i):
        try:
            title, content = getOne(link)
            txt = writeOne(title, content)
            f.write(txt)
            print(f"\r线程{i}正在写入 {title}", end="")
        except Exception as e:
            print("\n爬得太快被拒绝连接,等1s递归继续")
            sleep(1)
            inter(link,f,i)

    def inner(name,i,begin,end,cwd):
        f = open(f"{cwd}downloads/{name}/{i}.txt", mode='w+', encoding='utf-8')
        for link in novel_list[begin:end]:
            inter(link, f,i)
            if link == novel_list[end - 1]:
                print(f"\n线程{i}执行完毕")
                print(f"\n剩余线程数量{len(enumerate())}")
                base_xc = 2 if not cwd else 4
                if len(enumerate()) <= base_xc:
                    print(enumerate())
                    print("\n全本下载完毕")
                    t2 = time()
                    print(f"\n本次下载小说总共耗时{round(t2 - t1)}s")
                    hebing(f"{cwd}downloads/{name}")

        f.close()

    for i in range(1,xc_num+1):
        begin = 20*(i-1)
        end = 20*i if i != xc_num else article_num
        if i == xc_num:
            print(f"\n全部线程开启完毕")
        thread_it(inner,name,i,begin,end,cwd)
        sleep(0.5)

def paixuRule(elem):
    return int(elem.split(".")[0])

def hebing(path):
    dirs = os.listdir(path)
    dirs.sort(key=paixuRule, reverse=False)
    f = open(path+".txt",mode='w+',encoding='utf-8')
    for file in dirs:
        with open(path+"/"+file,mode="r",encoding="utf-8") as f1:
            f.write(f1.read())
    f.close()
    print("小说合并完成")

if __name__ == '__main__':
    t1 = time()
    name, _, _, novel_list = getAll(url="https://www.bookbao8.com/book/201506/04/id_XNDMyMjA1.html")
    print(name)
    if not os.path.exists("downloads/" + name):
        os.mkdir("downloads/" + name)
    runApp(novel_list, name, t1)
    while True:
        pass

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148031.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 常见的ARM集成开发环境

    常见的ARM集成开发环境1.ARMSDT:是ARM公司为方便用户在ARM芯片上进行应用软件开发而推出的一整套开发工具。到ARMSDT2.5.1,ARM宣布推出ARMADS1.0取代了ARMSDT,不再对ARMSDT进行维护。ARMSDT支持的ARM处理器最高到包括ARM9在内的所有ARM处理器。配合Angel驻留程序和JTAG仿真器,用户使用可方便的使用ARMSDT进行应用程序的开发。2.ARM

    2022年5月18日
    38
  • cs是一种重要的网络计算机模式_cs在计算机代表啥

    cs是一种重要的网络计算机模式_cs在计算机代表啥开始之前,先大概说一下吧。计算机网络研究的是理论,讲究的是网络过程中的连接方式,还有协议制定的原因,为什么这么指定,它不是一个简单的敲代码,做码农就好了的,关键是在于创新,先是理解协议为什么这么制定,要怎么样才可以更加好的指定出下一个协议,怎么才可以做出一个好的东西。什么是cscs即:client/server,是服务器客户端结构。是一种“一对多”的模式,一台服务器,处理多个客户端发来的请求,……

    2022年9月2日
    7
  • SQL EXITS用法

    SQL EXITS用法比如在Northwind数据库中有一个查询为SELECTc.CustomerId,CompanyNameFROMCustomerscWHEREEXISTS(SELECTOrderIDFROMOrdersoWHEREo.CustomerID=c.CustomerID) 这里面的EXISTS是如何运作呢?子查询返回的是OrderId字段,可是外面的查询要找的是Cu

    2025年6月24日
    3
  • 首次使用空气炸锅需要干烧10分钟_pycharm第一次打开

    首次使用空气炸锅需要干烧10分钟_pycharm第一次打开1、PyCharm的下载下载地址:https://www.jetbrains.com/pycharm/版本:PyCharmProfessionalEdition收费版本:PyCharmCommunityEdition免费2、首次新建项目打开安装好的PyCharm首次打开会出现本界面,点击CreateNewProject项目命名及选择Python解释…

    2022年8月27日
    5
  • eclipse adt bundle不显示Android SDK菜单

    eclipse adt bundle不显示Android SDK菜单我把adtbundle拷贝到装有jdk1.5的电脑时,Eclipse死活不显示SDK的相关菜单。原因是jdk版本太低,只有1.6以上才会有。。eclipse.ini里限制jdk版本原来是有意的。安装了jdk1.6后,就能定制GUI了。eclipse中的window→Customize Perspective→Command Groups availability→Av

    2025年7月26日
    5
  • Android ListView几种Adapter用法简介「建议收藏」

    Android ListView几种Adapter用法简介「建议收藏」ArrayAdapter适合非常简单的数据显示,很方便,很简单。SimpleAdapter可以自定义Item布局,用于显示交简单的布局及控件,但布局内的控件如按钮等无法获取到焦点,当然也就无法获取到他们的点击事件。SimpleCursorAdapter与SimpleAdapter相似,只是他的数据源是Cursor类型而已。BaseAdpter子类最常用的ListView数据适配器,通过继承BaseAdpter可以较灵活的实现数据的绑定,同时通过使用View

    2022年7月22日
    9

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号