鱼C论坛

 找回密码
 立即注册
查看: 1945|回复: 3

[已解决]关于多线程堆列的问题

[复制链接]
发表于 2023-4-14 01:03:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
如图,初学者,想多线程写一个爬虫,构思了一个框架,尝试了一下,发现不能运行完整,中途就结束了,请各位大佬劳烦看一下问题在哪里。

代码如下
import threading
import time
from queue import Queue
import requests

t1 = time.time()
url_queue = Queue()


def download():
    while not url_queue.empty():
        url=url_queue.get()
        res = requests.get(url)
        print(url,res.status_code,res.encoding)
        return res.status_code
    # print(res.headers)


urls = ['http://www.038909.xyz', 'http://www.solucky.com.cn',
        'http://www.baidu.com', 'http://www.bing.com', 'http://www.cnbeta.com', 'http://16666.com'

        ]

for url in urls:
    url_queue.put(url)

for i in range(3):
    t = threading.Thread(target=download)
    t.start()

运行结果:
当range(3)时,只跑前三个,后面的url不跑。
/Volumes/DATA/PythonData/venv/bin/python /Volumes/DATA/doc&docx/2.py
http://www.038909.xyz 200 ISO-8859-1
http://www.baidu.com 200 ISO-8859-1
http://www.solucky.com.cn 502 None

最佳答案
2023-4-14 01:06:12
从你提供的代码来看,你创建了三个线程来执行 `download` 函数。每个线程在队列中取出一个 URL 进行下载,但是当 `download` 函数返回结果后,线程就结束了。所以你观察到的现象是只有前三个 URL 被处理了。

你可以通过让每个线程处理多个 URL 来解决这个问题。这可以通过在 `download` 函数中添加一个循环来实现。当一个线程处理完一个 URL 后,它将继续处理队列中的下一个 URL,直到队列为空。这里是修改后的代码:
import threading
import time
from queue import Queue
import requests

t1 = time.time()
url_queue = Queue()


def download():
    while not url_queue.empty():
        url = url_queue.get()
        res = requests.get(url)
        print(url, res.status_code, res.encoding)
        url_queue.task_done()  # 需要添加这行,以通知队列此任务已完成

urls = [
    'http://www.038909.xyz', 'http://www.solucky.com.cn',
    'http://www.baidu.com', 'http://www.bing.com', 'http://www.cnbeta.com', 'http://16666.com'
]

for url in urls:
    url_queue.put(url)

threads = []  # 创建一个线程列表,用于保存所有线程
for i in range(3):
    t = threading.Thread(target=download)
    t.start()
    threads.append(t)  # 把线程添加到线程列表

# 等待所有任务完成
url_queue.join()

# 等待所有线程结束
for t in threads:
    t.join()

t2 = time.time()
print('Total time: ', t2 - t1)

这样修改后,你的代码应该可以正确地处理所有的 URL 了。不过,还有一点需要注意:由于多线程操作不是线程安全的,可能会出现一些意外情况。在实际编写爬虫时,建议使用线程池 (如 `concurrent.futures.ThreadPoolExecutor`) 等更高级的并发工具,以确保程序的稳定性和可扩展性。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-14 01:06:12 | 显示全部楼层    本楼为最佳答案   
从你提供的代码来看,你创建了三个线程来执行 `download` 函数。每个线程在队列中取出一个 URL 进行下载,但是当 `download` 函数返回结果后,线程就结束了。所以你观察到的现象是只有前三个 URL 被处理了。

你可以通过让每个线程处理多个 URL 来解决这个问题。这可以通过在 `download` 函数中添加一个循环来实现。当一个线程处理完一个 URL 后,它将继续处理队列中的下一个 URL,直到队列为空。这里是修改后的代码:
import threading
import time
from queue import Queue
import requests

t1 = time.time()
url_queue = Queue()


def download():
    while not url_queue.empty():
        url = url_queue.get()
        res = requests.get(url)
        print(url, res.status_code, res.encoding)
        url_queue.task_done()  # 需要添加这行,以通知队列此任务已完成

urls = [
    'http://www.038909.xyz', 'http://www.solucky.com.cn',
    'http://www.baidu.com', 'http://www.bing.com', 'http://www.cnbeta.com', 'http://16666.com'
]

for url in urls:
    url_queue.put(url)

threads = []  # 创建一个线程列表,用于保存所有线程
for i in range(3):
    t = threading.Thread(target=download)
    t.start()
    threads.append(t)  # 把线程添加到线程列表

# 等待所有任务完成
url_queue.join()

# 等待所有线程结束
for t in threads:
    t.join()

t2 = time.time()
print('Total time: ', t2 - t1)

这样修改后,你的代码应该可以正确地处理所有的 URL 了。不过,还有一点需要注意:由于多线程操作不是线程安全的,可能会出现一些意外情况。在实际编写爬虫时,建议使用线程池 (如 `concurrent.futures.ThreadPoolExecutor`) 等更高级的并发工具,以确保程序的稳定性和可扩展性。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-4-14 01:12:52 | 显示全部楼层
isdkz 发表于 2023-4-14 01:06
从你提供的代码来看,你创建了三个线程来执行 `download` 函数。每个线程在队列中取出一个 URL 进行下载, ...

非常感谢,让我多了一点思考,和发现一些没想到的地方。再次感谢(那么晚还没睡)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-14 01:15:45 | 显示全部楼层
fineconey 发表于 2023-4-14 01:12
非常感谢,让我多了一点思考,和发现一些没想到的地方。再次感谢(那么晚还没睡)

不客气。最近熬夜熬习惯了,虽然知道熬夜不好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-14 20:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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