鱼C论坛

 找回密码
 立即注册
查看: 1788|回复: 4

多线程爬虫阻塞queue问题

[复制链接]
发表于 2020-4-5 00:49:52 | 显示全部楼层 |阅读模式
5鱼币
  1. import requests
  2. from lxml import etree
  3. import re
  4. import threading
  5. from queue import Queue
  6. import time
  7. import random
  8. class Producer(threading.Thread):
  9.     headers = {
  10.         'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"}
  11.     def __init__(self,catalog_queue,text_queue,*args,**kwargs):
  12.         super(Producer, self).__init__(*args,**kwargs)
  13.         self.catalog_queue = catalog_queue
  14.         self.text_queue = text_queue
  15.     def run(self):
  16.         while True:
  17.             if self.catalog_queue.empty():      #---------------------------------------------------------可能有多线程通过了这个判断,导致有的线程卡在了get(),但是没关系吧   
  18.                 break
  19.             catalog = self.catalog_queue.get()#---------------------------------------------------这里卡不卡无所谓
  20.             url = catalog[2]
  21.             chapter_text = self.find_text(self.get_url(url))
  22.             self.text_queue.put((catalog[0], catalog[1], chapter_text))#--------------------------------------我怀疑是没有放进去,但是不知道为啥
  23.     def get_url(self,url):
  24.         response = requests.get(url, headers=self.headers)
  25.         if response.encoding == 'ISO-8859-1':
  26.             response.encoding = response.apparent_encoding
  27.         html = response.text
  28.         return (html)

  29.     def find_text(self,html):
  30.         html = etree.HTML(html)
  31.         text_list = html.xpath('//div[@id="content"]/text()')
  32.         if '精彩小说无弹窗免费阅读' in text_list[0]:
  33.             text_list = text_list[1:]
  34.         p = re.compile(r'(\S+)')
  35.         k = []
  36.         for each_line in text_list:
  37.             line = each_line.replace(u'\u3000', '')
  38.             line = line.replace(u'\xa0', '')
  39.             a = p.findall(line)
  40.             b = ''.join(a)
  41.             k.append(b)
  42.         while '' in k:
  43.             k.remove('')
  44.         chapter_text = '\n\n'.join(k) + '\n\n\n\n'
  45.         return(chapter_text)

  46. def get_url(url):
  47.     headers ={'user-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"}
  48.     response = requests.get(url,headers = headers)
  49.     if response.encoding == 'ISO-8859-1':
  50.         response.encoding = response.apparent_encoding
  51.     html = response.text
  52.     return(html)

  53. def find_catalog(html,target_url,catalog_queue):
  54.     html = etree.HTML(html)
  55.     name = html.xpath('//h1/text()')[0]
  56.     catalog_names = html.xpath('//dd/a/text()')
  57.     catalog_short_urls = html.xpath('//dd/a/@href')
  58.     #len_url = len(catalog_short_urls)
  59.     catalog_num = 1
  60.     count = 0
  61.     for each in catalog_short_urls[:]:
  62.         #catalog_urls.append(target_url+each)
  63.         #print((catalog_num,catalog_names[count],target_url+each))
  64.         a = (catalog_num,catalog_names[count],target_url+each)
  65.         catalog_queue.put(a)
  66.         catalog_num +=1
  67.         count += 1
  68.     return((name,catalog_num-1))

  69. def len_catalog(html):
  70.     html = etree.HTML(html)
  71.     catalog_short_urls = html.xpath('//dd/a/@href')
  72.     len_url =  len(catalog_short_urls)
  73.     return(len_url)

  74. def main():
  75.     t1 = time.time()
  76.     start_time = time.asctime()
  77.     emple_url = 'https://www.52bqg.com/book_'
  78.     p=re.compile(r'book_(\d+)')
  79.     target_url = input('请输入笔趣阁52bqg.com的小说地址:')
  80.     urls = p.findall(target_url)[0]
  81.     print('正在解析网页')
  82.     if urls == '':
  83.         print('输入网页格式错误,倒计时两秒')
  84.         time.sleep(2)
  85.         raise
  86.     html = get_url(emple_url+urls)
  87.     len_url = len_catalog(html)
  88.     catalog_queue = Queue(len_url+10)
  89.     text_queue = Queue(len_url+10)
  90.     novel = find_catalog(html, target_url,catalog_queue)
  91.     print('----------------------解析成功---------------------------')
  92.     print('-----------小说名:{}-----------章节数:{}-----------'.format(novel[0], novel[1]))
  93.     for i in range(100):
  94.         t =Producer(catalog_queue,text_queue)#------------------------------------------------------------从目录catalog_queue去爬取每一章的文字放在text_queue里面
  95.         t.start()
  96.     temp = input('按回车键爬取')
  97.     print('正在爬取小说内容')
  98.     novel_text = []
  99.     # print(text_queue.qsize())
  100.     # raise
  101.     while 1:
  102.         print('请勿关闭程序!  当前时间:'+time.asctime()+'  正在爬取  '+str(len(novel_text)+1)+'/'+str(novel[1])+'  章   当前线程数量:'+str(len(threading.enumerate())-1))
  103.         if len(novel_text) >= len_url:
  104.             break
  105.         content = text_queue.get()#-------------------------------------------肯定是卡在这里了,他拿不到这个最后几个数据。
  106.         novel_text.append(content)#------------------------------------------把章节放在列表里面,好排序
  107.     print('爬取完成,正在写入')
  108.     time.sleep(1)
  109.     def take_one(novel_text):
  110.         return (novel_text[0])

  111.     novel_text.sort(key=take_one, reverse=False)#-------------------------------------------------------------------------------排序
  112.     begin_text = '------------------ {} ------------------\n'
  113.     with open(novel[0]+'.txt','w',encoding = 'utf-8') as f:
  114.         count_0 = 0
  115.         for i in novel_text:
  116.             print('正在写入 {} .....'.format(i[1]))
  117.             f.write(begin_text.format(i[1])+i[2])
  118.             count_0 += 1
  119.     end_time = time.asctime()
  120.     t2 = time.time()
  121.     print('\n\n开始时间:'+start_time)
  122.     print('结束时间:'+end_time)
  123.     print('小说写入 '+str(count_0)+' 个章节')
  124.     print('平均下载速率  %.2f 章/秒  '%(count_0/(t2-t1)))
  125.     temp = input('\n按回车键结束')

  126. if __name__ == '__main__':
  127.     main()
复制代码



小说爬虫
最近学习了多线程爬虫,这里面没有用锁,但是用了queue还是经常阻塞。
程序的流程是先爬取所有章节的链接,然后开启多线程把每个章节的内容放在queue里面,然后再单线程放在列表里面,然后排序写入。

但是爬小说的时候,经常时不时的阻塞,我百度了超级多的方法,但是一直解决不了问题。我也不知道为啥会阻塞。因为上面的多线程里面的get阻塞了也没事呀,主进程结束了它也就结束了呀。
到底是为啥呀,难受

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-4-9 13:38:35 | 显示全部楼层
我运行了下,输入target_url:https://www.52bqg.com/book_127354
会报错。。。

顺便分享下
https://zhuanlan.zhihu.com/p/25228075?utm_source=wechat_session&utm_medium=social&utm_oi=28425901309952&s_s_i=Uij1R8pnmkjCPiO4HI66ySfC%2FyMZpeB3dNV9SUmG%2FjY%3D&s_r=1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-4-12 20:05:28 | 显示全部楼层
很好,1400多章的小说,10分钟爬完
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-4-14 13:28:14 | 显示全部楼层
兢兢 发表于 2020-4-12 20:05
很好,1400多章的小说,10分钟爬完

太慢了,可以看看这个
https://url.ms/mol4x
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-4-14 21:28:20 From FishC Mobile | 显示全部楼层
获取小说的目录链接时没有过滤掉部分空链接
有一部小说,总共有64章,但是有68个链接
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 19:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表