ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python requests, pasel多线程爬取并下载小说

2022-06-21 18:31:07  阅读:201  来源: 互联网

标签:chapter 章节 sel pasel title Python text 多线程 css


使用PYTHON语言,用到的外部包有pasel, requests。

  逻辑:首先得到该小说所有章节地址,再使用多线程访问链接,得到的内容放入object列表中,最后写入本地文件。

  功能:设置菜单,由此可以选择不同的小说站点;写入本地时会在命令行打印所有章节名称;高速爬取小说。

  注意:1,爬取时没有提示,但写入本地时会显示章节名称;2,测试用的小说站点已清除,在具体使用时,需要自己修改部分代码,其中用注释(需要手动修改)标明。

  1 import requests
  2 import parsel
  3 import threading
  4 import re
  5 
  6 # 常量区
  7 ## 网页标签xpath,主域名
  8 N_NAME = '.read h3::text'
  9 N_TITLE = '.title::text'
 10 N_CONTENT = '.text::text'
 11 # 站点域名, 需要手动修改
 12 HOST1 = 'https://m.xxxx.com'
 13 HOST2 = 'http://www.xxxx.com'
 14 
 15 threadLock = threading.RLock()
 16 chapters = []
 17 
 18 # 单章写入本地文件
 19 ## f 打开的文件对象
 20 def harddisk_write(f, chapter):
 21     ## 线程同步
 22     # global threadLock
 23     # threadLock.acquire()
 24     f.write(chapter.title)
 25     f.write('\n')
 26     f.write(chapter.content)
 27     f.write('\n')
 28     f.flush()
 29     print(chapter.title)
 30     # threadLock.release()
 31     return
 32 
 33 # 网页内容读取,处理; 返回章节名和章节内容,同下一函数相同,目的是应对不同的HOST
 34 ## 需要手动修改:css中的文本
 35 def pull_content1(url):
 36     res = requests.get(url)
 37     sel = parsel.Selector(res.text)
 38     chapter_title = sel.css('.title::text').get()  # 章节名字
 39     chapter_list = sel.css('.text::text').getall()   # 小说内容
 40     # 过滤AAA, 前三行
 41     chapter_content = "\n".join(chapter_list[3:])
 42     return chapter_title, chapter_content
 43 
 44 # 网页内容读取,处理; 返回章节名和章节内容
 45 ## 需要手动修改: css中的文本
 46 def pull_content2(url):
 47     res = requests.get(url)
 48     sel = parsel.Selector(res.text)
 49     chapter_title = sel.css('.bookname h1::text').get()  # 章节名字
 50     chapter_list = sel.css('#content::text').getall()   # 小说内容
 51     chapter_content = "".join(chapter_list)
 52     return chapter_title, chapter_content
 53 
 54 # 处理小说分页, 获取所有章节的url,同下一函数功能相同,不同的是应对的是不一样的HOST
 55 ## 需要手动修改: css中的文本,分页处理的逻辑
 56 def handle_pagination(first_page_url):
 57     response = requests.get(first_page_url)
 58     sel = parsel.Selector(response.text)
 59     novel_name = sel.css('.read h3::text').get().strip() # 小说名字
 60     page_str = sel.css('.page::text').getall()[2] # 分页信息字符串
 61     pages = int(re.findall(r'\d+', page_str)[1])
 62     second_part = re.search(r'(\d+_?)+', first_page_url).group() # 小说分页后缀
 63     second_part_sp = second_part.split('_')
 64     ## 生成小说章节地址
 65     urls = []
 66     i = 1
 67     while i <= pages:
 68         second_part_sp[2] = str(i)
 69         suffix = '_'.join(second_part_sp)
 70         url = HOST1 + '/' + suffix
 71         # urls.append(url)
 72         i += 1
 73         response = requests.get(url)
 74         sel = parsel.Selector(response.text)
 75         urls.extend(sel.css('.chapter li a::attr(href)').getall())
 76 
 77     return novel_name, list(map(lambda x: HOST1 + '/' + x, urls))
 78 
 79 # 获取小说名和章节url
 80 ## 需要手动修改:: css中的文本
 81 def handle_mainpage(first_url):
 82     response = requests.get(first_url)
 83     selector = parsel.Selector(response.text)
 84     novel_name = selector.css('#info h1::text').get().strip()
 85     part_suffix = selector.css('#list dd a::attr(href)').getall()
 86     return novel_name, list(map(lambda x: HOST2 + '/' + x, part_suffix))
 87 
 88 # 定义小说章节数据类型
 89 class Chapter:
 90     # index用来sorted排序
 91     def __init__(self, url, title, content, index):
 92         self.url = url
 93         self.title = title
 94         self.content = content
 95         self.index = index
 96 
 97     def set(self, title, content):
 98         self.title = title
 99         self.content = content
100 
101     def get_title(self):
102         return self.title
103 
104     def get_content(self):
105         return self.content
106     
107     def __repr__(self):
108         return repr((self.index, self.title))
109 
110 # 运行线程,deprecate(无法多线程高速度,抛弃)
111 def single_job(url, f):
112     threadLock.acquire()
113     title, content = pull_content1(url)
114     
115     harddisk_write(f, title, content)
116     threadLock.release()
117 
118 # my job
119 ## 需要手动修改:条件语句
120 def spider_job(chapter, number):
121     # 获取网址
122     url = chapter.url
123     if number == 1:
124         title, content = pull_content1(url)
125     elif number == 2:
126         title, content = pull_content2(url)
127     
128     chapter.title, chapter.content = title, content
129 
130 # 菜单,选择爬取的小说的主域名
131 ## 需要手动修改:打印的内容
132 def menu():
133     print("1, xxx1")
134     print("2, xxx2")
135 
136 # 主程序
137 ## 需要手动修改:结合menu函数,修改if条件语句
138 def main():
139     menu()
140     number = int(input("输入选择项目的序号:"))
141     first_url = input("请输入小说地址: ")
142      ## 小说名字, 章节网址列表
143     if number == 1:
144         novel_name, urls = handle_pagination(first_url)
145     elif number == 2:
146         novel_name, urls = handle_mainpage(first_url)
147     else:
148         exit()
149     threads = []
150     i = 1
151     for url in urls:
152         chapter = Chapter(url, "", "", i)
153         chapters.append(chapter)
154         i += 1
155         thread0 = threading.Thread(target = spider_job, args=(chapter,number))
156         thread0.start()
157         threads.append(thread0)
158 
159     # 关闭文件
160     for t in threads:
161         t.join()
162 
163     # 对queue排序
164     sorted(chapters, key=lambda ch: ch.index)
165     # 生成小说文件
166     with open("E:/online-novel/" +novel_name + ".txt", mode='a', encoding='utf-8') as f:
167         for chapter in chapters:
168             harddisk_write(f, chapter)
169 
170 main()

 

标签:chapter,章节,sel,pasel,title,Python,text,多线程,css
来源: https://www.cnblogs.com/dnghg/p/16397894.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有