下面是详细的攻略:
对于一些需要收集数据的任务,并发的采集方式无疑是对效率的一大提升。Python语言提供了多线程编程的支持,本文将会介绍两种使用Python实现多线程采集的方式并提供相应的代码。
第一种实现方式相对来说比较简单理解,我们可以直接使用Thread
类来创建新的线程并运行。
import threading
import requests
def main():
urls = ["http://example.com/",
"http://example.com/news",
"http://example.com/about",
"http://example.com/contact",
"http://example.com/sitemap",
"http://example.com/blog",
"http://example.com/jobs",
"http://example.com/feedback"]
threads = []
for url in urls:
t = threading.Thread(target=fetch_url, args=(url,))
threads.append(t)
t.start()
for t in threads:
t.join()
def fetch_url(url):
print("Fetching {0}".format(url))
try:
r = requests.get(url)
print("{0}: {1}".format(url, r.status_code))
except requests.exceptions.RequestException as e:
print("{0}: {1}".format(url, e))
使用上述代码,简单来说,我们首先定义了一个列表urls
,并在遍历该列表的过程中,创建了多个线程,每个线程都调用了fetch_url
函数,并传入了当前的URL。接着,我们在主线程内通过join
等待其他线程的结束。
另外一种实现方式相对来说更加高级,可以同时限制线程数量来进一步提升效率,我们可以使用Python的线程池来实现。
import concurrent.futures
import requests
def main():
urls = ["http://example.com/",
"http://example.com/news",
"http://example.com/about",
"http://example.com/contact",
"http://example.com/sitemap",
"http://example.com/blog",
"http://example.com/jobs",
"http://example.com/feedback"]
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
future_to_url = {executor.submit(fetch_url, url): url for url in urls}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
print("{0}: {1}".format(url, data))
except Exception as exc:
print("{0}: {1}".format(url, exc))
def fetch_url(url):
print("Fetching {0}".format(url))
try:
r = requests.get(url)
return r.status_code
except requests.exceptions.RequestException as e:
return str(e)
使用以上代码,我们可以看到,在主函数内,我们首先定义了一个URL列表urls
,并使用线程池ThreadPoolExecutor
创建了一个最大线程数为5的线程池。随后,我们在使用submit
方法向线程池提交任务时,还为每个任务使用了一个dict
来存储其对应的URL地址,方便我们后续的输出。最后,我们在对future
进行as_completed
迭代的过程中获取了每个任务返回的结果。
以上两种多线程采集Python代码的方式并不是唯一的选择,而是较为常用且简便的方式之一。通过合理使用多线程的方式来提升程序的效率,是Python程序员们需要重点考虑的一项工作。