抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

本文讲解Python多线程编程。

趣味小游戏

点击进入爬虫闯关1

image-20200412223104465

你需要在每一个页面获取数字,然后将其添加到URL后,依次循环,直到最终的成功页面。当然我们就利用爬虫来完成啦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
import re

url = 'http://www.heibanke.com/lesson/crawler_ex00/'
res = requests.get(url)
print(res.status_code)

#当HTTP状态码为200时,表示页面返回正常
while res.status_code == 200:
num = re.findall(r'\d{5}',res.text)
#分析页面得知数字在正则匹配后的第二个,将其取出并置于网址后面
url = 'http://www.heibanke.com/lesson/crawler_ex00/' + num[1]
print(url)
res = requests.get(url)

print(url)
1
2
3
4
5
6
7
8
9
10
11
http://www.heibanke.com/lesson/crawler_ex00/33818
http://www.heibanke.com/lesson/crawler_ex00/30867
http://www.heibanke.com/lesson/crawler_ex00/44513
http://www.heibanke.com/lesson/crawler_ex00/53577
http://www.heibanke.com/lesson/crawler_ex00/48950
http://www.heibanke.com/lesson/crawler_ex00/69524
http://www.heibanke.com/lesson/crawler_ex00/36499
....(中间省略,太多了)
http://www.heibanke.com/lesson/crawler_ex00/21070
http://www.heibanke.com/lesson/crawler_ex00/14042
http://www.heibanke.com/lesson/crawler_ex00/14042

image-20200412223724478

线程和进程

进程:进程是程序的一次执行。每一个进程都有自己的地址空间、内存、数据栈及其他记录其运行轨迹的辅助数据。

线程:所有的线程运行在同一个进程中,共享相同的运行环境。线程有开始顺序执行和结束三个部分。

什么?完全听不懂在说什么?看看下面的介绍吧!

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。

thread模块

start_new_thread(function, args kwargs=None)

产生一个新的线程,在新的线程中用指定的参数和可选的kwargs来调用这个函数。

注意:使用该方式时,一定要家time.sleep(),否则每个线程将可能不执行。

方法缺点:在遇到较复杂的问题时,线程数不易控制。

注意:python3中,由于thread有两个很致命的问题,所以python3更推荐用threading代替thread,所以,thread被改名为_thread。

1
2
3
4
5
6
7
8
9
10
11
12
import _thread
import time

def fun1():
print('hello world! %s\n' % time.ctime())

def main():
_thread.start_new_thread(fun1, ())
_thread.start_new_thread(fun1, ())
time.sleep(2)

main()

小脚本–对C段所用信息进行检测

  1. 检测是否ping的通的返回内容
1
2
3
4
5
6
7
8
9
10
11
import _thread
import time
from subprocess import Popen,PIPE

def ping_check():
check = Popen(['/bin/bash', '-c', 'ping -c 2 '+'127.0.0.1'],stdin=PIPE,stdout=PIPE)
data = check.stdout.read()
if 'ttl' in str(data):
print('UP')

ping_check()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ping 成功返回内容
b'PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.043 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.098 ms

--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.043/0.071/0.098/0.028 ms

# ping 失败返回内容
b'PING 127.1.0.1 (127.1.0.1): 56 data bytes
Request timeout for icmp_seq 0

--- 127.1.0.1 ping statistics ---
2 packets transmitted, 0 packets received, 100.0% packet loss\n'
  1. 对C段所有信息检测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import _thread
import time
from subprocess import Popen,PIPE

def ping_check(ip):
check = Popen(['/bin/bash', '-c', 'ping -c 2 '+ip],stdin=PIPE,stdout=PIPE)
data = check.stdout.read()
if 'ttl' in str(data):
print(ip)

def main():
for i in range(1,255):
ip = '185.199.108.'+str(i)
_thread.start_new_thread(ping_check, (ip,))
time.sleep(0.1)

main()
1
2
3
4
185.199.108.1
185.199.108.2
185.199.108.3
...

threading模块

threading模块基本构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import threading
import time

# 定义函数
def fun1(name):
print(name + time.ctime(),end='\n')

def main():
# 设置线程集合
threads = []
keys = ['张三 ', '李四 ', '王五 ']
threads_count = len(keys)

# 设置线程内容某个函数
for i in range(threads_count):
t = threading.Thread(target=fun1, args=(keys[i],))
threads.append(t)

#设置线程开始
for i in range(threads_count):
threads[i].start()

#设置线程结束
for i in range(threads_count):
threads[i].join()

main()
张三 Mon Apr 13 15:41:37 2020
李四 Mon Apr 13 15:41:37 2020
王五 Mon Apr 13 15:41:37 2020

Queue模块

1
2
3
4
5
6
7
8
import queue

q = queue.Queue()

for i in range(10):
q.put(i)

q.empty(), q.qsize()
(False, 10)

取出Queue队列的元素

1
2
while q.empty() == False:
print(q.get(), end=' ')
0 1 2 3 4 5 6 7 8 9 

Queue + Threading 解决C段信息探测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import threading
import queue
from subprocess import Popen,PIPE



class fun1(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self._queue = queue

def run(self):
while not self._queue.empty():
ip = self._queue.get()
ping_check(ip)

def ping_check(self, ip):
check = Popen(['/bin/bash', '-c', 'ping -c 2 '+ip],stdin=PIPE,stdout=PIPE)
data = check.stdout.read()
if 'ttl' in str(data):
print(ip)

def main():
threads = []
threads_count = 200

q = queue.Queue()

for i in range(1,255):
q.put('185.199.108.'+str(i))

for i in range(threads_count):
threads.append(fun1(q))

for i in threads:
i.start()

for i in threads:
i.join()

main()
1
2
3
4
5
6
7
8
9
185.199.108.127
185.199.108.37
185.199.108.31
185.199.108.33
185.199.108.32
185.199.108.30
185.199.108.12
185.199.108.36
........

评论