转载:蚂蚁学python 网址:【【2021最新版】Python 并发编程实战,用多线程、多进程、多协程加速程序运行】 https://www.bilibili.com/video/BV1bK411A7tV/?p=8&share_source=copy_web&vd_source=d0ef3d08fdeef1740bab49cdb3e96467
实战案例:
对于网络爬虫来讲是属于I/O 操作,比较适用多线程爬虫,多进程就不太适合,如果对协程分支异步编程asyncio 较为熟悉的话,也很方便。
小项目任务:获取博客园文章标题,以及访问连接,当然你也可以去访问本网站csdn
需要改变的代码部分,访问网址,以及通过正则提取网页数据
网页请求代码:(这里只是通过单线程串行的方式获取了一页数据)
blog_spider 文件(先创建这样以 blog_spider 命名的python文件)
import requests
import re
urls = [
f"https://www.cnblogs.com/#p{page}"
for page in range(1,51)
]
def craw(url):
r = requests.get(url).text
return r
def parse(html):
url_Data = re.findall('<a class="post-item-title" href="(.*?)" target="_blank">(.*?)</a>',html)
return url_Data
if __name__ == '__main__':
for result in parse(craw(urls[3])):
print(result)
在创建一个名为 :thread_pool python文件
import concurrent.futures
import pprint
import blog_spider
#这里是导入自己写的一个包,我的理解是封装成一个包或者是模块可以供其他python文件调用
with concurrent.futures.ThreadPoolExecutor() as pool:
htmls = pool.map(blog_spider.craw,blog_spider.urls)
htmls = list(zip(blog_spider.urls,htmls))
for url,html in htmls:
print(url,len(html))
print("craw over")
with concurrent.futures.ThreadPoolExecutor()as pool:
futures = {}
for url,html in htmls:
future = pool.submit(blog_spider.parse,html)
futures[future] = url
for future in concurrent.futures.as_completed(futures):
url = futures[future]
print(url,future.result())
关于多进程和多线程的关系:
进程适用cpu密集型,线程适用IO密集型,线程是由进程所创建的,创建一个进程,会自动帮你创建一个主线程,由主线程可以创建其他子线程,线程的数量是有限的,因为python由于 GIL(全局事务解释器)锁的限定,无论你是多核cpu但是只允许你在同一时间执行一个线程,在请求IO时,线程是在不定时进行切换的会损耗一定的资源,如果线程数量过多,线程的切换开销过大,这样就会抵消多线程带来的速度优势。
第五十页请求到的数据
看看获取的数据是否正确
检查了一下,的确数据不对,有可能是反扒机制识别,等待时间,和网址信息填充存在问题,我已经排除,我太忙了有时间我会在看看。