|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 大马强 于 2021-8-2 20:09 编辑
写了一个小说的爬虫作为练手,想分享给各位鱼油和交流
网站:铅笔小说网
代码涉及模块
- from concurrent.futures import ThreadPoolExecutor #多线程
- import requests #网页请求
- from lxml import etree #网页处理,数据获取
- import re #获取数据
- import os #保存内容
复制代码
最近在看这部小说《灰与幻想的格林姆加尔》,所以就拿它来当本次目标了,选择作为起始mian_url
一、网页分析
【1】观察主页面,发现这个小说的所有章节都在这上面,拉到底部时没有动态刷新,可以猜测这是一个静态的
【2】点击右键,查看网页源代码,发现每一章的url和章节名字都在上面,不过要注意的是,url要经过一些处理才能使用,每一章的url要再加上前缀 https://www.23qb.net
【3】点击任意一章查看,打开浏览器的调试工具f12,找到文本内容以及下一页的url,再重复【1】操作,可以确定二者都在网页源代码中
二、代码实现
- from concurrent.futures import ThreadPoolExecutor
- import requests
- from lxml import etree
- import re
- import os
- main_url = "https://www.23qb.net/book/1883/"
- headers = {
- 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'}
- # 获取每一章的url
- def get_chapter_url(html):
- chapter_url_list = [] # 存放每一章的地址
- chapter_name_list = [] # 存放每一章的名字
- # 将小说放在特定的位置
- dir_name = html.xpath('//*[@id="bookinfo"]/div[2]/div[1]/h1/text()')[0]
- try:
- os.mkdir(dir_name)
- print(f"{dir_name}创建成功!")
- except:
- print(f"{dir_name}已经存在!")
- pass
- os.chdir(dir_name)
- # 获取每一个章节
- chapter_list = html.xpath('//*[@id="chapterList"]/li')
- for each in chapter_list:
- # 章节的url不能直接访问,要先经过处理、拼接
- chapter_url = main_url + each.xpath("./a/@href")[0].split("/")[-1]
- chapter_name = each.xpath("./a/text()")[0]
- chapter_url_list.append(chapter_url)
- chapter_name_list.append(chapter_name)
- # print(chapter_url)
- return zip(chapter_url_list, chapter_name_list)
- # 将数据下载保存
- def save_content(p_list, fp):
- for i in p_list:
- fp.write(i+'\n')
- # 获取数据
- def get_content(text, fp):
- html = etree.HTML(text)
- p_list = html.xpath('//*[@id="TextContent"]//p/text()')
- save_content(p_list, fp)
- # 读取每一章的信息
- def get_page(*params):
- chapter_url = params[0]
- chapter_file_name = params[1]
- with open(f"{chapter_file_name}.txt", mode="w", encoding="utf-8") as fp:
- # 每一章小说不止一页,每一页的规律为 xxx_1.html,xxx_2.html
- # 先将将原url分成两部分,舍去后面 .html 部分
- # 先假设本章有20p ,要判断next_url是否是本章的,如果不是就跳出,到下一章
- target = chapter_url.split(".html")[0]
- for page in range(1, 20): #
- target_url = target+f"_{page}.html"
- with requests.get(target_url, headers=headers) as req:
- # 获取下一个页的url,判断是否为同一张章节
- p = re.compile(
- '<script>.*?nextpage="(?P<next_url>.*?)".*?', re.S)
- res = p.search(req.text)
- next_url = main_url + res.group('next_url').split("/")[-1]
- if next_url.split("_")[0] != target_url.split("_")[0]:
- # 此时为本章的最后一页
- get_content(req.text, fp)
- break
- get_content(req.text, fp)
- print(f"{chapter_file_name}下载完毕!")
- main_html = requests.get(url=main_url).text
- html = etree.HTML(main_html)
- chapter_url_list = get_chapter_url(html)
- # 开启多线程,num可以设置线程数
- num = 5
- with ThreadPoolExecutor(num) as t:
- for each_chapter in chapter_url_list:
- t.submit(get_page, *each_chapter)
- # 下面的是测试代码
- # est_list = ("https://www.23qb.net/book/1883/270977.html", "第一卷 1.净是些令人费解的事")
- # get_page(*test_list)
复制代码
速度还可以
最后
太难了,第一次发这样的长帖,早上没点到保存为草稿,审核了两次
|
|