+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2019-07(1)

2019-08(116)

2019-09(115)

2019-10(14)

2019-11(6)

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

发布于2020-09-20 19:30     阅读(1398)     评论(0)     点赞(27)     收藏(5)


0

1

2

3

4

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

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

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

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

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

以下是效果图。

源码在文末。

#这是链接文件。

  1. #coding:utf-8
  2. #仅仅学习参考,请爱护好网站服务器,切勿恶意攻击。谢谢。
  3. from bs4 import BeautifulSoup
  4. import requests
  5. import time
  6. import json #存储书本链接文件
  7. import pandas as pd #清洗数据,去掉重复的链接需要用到
  8. import os #检查当前目录下是否有对应的文件需要用到
  9. import random #随机请求头,但并不是每次调用都刷新,需要改进
  10. html_base = 'https://www.qu.la/'
  11. user_agent = [
  12. "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
  13. "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
  14. "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
  15. "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
  16. "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
  17. "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
  18. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
  19. "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
  20. "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
  21. "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
  22. "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
  23. "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
  24. "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
  25. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
  26. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
  27. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
  28. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
  29. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
  30. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
  31. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
  32. "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
  33. "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
  34. "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
  35. "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
  36. "Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
  37. "MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
  38. "Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
  39. "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
  40. "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+",
  41. "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
  42. "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124",
  43. "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)",
  44. "UCWEB7.0.2.37/28/999",
  45. "NOKIA5700/ UCWEB7.0.2.37/28/999",
  46. "Openwave/ UCWEB7.0.2.37/28/999",
  47. "Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999",
  48. # iPhone 6:
  49. "Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25"]
  50. randomnum = random.randint(1,35)
  51. headers = {'User-Agent': user_agent[randomnum]}
  52. xl = {}#书本系列
  53. xl_link = {} #书本系列
  54. zj_list_links = [] # 章节链接清单,收集书本的所有链接
  55. zj_list_html_dict = {} # total(int):小说总数 next_href:下一页的链接
  56. storyinfo = {} # 收集小说的书名、作者、简介、等信息
  57. over_mark = True
  58. over_mark1 = True #标志
  59. over_mark_getlinks = True
  60. #下载正文 ,下载完成后打开下一章继续下载,直至到完成一本书的下载
  61. def get_story(soup):
  62. #下载第几章
  63. storyinfo["第N章"] = soup.select(".reader-main .title")[0].text
  64. storyinfo["正文"] = soup.select(".container .content")[0].text # 如果不加.text 就回出现<br/>符号。加上后就回只留下文本。
  65. storyinfo["下一页link"] = soup.select(".section-opt a")[2]['href']
  66. #每本书的基本信息zjnum = -20
  67. def story_info(soup):
  68. #小说名称
  69. storyinfo["书名"] = soup.select(".top h1")[0].text
  70. # 小说系列
  71. storyinfo["系列"] = soup.select(".xs-show")[0].text
  72. # 小说更新日期
  73. storyinfo["更新时间"] = soup.select(".fix p")[4].text
  74. # 小说作者l
  75. storyinfo["作者"] = soup.select(".fix p")[0].text
  76. #小说简介
  77. storyinfo["简介"] = soup.select(".info .desc.xs-hidden")[0].text
  78. #书本第一章
  79. storyinfo["第一章link"] = soup.select(".container .section-box li a")[-20]['href']
  80. #收集小说总数,以及20本之后的下一页链接
  81. def zj_list_html(soup):
  82. #当前系列中所有小说的总数
  83. total_story = soup.select(".pagination.pagination-mga .hd strong")[0].text
  84. #"最近更新小说页面的#下一页#"
  85. zj_list_nextpage = soup.select(".pagination.pagination-mga li a")[0]['href']
  86. zj_list_html_dict["书本总数"] = int(total_story)
  87. zj_list_html_dict["下一页link"] = zj_list_nextpage
  88. for i in range(20):
  89. zj_links = soup.select(".layout.layout2.layout-col2 .txt-list.txt-list-row5 li .s2 a")[i]['href']
  90. zj_list_links.append(zj_links)
  91. #打开网页
  92. def open_html(href):
  93. res = requests.get(html_base + href,headers = headers)
  94. res.encoding = "utf-8"
  95. soup = BeautifulSoup(res.text, "lxml")
  96. return soup
  97. #新建txt,并追加内容。可在这个方法里进行数据清洗,和小说排版等工作
  98. def download_newfile(file_text,filename,zjname):
  99. #创建文件夹
  100. zj_file = open(filename+'.txt',"ab+") #这里 ab+ 标记出了使用二进制打开txt
  101. # 数据清洗
  102. newfile = str(file_text)
  103. newfile = newfile.replace("章节错误,点此举报(免注册)</a>,举报后维护人员会在两分钟内校正章节内容,请耐心等待,并刷新页面。</div>。",'\n')#文本格式整理#文本格式整理
  104. newfile_encode = newfile.encode("utf-8") #这里必须转换成UTF-8再写入txt 否则回报错
  105. zjname_encode = str(zjname).encode("utf-8")
  106. #数据写入
  107. zj_file.write(zjname_encode)
  108. zj_file.write(newfile_encode)
  109. zj_file.close()
  110. res = requests.get(html_base,headers = headers)
  111. res.encoding = "utf-8"
  112. soup = BeautifulSoup(res.text,"lxml")
  113. #收集系列名称并写入dict(xl)
  114. for i in range(1,7):
  115. xl[i] = soup.select(".nav li a")[i+1].text
  116. #收集系列名称并写入dict(xl_link)
  117. for i in range(1,7):
  118. xl_link[i] = soup.select(".nav li a")[i+1]['href']
  119. # 显示选项,并选择需要下载的系列
  120. print(xl)
  121. num = input("Please input your choose:")
  122. if bool(num) == True:
  123. # 打开这个链接可以获取当前页面20本书的链接和下一页的链接
  124. zj_list_html(open_html(xl_link[int(num)]))
  125. #检索目前路径数据库
  126. if os.path.exists('xl_all_links' + '_' + xl[int(num)] + '.json')==True :
  127. print("书本链接文件已存在,正在读取链接文件...")
  128. with open('xl_all_links' + '_' + xl[int(num)] + '.json','r') as f:
  129. zj_list_links = json.load(f)
  130. print(zj_list_links)
  131. alllinks = len(zj_list_links)
  132. print("书本总数:"+str(alllinks))
  133. while over_mark:
  134. for i in range(alllinks):
  135. print("当前下载:第"+str(i+1)+"本")
  136. #从story_info获取第一章的链接并打开
  137. story_info(open_html(zj_list_links[i]))
  138. print(storyinfo["书名"])
  139. over_mark1 = True
  140. while over_mark1:
  141. get_story(open_html(storyinfo["第一章link"]))
  142. while zj_list_links[i] != storyinfo["下一页link"]:
  143. time.sleep(1)
  144. download_newfile(storyinfo["正文"], storyinfo["书名"], storyinfo["第N章"])
  145. try:
  146. get_story(open_html(storyinfo["下一页link"]))
  147. #当收集到最后一页的时候,返回就会出错,首先返回出错网页,再返回书本列表。这里检测到这个信息后,就表示已收集完成了。
  148. if storyinfo["下一页link"] == "javascript:void(0);":
  149. if 0==alllinks-1:
  150. print("当前书籍收集完成。")
  151. break
  152. storyinfo["下一页link"] = zj_list_links[i]
  153. except:
  154. print("这里出错了,出错内容:")
  155. print(storyinfo["第N章"])
  156. print("出错链接:"+storyinfo["下一页link"])
  157. print("10秒后重新尝试")
  158. time.sleep(10)
  159. continue
  160. over_mark1 = False
  161. #print("当前章节链接:"+storyinfo["下一页link"]) #打印出当前章节链接
  162. print("正在下载:"+ storyinfo["第N章"]) # 当前下载的章节
  163. alllinks = alllinks-1 #下载完成后,总链接 -1
  164. else:
  165. print("当前目录未发现链接文件,请先下载书本链接...")
  166. # 选中系列打开网址
  167. print("正在下载" + xl[int(num)] + "书本链接...")
  168. print("当前系列书本总数:"+str(zj_list_html_dict["书本总数"]))
  169. """这里开始收集书本中的所有链接
  170. 并开始清洗收集到的数据#使用pandas unique 进行清除重复值
  171. 最终保存数据文件为json
  172. """
  173. while over_mark_getlinks:
  174. time.sleep(1)
  175. getlinks = open_html(zj_list_html_dict["下一页link"])
  176. try:
  177. zj_list_html_dict["下一页link"] = getlinks.select(".pagination.pagination-mga li a")[1]['href']
  178. for i in range(20):
  179. zj_links = getlinks.select(".layout.layout2.layout-col2 .txt-list.txt-list-row5 li .s2 a")[i]['href']
  180. zj_list_links.append(zj_links)
  181. print("已下载链接:"+str(len(zj_list_links)))
  182. except:
  183. print("页面异常!停止收集,已收集:")
  184. print(len(zj_list_links))
  185. print(zj_list_html_dict["下一页link"])
  186. print("收集完毕,正在清洗整理文件并保存....")
  187. zj_list_links = pd.unique(zj_list_links)
  188. print(len(zj_list_links))
  189. with open('xl_all_links' + '_' + xl[int(num)] + '.json', 'w') as file:
  190. json.dump(list(zj_list_links), file)
  191. print("存储文件:" + 'xl_all_links' + '_' + xl[int(num)] + "-->保存完毕!")
  192. print("下载完毕请重新运行软件。")
  193. break

原文链接:https://blog.csdn.net/myself360013139/article/details/108605416

0

1

2

3

4

5



所属网站分类: 技术文章 > 博客

作者:ereryu8787

链接: https://www.pythonheidong.com/blog/article/535239/565be6b6a02bb0bcc97e/

来源: python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

27 0
收藏该文
已收藏

评论内容:(最多支持255个字符)