上一篇的多线程是使用类创建的,这一次使用函数创建多线程,还是同一个网站https://www.quanjing.com/category/1286521/1.html,
代码如下:
1 # 多线程,自动创建文件夹,每个页面单独存储一个文件夹 2 3 import requests 4 import threading 5 import re 6 import time 7 import queue 8 import os 9 from bs4 import BeautifulSoup 10 11 12 string = ‘https://www.quanjing.com/category/1286521/‘ 13 url_queue = queue.Queue() 14 pipei = re.compile(‘lowsrc="(.*?)" m=‘) # 定义正则表达式,匹配出每一张图片的链接 15 16 17 def get_url(page): # 根据传入的页面数,创建1-page每个页面的url 18 for i in range(1, page+1): 19 url = string + str(i) + ‘.html‘ # 拼接url 20 url_queue.put(url) # 把每个url放入队列中 21 # print(url_queue.queue) 22 23 24 def spider(url_queue): # 爬取函数 25 url = url_queue.get() # 从队列中取出最前面的url 26 floder_count = url[-7:-5] # 判断当前爬取的为第几页,用于后面的创建文件夹,如果页数为两位数,则会截取当前页数,如果为一位数字,则会截取当前页数和前面的‘/’符号 27 if floder_count[0] == ‘/‘: 28 floder_name = floder_count[1] 29 else: 30 floder_name = floder_count 31 os.mkdir(‘第{0}页‘.format(floder_name)) # mkdir创建文件夹 32 html = requests.get(url=url).text 33 soup = BeautifulSoup(html, ‘lxml‘) # 对源码进行解析 34 ul = soup.find_all(attrs={"class": "gallery_list"}) # 提取出图片链接的部分 35 # print(ul) 36 lianjies = re.findall(pipei, str(ul)) # 匹配出每一张图片的链接,正则匹配必须是字符串类型 37 i = 1 38 for lianjie in lianjies: 39 # print(lianjie) 40 result = requests.get(url=lianjie).content # 二进制方式请求每张图片,并存储。 41 with open(‘第{0}页\{1}.jpg‘.format(floder_name, i), ‘ab‘) as f: 42 f.write(result) 43 print(‘第{0}页第{1}张存储完成‘.format(floder_name, i)) 44 i += 1 45 46 if not url_queue.empty(): # 如果队列未空,则该线程继续工作,从队列中取出url 47 spider(url_queue) 48 49 50 def main(): # main函数,用于线程的创建,线程的启动 51 queue_list = [] # 线程列表 52 queue_count = 3 # 线程数量 53 for i in range(queue_count): 54 t = threading.Thread(target=spider, args=(url_queue, )) # 创建线程,第一个参数为线程要调用的函数,第二个参数为函数的参数 55 queue_list.append(t) # 把线程加入队列 56 for t in queue_list: # 线程开始 57 t.start() 58 for t in queue_list: # 等待所有线程结束 59 t.join() 60 61 62 if __name__ == ‘__main__‘: 63 page = int(input("请输入需要爬取的页数:")) 64 get_url(page) 65 start_time = time.time() 66 main() 67 print("test3用时:%f" % (time.time() - start_time)) # 计算爬取用时
在写代码时,遇到了两点困难:一是队列未空时,怎么让线程继续工作。刚开始是在if判断后调用main函数,但这样做等于又重新定义了新的线程,并不是之前的线程在继续工作,且有时候会存在爬取不完的情况,后来尝试调用spider函数,爬取成功
第二个困难是文件夹的创建,刚开始没有对截图的两个字符进行判断,导致创建失败,百度一下后发现可以用makedirs解决,试了后发现这样创建的是多级目录,也不行,(可能是‘/’字符的缘故),后来加了一个判断,才解决这一问题。
写完这两个多线程爬虫,才算是了解了线程的工作机制的程序。(ps:若有错误的地方,欢迎大佬随时指正。。xixix)
原文地址:https://www.cnblogs.com/liangxiyang/p/11146065.html
时间: 2024-10-10 14:47:38