首页 > 系统相关 >python爬虫3-多进程多线程协程

python爬虫3-多进程多线程协程

时间:2024-07-04 20:43:00浏览次数:16  
标签:__ 协程 name python url import 多线程 loop asyncio

多进程和多线程

from multiprocessing import Process
import threading

def process_worker():
    for i in range(200):
        print(f"Process worker {i}")

def thread_worker():
    for i in range(200):
        print(f"Thread worker {i}")

if __name__ == '__main__':
    # 创建并启动一个进程
    p = Process(target=process_worker)
    p.start()
    # p.join() # 阻塞主线程(或主进程),直到被调用的线程(或进程)完成执行。

    # 创建并启动一个线程
    t = threading.Thread(target=thread_worker)
    t.start()
    # t.join() # 阻塞主线程(或主进程),直到被调用的线程(或进程)完成执行。

    for i in range(200):
        print(f"主进程 {i}")

线程池和进程池

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time

def io_task(n):
    print(f'IO Task {n} starting')
    time.sleep(2)
    print(f'IO Task {n} finished')

def cpu_task(n):
    print(f'CPU Task {n} starting')
    result = sum(i*i for i in range(10**6))
    print(f'CPU Task {n} finished with result {result}')

if __name__ == '__main__':
    with ThreadPoolExecutor(max_workers=2) as thread_pool, ProcessPoolExecutor(max_workers=2) as process_pool:
        thread_futures = [thread_pool.submit(io_task, i) for i in range(4)]     # 循环四次(从 i=0 到 i=3),每次循环调用 io_task 函数并传递当前的循环计数 i 作为参数。
        process_futures = [process_pool.submit(cpu_task, i) for i in range(4)]  # 循环四次(从 i=0 到 i=3),每次循环调用 cpu_task 函数并传递当前的循环计数 i 作为参数。

    print("Main thread continues")

豆瓣实例

import requests
from lxml import etree
import re
import csv
from concurrent.futures import ThreadPoolExecutor

csvfile = open("douban4.csv",mode="w",encoding="utf-8")
csvwriter = csv.writer(csvfile)


def download_one_page(url):
    # 网页源码
    # 头部信息
    headers = {
        'User-Agent': 'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
    }
    resp = requests.get(url,headers=headers)

    html = etree.HTML(resp.text)
    # 使用 XPath 选取所有 title 元素的文本内容
    lis = html.xpath('//*[@id="content"]/div/div[1]/ol/li')

    for li in lis:
        name = li.xpath("./div/div[2]/div[1]/a/span[1]/text()")[0]  # 名字
        year = li.xpath("./div/div[2]/div[2]/p[1]/text()[2]")[0]  # 年份
        rating = li.xpath("./div/div[2]/div[2]/div/span[2]/text()")[0]  # 评分
        year = re.findall(r'\b\d{4}\b', year)[0]  # 对年份进行处理
        # 保存为csv文件
        csvwriter.writerow([name, year, rating])
    print(url,"提取完毕")



if __name__ == '__main__':

    with ThreadPoolExecutor(3) as thread_pool:
        for i in range(10):
            thread_pool.submit(download_one_page,f'http://movie.douban.com/top250?start={i*25}&filter=')
    print("over")

协程

协程(coroutine)是一种用于并发编程的构造,允许你在等待某些操作完成时进行其他工作。协程在处理 I/O 绑定任务(如网络请求或文件读取)时特别有用,因为它们可以在一个任务等待完成时切换到另一个任务。

实例

import asyncio

async def say(what, when):      # async 关键字 用来定义一个协程.
    await asyncio.sleep(when)   # await 关键字 用来挂起阻塞方法的执行。
    print(what)

async def main():
    # 并行执行多个协程
    await asyncio.gather(
        say("First", 2),
        say("Second", 1),
        say("Third", 3)
    )

if __name__ == '__main__':
    asyncio.run(main()) #运行协程

异步爬取图片

import asyncio
import aiohttp
import os

urls = [
    "https://p0.ssl.qhimgs1.com/sdr/400__/t01c3a6a8abd00f35a4.jpg",
    "https://p2.ssl.qhimgs1.com/sdr/400__/t01f2bf1a12bb90de88.jpg",
    "https://p1.ssl.qhimgs1.com/sdr/400__/t0101cc32a15d91a3f7.jpg"
]


async def aiodownload(url):
    name = url.rsplit("/", 1)[1]  # 提取文件名
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            with open(name, mode="wb") as f:
                f.write(await resp.content.read())  # 读取内容为异步,需要await
    print(name, "over")


async def main():
    tasks = [aiodownload(url) for url in urls]
    await asyncio.gather(*tasks)  # 使用 asyncio.gather() 代替 asyncio.wait()


if __name__ == '__main__':
    # 在 Windows 上使用 SelectorEventLoop
    if os.name == 'nt':
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

    try:
        asyncio.run(main())  # 运行协程
    except RuntimeError as e:
        if str(e) == "Event loop is closed":
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            loop.run_until_complete(main())

百度西游记异步爬取

import requests
import asyncio
import aiohttp
import aiofiles
import os
import json

async def aiodownload(cid, b_id, title):
    # 拼接url
    data = {
        "book_id": b_id,
        "cid": f"{b_id}|{cid}",
        "need_bookinfo": 1
    }
    data = json.dumps(data)
    url = f"https://dushu.baidu.com/api/pc/getChapterContent?data={data}"
    
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            # 异步获取网页数据
            dic = await resp.json()
            
            if 'data' in dic and 'novel' in dic['data'] and 'content' in dic['data']['novel']:
                content = dic['data']['novel']['content']
                # 异步写入文件
                async with aiofiles.open(os.path.join('novel', title + '.txt'), mode="w", encoding='utf-8') as f:
                    await f.write(content)
            else:
                print(f"Failed to get content for chapter {title}")

# 实现同步获取目录
async def getCatalog(url, b_id):
    resp = requests.get(url)
    dic = resp.json()
    tasks = []
    # 获取目录并添加协程任务
    for item in dic['data']['novel']['items']:
        title = item['title']
        cid = item['cid']
        
        # 准备异步任务
        tasks.append(aiodownload(cid, b_id, title))
	
    # 异步执行任务
    await asyncio.gather(*tasks)

if __name__ == '__main__':
    b_id = "4306063500"
    url = f'https://dushu.baidu.com/api/pc/getCatalog?data={{"book_id":"{b_id}"}}'

    # 创建novel目录
    if not os.path.exists('novel'):
        os.makedirs('novel')

 # 在 Windows 上使用 SelectorEventLoop
    if os.name == 'nt':
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    try:
        asyncio.run(getCatalog(url, b_id))
    except RuntimeError as e:
        if str(e) == "Event loop is closed":
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            loop.run_until_complete(getCatalog(url, b_id))

标签:__,协程,name,python,url,import,多线程,loop,asyncio
From: https://www.cnblogs.com/noahze/p/18284627

相关文章

  • Python的分支结构的教学
    一.pass的介绍:1、pass在执行过程中表示的含义:“暂时跳过”,pass是一种空操作,解释器执行到它的时候,除了检查语法是否合法,什么也不做就直接跳过。它跟return、break和continue之类的非空操作相比,最大的区别是它不会改变程序的执行顺序。它就像我们写的注释,除了占用一行代码......
  • python实现扑克游戏 - 抽鬼牌 和 21点
    poker_gamespython实现扑克游戏:抽鬼牌和21点-PythonImplementationofPokerGames:DrawingGhostCardsandBlackjackpoker模块首先,定义一个扑克模块,后面的包括以后的扑克牌游戏,都可以调用这个模块这个模块可以实现:卡牌、扑克牌组发牌、洗牌玩家摸牌、出牌等......
  • Python从0到100(三十三):xpath和lxml类库
    1.为什么要学习xpath和lxmllxml是一款高性能的PythonHTML/XML解析器,我们可以利用XPath,来快速的定位特定元素以及获取节点信息2.什么是xpathXPath,全称为XMLPathLanguage,是一种用于在XML文档中进行导航和数据提取的语言,可用来在HTML\XML文档中对元素和属性进行遍......
  • python+flask计算机毕业设计的图书管理系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在数字化与信息化日益深入的今天,图书管理系统的开发与应用已成为图书馆管理工作中的重要一环。传统的图书管理方式,如手工登记、纸质借阅记......
  • python+flask计算机毕业设计二手图书零售系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着信息时代的到来,知识的传播与获取方式发生了深刻变革,图书作为文化传承和知识积累的重要载体,其数量与日俱增。然而,在传统图书市场饱和、......
  • 工具篇:01用python的request爬虫
    工具篇:01用python爬虫爬虫爬虫的概念尝试用python爬虫爬虫爬虫的概念爬虫我认为就是用代码获取数据经过我的上网查找得出结论:爬虫是一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。尝试用python爬虫用两种爬虫方式第一种是request,第二种scra......
  • Authlib,一个终极利器 Python 库专注于提供各种认证和授权解决方案
    目录01什么是Authlib?Authlib简介为什么选择Authlib?安装与配置02Authlib的基本用法实现OAuth2客户端1、创建OAuth2客户端 2、获取访问令牌3、使用访问令牌访问资源实现OAuth2服务器1、创建OAuth2服务器2、实现授权端点3、实现资源端点03Authlib......
  • 《Python 第三方模块包安装指南》
    在Python编程中,第三方模块包极大地丰富了其功能,让我们能够更高效地完成各种任务。下面将为您详细介绍如何安装Python的第三方模块包。一、使用pip命令安装pip 是Python的包管理工具,大多数情况下,我们可以通过以下命令来安装第三方模块包: pipinstall模块包名称......
  • Django与Flask的比较与应用场景 —— Python
    PythonWeb开发框架详解:Django与Flask的比较与应用场景在Python的Web开发领域,Django和Flask是两个非常受欢迎的框架。它们各自具有独特的特点和优势,适用于不同的开发场景。本文将对这两个框架进行详细的解释和比较,并给出一些实用的开发建议。一、Django框架概述Django是一......
  • 2024年华为OD机试真题- 电脑病毒感染-(C++/Java/python)-OD统一考试(C卷D卷)
     2024华为OD机试真题目录-(B卷C卷D卷)-【C++JavaPython】   题目描述一个局域网内有很多台电脑,分别标注为0~N-1的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t表示。其中网络内一台电脑被病毒感染,求其感染网络内所有的电脑最少需要多长时间。......