python初学者爬虫教程(五)提升爬虫的速度
并发,并行,同步,异步
-
并发指在一个时间段内发生若干事件的情况,各个任务时间段短,经常切换,所以感觉是“同时”进行。
-
并行值在同一时刻发生若干事件的情况,真正的同时
-
同步,各个任务不是独自运行的,任务之间有交替顺序,运行完一个任务后才运行另一个。
-
异步,各个任务独立运行
多线程爬虫
多线程爬虫是以并发方式执行。即通过进程的快速切换来加快爬虫速度。
单线程例子
通过访问1000个网站,来统计时间
由于运行时间较长,不展示结果
txt文本数据在这里
import requests
import time
link_list = []
with open('../alexa.txt', 'r') as file:
file_list = file.readlines()
for each in file_list:
link = each.split('\t')[1]
link = link.replace('\n', '')
link_list.append(link)
start = time.time()
for each in link_list:
try:
r = requests.get(each)
print(r.status_code, each)
except Exception as e:
print(e)
end = time.time()
print("串行总时间为", end - start)
python中的多线程
函数式
调用_thread
模块中的start_new_thread
创建新线程
import _thread
import time
# 为线程定义一个函数
def print_time(threadName, delay):
count = 0
while count < 3:
time.sleep(delay)
count += 1
print(threadName, time.ctime())
if __name__ == '__main__':
try:
_thread.start_new_thread(print_time, ("Thread-1", 1))
_thread.start_new_thread(print_time, ("Thread-2", 2))
print("Main Finished")
except:
print("Error: unable to start thread")
while 1:
pass
结果:
可以看到,主线程先完成。然后两个新的线程还会继续运行。
_thread.start_new_thread(function, args[, kwargs])
启动一个线程,并返回其标识符。线程会用 args 作为参数(必须是元组)执行 function 函数。可选的 kwargs 参数使用字典来指定有名参数。当函数返回时,线程会静默退出,当函数由于未处理的异常而中止时,会打印一条堆栈追踪信息,然后该线程会退出(但其他线程还是会继续运行)。
类包装式
threading 模块基于_thread提供了更易用的高级多线程 API。
调用Threading
库创建线程,从threading.Thread
继承
-
start()
开始线程活动。
它在一个线程里最多只能被调用一次。它安排对象的 run() 方法在一个独立的控制进程中调用。 -
run()
代表线程活动的方法。 -
join(timeout=None)
等待,直到线程终结。这会阻塞调用这个方法的线程,直到被调用 join() 的线程终结 – 不管是正常终结还是抛出未处理异常 – 或者直到发生超时,超时选项是可选的。
当 timeout 参数存在而且不是 None 时,它应该是一个用于指定操作超时的以秒为单位的浮点数(或者分数)。因为 join() 总是返回 None ,所以你一定要在 join() 后调用 is_alive() 才能判断是否发生超时 – 如果线程仍然存活,则 join() 超时。
当 timeout 参数不存在或者是 None ,这个操作会阻塞直到线程终结。
一个线程可以被 join() 很多次。 -
is_alive()
返回线程是否存活。 -
getName()
-
setName()
import threading
import time
class myThread(threading.Thread):
def __init__(self, name, delay):
threading.Thread.__init__(self)
self.name = name
self.delay = delay
def run(self):
print("Starting " + self.name)
print_time(self.name, self.delay)
print("Exiting " + self.name)
def print_time(threadName, delay):
counter = 0
while counter < 3:
time.sleep(delay)
print(threadName, time