Python实现多线程、多进程爬虫

第41课 Python 并发编程技术精讲:多线程、多进程与异步编程 通过学习多线程、多进程和异步编程等并发编程技术,可以更好地利用计算机资源,提高程序的执行效率和响应速度,解决实际开发中的并发问题. 阅读详情
1.多线程的线程守护

在python3中,主线程主进程结束,子进程不会结束,为了能够让主线程回收子线程,可以把子线程设置为守护线程,即该线程不重要,主线程结束,子线程结束:
举个例子:

import time
import threading

def test():
    while True:
        print('测试线程守护!!',threading.currentThread())
        time.sleep(1)

if __name__ == '__main__':
    t1 = threading.Thread(target=test)
    t2 = threading.Thread(target=test)
    t1.start()
    t2.start()

执行以上代码,得出的结果是交替打印出两个线程,由于线程执行的函数为死循环,所以子线程也会陷入死循环,不管你怎么按ctrl+c也无法停止线程。如下:

(venv) E:\test>python test.py
测试线程守护!! <Thread(Thread-1, started 9652)>
测试线程守护!! <Thread(Thread-2, started 2728)>
测试线程守护!! <Thread(Thread-1, started 9652)>
测试线程守护!! <Thread(Thread-2, started 2728)>
测试线程守护!! <Thread(Thread-1, started 9652)>
测试线程守护!! <Thread(Thread-2, started 2728)>
测试线程守护!! <Thread(Thread-1, started 9652)>
测试线程守护!! <Thread(Thread-2, started 2728)>
测试线程守护!! <Thread(Thread-1, started 9652)>
测试线程守护!! <Thread(Thread-2, started 2728)>
测试线程守护!! <Thread(Thread-1, started 9652)>
测试线程守护!! <Thread(Thread-2, started 2728)>
测试线程守护!! <Thread(Thread-1, started 9652)>
测试线程守护!! <Thread(Thread-2, started 2728)>

那么怎样才能可以避免这种问题呢?或者说,怎样才能在主线程退出的时候,子线程也自动退出呢?没错就是使用线程守护,也就是等到主线程执行完,子线程也强制停止,换句话说就是子线程会随着主线程一起结束。使用案例:

t1 = threading.Thread(targe=func,args=(,))
t1.setDaemon(True)
t1.start() #此时线程才会启动

优化前面死循环不能停止的线程,源码如下:

import time
import threading

def test():
    while True:
        print('测试线程守护!!',threading.currentThread())
        time.sleep(1)

if __name__ == '__main__':
    t1 = threading.Thread(target=test)
    t2 = threading.Thread(target=test)
    t1.setDaemon(True)
    t1.start()
    t2.setDaemon(True)
    t2.start()

输出结果:

(venv) E:\test>python test.py
测试线程守护!! <Thread(Thread-1, started daemon 5884)>
测试线程守护!! <Thread(Thread-2, started daemon 7112)>

可以看到,运行一次就直接退出了,因为主线程已经执行完了,确实是主线程已经结束了,正因为设置了守护线程,所以这时候子线程也一并退出了。

2.队列模块的使用
from queue import Queue
q = Queue(maxsize=100)
item = {}
q.put_nowait(item) #不等待直接放,队列满的时候会报错
q.put(item) #放入数据,队列满的时候会等待
q.get_nowait() #不等待直接取,队列空的时候会报错
q.get() #取出数据,队列为空的时候会等待
q.qsize() #获取队列中现存数据的个数 
q.join() #队列中维持了一个计数,计数不为0时候让主线程阻塞等待,队列计数为0的时候才会继续往后执行
q.task_done() # put的时候计数+1,get不会-1,get需要和task_done 一起使用才会-1
3. 线程中使用队列
## 队列可用于线程间的数据通讯
from queue import Queue
import threading

q = Queue()
def add_to_queue():
    for i in range(0, 100):
        print("存入队列: {}".format(i))
        q.put(i)

def get_from_queue():
    # 但是在我们获取队列元素的时候, 我们并不知道队列中放了几个元素,
    # 这个时候我们就会使用while的死循环来获取,知道取完为止
    # for i in range(0, 100):
    while True:
        print("从队列中取出: {}".format(q.get()))
        q.task_done()

# 创建线程
t = threading.Thread(target=add_to_queue)
# 设置为守护线程
t.setDaemon(True)
# 启动线程
t.start()

t = threading.Thread(target=get_from_queue)
t.setDaemon(True)
t.start()

# 队列加入主线线程, 等待队列中任务完成为止
q.join()

4. 装饰器的基本使用

装饰器的作用: 不改变原有函数,给函数添加额外功能

# 定义装饰一个死循环执行任务的装饰器
def run_forever(func):
    def forever(obj):
        while True:
            func(obj)
    return forever

# 使用装饰器
@run_forever # 等同于 run_forever(run)
def run(obj):
    print("人生苦短,我用Python {}".format(obj))

# 执行函数  --死循环
run('Hpayy')

糗事百科多线程
实现步骤:
  • 1.在init方法中, 创建 URL队列, 响应队列, 数据队列
  • 2.在生成URL列表中方法中,把URL添加URL队列中
  • 3.在请求页面的方法中,从URL队列中取出URL执行,把获取到的响应数据添加响应队列中
  • 4.在处理数据的方法中,从响应队列中取出页面内容进行解析, 把解析结果存储数据队列中
  • 5.在保存数据的方法中, 从数据队列中取出数据,进行保存
  • 6.开启几个线程来执行上面的方法
注意: 开的线程数取决于这个任务耗时, 耗时长的就多开几个线程.

多线程爬虫源码:


import threading
import requests
from lxml import etree
import json
from queue import Queue

# 多线程思路:
# 把所有待采集得链接url放进一个url队列里面
# 在请求页面得过程中,以多线程得方式从队列中取出url,请求结束后要执行task_done()方法来释放队列避免重复采集
# 为了更快得处理相应后数据(页面数据),也可以把每个页面获得得页面源码放在相应队列中,一样处理完得task_done()来清队列
# 最后得保存数据也可以开一个队列用于保存
# 可以设置线程数量来处理数据


# 由于请求、处理数据需要较多次数的轮循,所以可以直接写个修饰器函数用于循环某个函数
def run_forever(func):
    def wrapper(obj):
        while True:
            func(obj)
    return wrapper


class CrawlData:
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
        }
        self.url_pattern = 'https://www.qiushibaike.com/8hr/page/{}/'
        self.url_queue = Queue() # url 队列
        self.page_queue= Queue() # 页面 队列
        self.data_queue = Queue() # 数据 队列


    # 把待采集的url放入队列
    def add_url_to_queue(self):
        for i in range(1, 14):
            self.url_queue.put(self.url_pattern.format(i))


    @run_forever
    def add_page_to_queue(self):
        url = self.url_queue.get() # 从队列中获取一个url,get不会做-1操作
        result = requests.get(url, headers=self.headers)
        if result.status_code != 200:
            self.url_queue.put(url)
        else:
            self.page_queue.put(result.text)
        #结束当前url任务
        self.url_queue.task_done()

    @run_forever
    def add_data_to_queue(self):
        # 从队列中获取一个页面数据出来待处理
        page = self.page_queue.get()
        element = etree.HTML(page)
        div_s = element.xpath('//div[@class="recommend-article"]/ul/li')
        # 遍历分组列表, 再使用xpath获取内容
        dz_list = []
        for div in div_s:
            item = {}
            # 每个段子包含发送人头像URL, 昵称, 性别, 段子内容, 好笑数,评论数
            # 头像URL
            item['head_url'] = self.get_first_element(div.xpath('.//a[@class="recmd-user"]/img/@src'))
            if item['head_url'] is not None:
                item['head_url'] = 'http:' + item['head_url']
                # 昵称
            item['author_name'] = self.get_first_element(div.xpath('.//a[@class="recmd-user"]/span/text()'))

            dz_list.append(item)
        # 解析好得数据放入队列
        self.data_queue.put(dz_list)
        # 结束当前页面数据任务
        self.page_queue.task_done()


    def get_first_element(self, list):
        '''获取列表中第一个元素,如果是空列表就返回None'''
        return list[0] if len(list) != 0 else None

    # 保存数据
    @run_forever
    def save_data(self):
        # 从已有的数据中获取一个处理后的数据进行存储
        data = self.data_queue.get()
        with open('qiubai.json', 'a', encoding='utf8') as f:
            for dt in data:
                json.dump(dt, f, ensure_ascii=False)
                f.write('\n')

        self.data_queue.task_done() # 结束当前数据任务

    def run_count_use(self, func, count):
        # 开启多个线程处理
        for i in range(count):
            t = threading.Thread(target=func)
            t.setDaemon(True)
            t.start()

    def run(self):
        # 把待处理的url加入队列
        url_t = threading.Thread(target=self.add_url_to_queue)
        url_t.start()

        # 开启获取页面数据线程
        self.run_count_use(self.add_page_to_queue, 3)
        # 开启处理解析页面数据 
        self.run_count_use(self.add_data_to_queue, 2)
        # 开启数据存储线程
        self.run_count_use(self.save_data, 2)

        # 使用队列join方法,等待队列数据处理结束
        self.url_queue.join() # 等待url队列为空时才会往下继续
        self.page_queue.join() # 等待页面队列为空时才会往下继续
        self.data_queue.join() # 等待数据队列为空时才会往下继续


if __name__ == '__main__':
    import time
    start = time.time()
    CrawlData().run()
    end = time.time()

    print('总共用时:{}'.format((end-start)))
多进程爬取糗百

实现步骤

  • 开启一个进程池Pool,一般是基于cpu个数
  • 直接遍历循环待采集的url,并使用apply_async开启异步进程
  • 按找需求解析源码,获取想要采集的数据
    源码:
from multiprocessing import Pool
import json
import requests
import os
import time
from lxml import etree

class CrawlData:
    def __init__(self, url):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
        }
        self.url = url


    def get_page_data(self):
        print('当前子进程{}'.format(os.getpid()))
        page_data = requests.get(self.url, headers=self.headers)
        element = etree.HTML(page_data.text)
        div_s = element.xpath('//div[@class="recommend-article"]/ul/li')
        # 遍历分组列表, 再使用xpath获取内容
        dz_list = []
        for div in div_s:
            item = {}
            item['head_url'] = self.get_first_element(div.xpath('.//a[@class="recmd-user"]/img/@src'))
            if item['head_url'] is not None:
                item['head_url'] = 'http:' + item['head_url']
                # 昵称
            item['author_name'] = self.get_first_element(div.xpath('.//a[@class="recmd-user"]/span/text()'))
            dz_list.append(item)
        self.save_data(dz_list)


    def get_first_element(self, list):
        '''获取列表中第一个元素,如果是空列表就返回None'''
        return list[0] if len(list) != 0 else None

    def save_data(self, data):
        # 从已有的数据中获取一个处理后的数据进行存储
        with open('qiubai_process.json', 'a', encoding='utf8') as f:
            for dt in data:
                json.dump(dt, f, ensure_ascii=False)
                f.write('\n')


# 采集入口函数
def crawl(url):
    CrawlData(url).get_page_data()

if __name__ == '__main__':
    start = time.time()
    url_pattern = 'https://www.qiushibaike.com/8hr/page/{}/'
    p = Pool(4) # 不传参默认以最大cpu数作为进程数
    for i in range(1,14):
        url = url_pattern.format(str(i))
        p.apply_async(crawl, args=(url,))
    p.close()
    p.join()

    end = time.time()
    print(f'总共用时:{(end-start)}')

运行结果:

  • 单进程 Pool(1):
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
当前子进程10356
总共用时:13.325877666473389
  • 双进程 Pool(2):
当前子进程3320
当前子进程9492
当前子进程3320
当前子进程9492
当前子进程9492
当前子进程3320
当前子进程9492
当前子进程3320
当前子进程3320
当前子进程9492
当前子进程3320
当前子进程9492
当前子进程3320
总共用时:1.3394155502319336
  • 三进程 Pool(3):
当前子进程10908
当前子进程9124
当前子进程3148
当前子进程10908
当前子进程9124
当前子进程3148
当前子进程3148
当前子进程9124
当前子进程10908
当前子进程9124
当前子进程3148
当前子进程10908
当前子进程3148
总共用时:1.1449363231658936
  • 四进程 Pool(4):
当前子进程11208
当前子进程7944
当前子进程9188
当前子进程9916
当前子进程9916
当前子进程11208
当前子进程9188
当前子进程7944
当前子进程9916
当前子进程7944
当前子进程11208
当前子进程9188
当前子进程11208
总共用时:0.9803769588470459

下面再来个爬取知乎的例子

采集知乎一定要登录才可以,否则无法正常获取数据,本文采用cookies携带登录信息请求数据,具体之前文章《Python爬虫之利用cookies跳过登陆验证码》已经介绍过。其中cookies一定要用等登陆后从浏览器里面获取,并用于请求中,不然会报以下错误:

{"code":"100010","'message'":"Unsupported auth type oauth"}
多进程采集知乎
from multiprocessing import Pool
import json
import os
import requests
import time
from queue import Queue


class CrawlZH(object):
	def __init__(self, url, cookies):
		self.url = url
		self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'
        }
		self.cookies = cookies
		

	def get_json(self):

		session = requests.session()
		session.headers = self.headers
		requests.utils.add_dict_to_cookiejar(session.cookies, self.cookies)
		response = session.get(self.url)
		result = json.loads(response.text)
		print("当前子进程-{}运行结果:{}".format(os.getpid(), len(result['data'])))


def main(url, cookies):
	# print('当前子进程:{}'.format(os.getpid()))
	CrawlZH(url, cookies).get_json()

if __name__ == '__main__':
	# 这里cookies是你正常的登陆后从浏览器里面复制出来
	cookies = { ...
				}
	url_pattern = 'https://www.zhihu.com/api/v3/feed/topstory/recommend?desktop=true&page_number={}&limit=6'

	# 开启多进程采集 start === 
	print('母进程:{}'.format(os.getpid()))
	start = time.time()
	p = Pool()
	for page_number in range(1, 11):
		url = url_pattern.format(str(page_number))
		p.apply_async(main,  args=(url, cookies,))
	p.close()
	p.join()
	end = time.time()
	print(f'总共耗时:{(end-start)}')
	# 多进程 end ==== 
	

	# 多线程采集  start ===
	start = time.time()
	CrawlZHThread(cookies).run()
	end = time.time()
	print(f'总共耗时:{(end-start)}')

	# 多线程 end ==== 

结果:

多进程结果:
母进程:5024
当前子进程-6372运行结果:6
当前子进程-12984运行结果:6
当前子进程-4536运行结果:6
当前子进程-12924运行结果:6
当前子进程-12984运行结果:6
当前子进程-6372运行结果:6
当前子进程-12924运行结果:6
当前子进程-4536运行结果:6
当前子进程-12984运行结果:6
当前子进程-6372运行结果:6
总共耗时:2.6678614616394043
多线程采集知乎

# 简单 修饰器 用于无限循环
def run_forever(func):
	def wrapper(obj):
		while True:
			func(obj)
	return wrapper

class CrawlZHThread(object):
	def __init__(self, cookies):
		self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'
        }
		self.cookies = cookies
		self.url_pattern = 'https://www.zhihu.com/api/v3/feed/topstory/recommend?desktop=true&page_number={}&limit=6'
		self.url_queue = Queue()
	
	def add_url_to_queue(self):
		for i in range(1, 11):
			self.url_queue.put(self.url_pattern.format(str(i)))

	def get_json(self):
		while True:
			url = self.url_queue.get()
			session = requests.session()
			session.headers = self.headers
			requests.utils.add_dict_to_cookiejar(session.cookies, self.cookies)
			response = session.get(url)
			result = json.loads(response.text)
			print("当前子线程-{}运行结果:{}".format(threading.current_thread().name, len(result['data'])))
			self.url_queue.task_done()

	@run_forever
	def get_json_01(self):
		url = self.url_queue.get()
		session = requests.session()
		session.headers = self.headers
		requests.utils.add_dict_to_cookiejar(session.cookies, self.cookies)
		response = session.get(url)
		result = json.loads(response.text)
		print("当前子线程-{}运行结果:{}".format(threading.current_thread().name, len(result['data'])))
		self.url_queue.task_done()


	def run(self):
		url_t = threading.Thread(target=self.add_url_to_queue)
		url_t.start()
		# 开启多线程
		for i in range(4):
			t = threading.Thread(target=self.get_json)
			t.setDaemon(True)
			t.start()
		self.url_queue.join()

if __name__ == '__main__':
	# 这里cookies是你正常的登陆后从浏览器里面复制出来
	cookies = { ...
				}

	# 多线程采集  start ===
	start = time.time()
	CrawlZHThread(cookies).run()
	end = time.time()
	print(f'总共耗时:{(end-start)}')

	# 多线程 end ==== 

结果:

多线程结果:
当前子线程-Thread-3运行结果:6
当前子线程-Thread-4运行结果:6
当前子线程-Thread-5运行结果:6
当前子线程-Thread-2运行结果:6
当前子线程-Thread-3运行结果:6
当前子线程-Thread-4运行结果:6
当前子线程-Thread-5运行结果:6
当前子线程-Thread-2运行结果:6
当前子线程-Thread-3运行结果:6
当前子线程-Thread-4运行结果:6
总共耗时:2.4344863891601562

其中get_json与get_json_01结果是一样的,只不过一个用了修饰器,用修饰器可以提高可读性
对比以上两种采集方式,时间差不多,我只做获取页面数据,没有做后续数据处理,所以没有显著差异!!

注意本文的创作时间,后期页面源码调整,可能将采集不到数据,也属正常现象,本文主要目的是提供多进程、多线程爬虫的思想逻辑,仅供参考!!

Python制作的精美的一个网络爬虫播放器加本地播放器 Python自制播放器(Spider + Play + More) 阅读详情

相关推荐

python爬虫:python中使用多进程、多线程和协程对比和采集实践

在网络爬虫中,为了提高抓取效率,常常需要使用多进程、多线程或协程等技术来并发地发送请求和处理响应。以下是使用Python实现多进程、多线程和协程的爬虫样例。使用 asyncio 和 aiohttp 实现协程爬虫,通过事件循环高效地管理并发任务。使用 multiprocessing 模块实现多进程爬虫,每个进程独立处理一部分任务。多进程是指在操作系统中同时运行多个独立的进程。使用 threading 模块实现多线程爬虫,多个线程共享同一进程的资源。多线程是在同一进程内创建多个线程,共享进程的内存空间。

数据知道的博客 9452

python3 提高爬虫采集速度 方案三:多进程 + 队列

多进程使用注意点 1.多进程说明 进程:一个程序运行起来后,代码+用到的资源 称之为进程,它是操作系统分配资源的基本单元。 2.使用多进程后的通信 多进程中使用普通的队列模块无法实现进程间的通讯,因为进程是系统分配资源的基本单元. 对应的需要使用multiprocessing提供的JoinableQueue模块,其使用过程和在线程中使用的queue方法相同 案列使用说明 queue = Queue...

RedHot_Thinker 904

Educoder 第1关:多线程、多进程爬虫

【代码】Educoder 第1关:多线程、多进程爬虫。

weixin_46026136的博客 2294

Python如何在网络爬虫程序中使用多进程进行数据爬取

本文介绍了python在网络爬虫程序中如何使用多进程的方式进行数据爬取

hubing_hust的专栏 1万+

Python网络爬虫项目开发实战:如何处理并发下载

在Python网络爬虫项目开发中,为了提高数据抓取的效率和速度,往往需要实现并发下载。并发下载是指同时处理多个下载任务,而不是按照顺序逐一执行。这样做的好处在于能够充分利用系统的多核处理器资源,减少网络等待时间,从而显著提升爬虫的整体性能。

一个好知识的传播者 937

并行爬虫中的多线程与多进程实践解析

本文深入探讨了Python在并行爬虫开发中的多线程与多进程技术应用。通过对比两种技术在实际爬虫项目中的使用,分析了它们各自的优势和局限性。文章详细解读了如何使用threading和multiprocessing模块来实现高效的数据抓取,同时展示了如何在不同进程间共享和管理数据,确保爬虫的高效、稳定运行。

weixin_42518334的博客 464

Python-多进程检索

利用多进程检索说句,求平均数

详解电路设计中的RC电路

​ 一、什么是RC电路 RC电路是指由电阻R和电容C组成的电路,它是脉冲产生和整形电路中常用到 的电路。 常见的RC充、放电电路、RC积分电路合RC微分电路接下来详细讲解。 二、RC充、放电电路 RC充、放电电路如下图所示,下面通过充电和放电两个过程来分析此电路。 ​RC充、放电电路图 (1)RC充电电路 RC充电电路图如下图(a)所示 RC充电电路图及充电曲线图 ​由上图分析: 将上图a中开关S置于“1”处,电源E开始通过电阻R对电容C充电,由于刚开始充电时电容两端没有..

IT xiaobai 4万+

Python的多线程爬虫详解

Python 提供了两个支持多线程的模块,分别是 _thread 和 threading。其中 _thread 模块偏底层,它相比于 threading 模块功能有限,因此推荐大家使用 threading 模块。

Python966的博客 4395

Innovus实战:5分钟搞定postRoute阶段冗余hold buffer的自动清理(附PHC识别技巧)

本文分享了在数字IC后端设计中使用Innovus工具,于postRoute阶段自动清理冗余hold buffer的实战技巧。通过配置时序感知的面积回收模式,可在5分钟内安全移除非关键路径上的PHC缓冲器,有效优化芯片面积与功耗,并附有PHC识别与验证方法。

moon9的博客 400

心电图机原理及电路超详细讲解

前置心电放大电路(虚线框:这是隔离电路的分界,在隔离电路分析中知道,完整隔离包括信号隔离(脉宽调制)、控制信号隔离(光电耦合)和电源隔离)后级放大电路。

fcxgfdjy的博客 2万+

【Python 爬虫】多线程爬取

文章目录前言一、多进程库(multiprocessing)二、多线程爬虫三、案例实操四、案例解析1、获取网页内容2、获取每一章链接3、获取每一章的正文并返回章节名和正文4、将每一章保存到本地5、多线程爬取文章 前言 简单的爬虫只有一个进程、一个线程,因此称为单线程爬虫。单线程爬虫每次只访问一个页面,不能充分利用计算机的网络带宽。一个页面最多也就几百KB,所以爬虫在爬取一个页面的时候,多出来的网速和从发起请求到得到源代码中间的时间都被浪费了。如果可以让爬虫同时访问10个页面,就相当于爬取速度提高了10倍..

懂得一千零一种,赋予你失败的方法! 2万+

车辆TBOX科普 第69次 TBOX行业发展趋势与就业前景深度解析

TBOX技术革新驱动汽车智能化发展 Telematics BOX(TBOX)正快速从车辆状态监控器进化为整车智能核心,市场年增速超25%,2025年规模将达150亿美元。技术呈现四大革新方向:5G与V2X集成实现多模通信网关,支持10-20Gbps高速传输;多模GNSS融合定位精度达厘米级,北斗系统提供独特优势;边缘计算架构使TBOX具备本地AI处理能力,减少95%数据上传;硬件安全模块(HSM)成为标配,满足EVITA标准的安全需求。这些技术突破正重塑TBOX架构,使其从单纯通信管道升级为智能网联汽车的关

IT深耕十余载,大道之简 1828

python多线程爬虫和异步爬虫_Python多线程、异步+多进程爬虫实现代码

安装Tornado省事点可以直接用grequests库,下面用的是tornado的异步client。 异步用到了tornado,根据官方文档的例子修改得到一个简单的异步爬虫类。可以参考下最新的文档学习下。pip install tornado异步爬虫#!/usr/bin/env python# -*- coding:utf-8 -*-import timefrom datetime import ...

weixin_39586235的博客 506

2026年数学建模国赛C题利器:层次分析法与主成分分析在统计建模中的应用

本文系统探讨了层次分析法(AHP)与主成分分析(PCA)在数学建模竞赛,特别是全国大学生数学建模竞赛C题中的联合应用策略。通过理论阐述、方法对比和案例实践,本文揭示了两种方法从“数据降维”到“决策评价”的完整分析链条,提出了“PCA+AHP”协同框架,并通过实际算例验证了该框架在解决复杂评价类问题中的有效性和优越性。研究表明,将PCA的客观降维能力与AHP的主观决策优势有机结合,能够显著提升统计建模的科学性、合理性和解释力,是应对日益复杂的竞赛题目的重要方法论工具。关键词:层次分析法;主成分分析;数学建模。

YOLO 41

第3讲:单端传输线的时域TDR仿真(基于实战的第一次仿真视角切换)

本文为CST仿真系列教程的第3讲,主要介绍传输线阻抗(TDR)的两种仿真方法:基于S参数的频域计算和基于高斯脉冲的时域计算。文章详细演示了在CST PCB Studio中修改电容参数、设置TDR仿真参数(包括截止时间和采样点数)的操作步骤,并通过对比实验展示TVS寄生电容对阻抗曲线的影响。最后将两种TDR方法的结果进行对比,验证了两种方法的一致性。本教程适合硬件工程师通过时域波形直观分析传输线阻抗特性,是信号完整性分析的重要技能。

一只豌豆象的博客 228

python爬虫用多线程还是多进程_Python多线程、异步+多进程爬虫实现代码

安装Tornado省事点可以直接用grequests库,下面用的是tornado的异步client。 异步用到了tornado,根据官方文档的例子修改得到一个简单的异步爬虫类。可以参考下最新的文档学习下。pip install tornado异步爬虫#!/usr/bin/env python# -*- coding:utf-8 -*-import timefrom datetime import ...

weixin_39702483的博客 984

RHCA III之路---EX436-1

由于ha这门课有大量命令需要在3个节点上同步执行.如果执行history会出现前面数字,复制多行会有些麻烦.lab环境是nodea,nodeb,nodec 考试环境是node1,node2,node3。就可以快速将历史命令实现可多行复制,当然也可以用awk进行分割,个人喜好随意。技巧只能加快答题速度,对考试得分帮助不大。确认3个红框内容一致,且没报错即可。再执行一个histrory。3个node节点上运行。这样就能1次复制3行。

Q先生 1002

python多线程异步爬虫-Python多线程、异步+多进程爬虫实现代码

安装Tornado省事点可以直接用grequests库,下面用的是tornado的异步client。 异步用到了tornado,根据官方文档的例子修改得到一个简单的异步爬虫类。可以参考下最新的文档学习下。pip install tornado异步爬虫#!/usr/bin/env python# -*- coding:utf-8 -*-import timefrom datetime import ...

weixin_39608116的博客 562

【系统分析师】2025年下半年真题:综合知识-答案及详解(回忆版)

本文摘要包含系统分析师考试相关题目解析,主要涵盖软件工程、数据库、网络协议和项目管理等知识点。内容包括:软件再工程与逆向工程的区别(D);GNU GPL开源协议特性(A);TCP/IP协议分层(A、B);数据库范式判定(A、B);前导图进度管理工具(C);系统规划中的数据类识别方法(B、D);关系代数除运算(C);CMM优化级特征(A);回归测试重要性(C)。这些解析帮助理解核心概念和考试重点。

数据知道的博客 6717

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

python多线程和多进程的区别_多线程、多进程爬虫

一、前言1、并发和并行并发:在一个时间段内发生若干事件的情况(单个CPU) 并行:在同一时间发生若干事件的情况(多个CPU)2、同步和异步同步:指并发和并行的各个任务之间不是独自运行的,任务之间有一定的交替顺序,可能在运行完一个任务得到结果之后,另一个任务才会开始运行 异步:并发或并行的各个任务可以独立运行,一个任务的运行不受另一个任务的影响3、多线程与多进程爬虫多线程、多进程、多协程网络爬虫在进...

weixin_39538962的博客 236

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Python 开发(18):多线程与多进程 - 提升程序运行效率

在现代计算中,利用多线程与多进程实现并发或并行操作是提升程序效率的重要手段。Python 提供了强大的标准库,如threading和,方便开发者实现多线程和多进程编程。本文将详细解析多线程与多进程的概念、差异、适用场景,以及在 Python 中的具体实现与优化策略。并发(Concurrency):任务在时间上交替执行,通常应用于 IO 密集型任务。并行(Parallelism):任务同时执行,适用于多核 CPU 的计算密集型任务。threading:用于多线程操作,轻量但受 GIL 影响。

一名热衷于技术的全栈开发者,专注于前端与后端的全面技术探索。在这里,我将分享我在技术领域的学习与成长,助力更多开发者的进步。 874

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

从入门到精通:网络爬虫开发实战总结

学习是一种持续不断的过程,无论在什么领域,都需要不断地努力和探索。在这段爬虫学习历程中,我不仅获得了丰富的知识和技能,也结交了很多志同道合的朋友和粉丝,他们对我的学习和进步都提供了极大的支持和鼓励,支持我继续写下去。 总的来说,这段时间的学习和写作让我认识到了自己的不足和缺陷,也让我更加坚定了继续学习和进步的决心。我相信,在未来的学习和工作中,这段经历将成为我前行的动力和支撑。在这里,我将过去写过的爬虫文章总结一下,不仅是在爬虫学习这里留下一个里程碑,也是为了能够总结一下阶段性学习成果。

weixin_50804299的博客 6560

网络爬虫(一):爬虫基础原理

一、学习前言 学习完Python语言后,总觉得有难以用武之地,纸上学来终觉浅,绝知此事要躬行,如果不加以使用就很容易忘记,为了加深python语言的记忆和理解,我选择学习网络爬虫的技术来进一步提升自己的能力。 其次觉得爬虫是一项必须掌握的技术,有很多用武之地,看似简单却趣味无穷,入门容易但真的想做好也是需要下一番功夫的。经过我的一番了解和学习,爬虫技术也有很深的奥秘,爬虫技术也很容易失效,企业...

lancerFm的博客 1935

关于python的多进程和多线程

原因:I/O密集型任务(如网络请求、文件读写、数据库查询)涉及大量等待时间,在等待I/O操作时,线程会释放GIL,允许其他线程运行。因此,多线程可以在单线程内高效处理并发I/O操作,尽管不实现真正的并行。多进程(Multiprocessing)适用于计算密集型任务。多线程(Threading)适用于I/O密集型任务。适用场景:网络爬虫、服务器请求处理、文件操作等。关于python的多进程和多线程。

2401_86968032的博客 320
上一篇: 浅谈python多线程与多进程
下一篇: MySQL增删改查报(INSERT、DROP、UPDATE、SELECT、CREATE)command denied to user 'xx'@'localhost' for table 'test'
Thomas_Lean
博客等级 码龄9年 58粉丝 72原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值