python爬虫基础--多线程--多进程--协程

目录

终于考完试了,自由了哈哈哈哈哈

知识点回顾

详看:python爬虫基础--json数据和jsonpath--多线程原理_我还可以熬_的博客-CSDN博客

多线程

多线程--方法版

 多线程--类版

 多进程

multiprocessing模块

Manager类,实现数据共享

进程池的使用

多进程--方法版

多进程-- 进程池版

 协程

安装第三方模块


终于考完试了,自由了哈哈哈哈哈

本来早该完成的这篇,然后期间考试,耽误了很久!!!今天考完了!!!!!!!!!

知识点回顾

json数据

jsonpath的使用

多线程原理

详看:python爬虫基础--json数据和jsonpath--多线程原理_我还可以熬_的博客-CSDN博客

下面的例子均用虎扑网为例!!!

多线程

多线程--方法版

需要用到模块:

import requests
from fake_useragent import UserAgent
from time import sleep
from queue import Queue
from threading import Thread

定义一个函数spider()

判断URL网站是否不为空:

    while not url_queue.empty():
        url = url_queue.get()  

在后面要判断URL网站是否能访问成功:

        if resp.status_code == 200:
            print(f'成功获取了:{url}')

 另外为了不过于频繁的在短时间的产生过多的访问,要添加一个sleep:

        sleep(3)

使用线程来处理 URL队列中的url,然后将url返回的结果保存在另一个队列中,其他线程读取数据,并写入文件中。

if __name__ == '__main__':
    url_queue = Queue()

    for i in range(1,11):
        url = f'https://www.hupu.com/home/v1/news?pageNo={i}&pageSize=50'
        url_queue.put(url)

    
    for i in range(3):
        # 创建线程
        t = Thread(target=spider)
        #启动线程
        t.start()

 完整代码如下:

import requests
from fake_useragent import UserAgent
from time import sleep
from queue import Queue
from threading import Thread

def spider():
    '''
    从队列里获取url,并且爬取
    '''
    while not url_queue.empty():
        url = url_queue.get()   
        # 获取数据 
        headers={
            'User-agent':UserAgent().chrome
        }
        resp = requests.get(url,headers=headers)
        if resp.status_code == 200:
            print(f'成功获取了:{url}')
        sleep(3)

if __name__ == '__main__':
    url_queue = Queue()

    for i in range(1,11):
        url = f'https://www.hupu.com/home/v1/news?pageNo={i}&pageSize=50'
        url_queue.put(url)

    
    for i in range(3):
        # 创建线程
        t = Thread(target=spider)
        #启动线程
        t.start()

效果如下:

 多线程--类版

跟类版跟方法版其实没有什么区别,就是把内容放入一个类中。

import requests
from fake_useragent import UserAgent
from queue import Queue
from threading import Thread
from time import sleep


class MyThead(Thread):
    def run(self):
        '''
        从队列里获取url,并且爬取
        '''
        while not url_queue.empty():
            url = url_queue.get()   
            # 获取数据 
            headers={
                'User-agent':UserAgent().chrome
            }
            resp = requests.get(url,headers=headers)
            if resp.status_code == 200:
                print(f'成功获取了:{url}')
            sleep(3)

if __name__ == '__main__':
    url_queue = Queue()

    for i in range(1,11):
        url = f'https://www.hupu.com/home/v1/news?pageNo={i}&pageSize=50'
        url_queue.put(url)

    
    for i in range(3):
        # 创建进程
        t = MyThead()
        # 启动进程
        t.start()

跟方法版的输出结果是一样的。 

 多进程

提升爬虫效率除了多线程以外还有多进程,multiprocessing是python的多进程管理包,和threading.Thread类似。

multiprocessing模块

multiprocessing模块可以让程序员在给定的机器上充分的利用CPU

在multiprocessing中,通过创建Process对象生成进程,然后调用它的start()方法。

Manager类,实现数据共享

在使用并发设计的时候最好尽可能的避免共享数据,尤其是在使用多进程的时候。 如果你真有需要 要共享数据,可以使用由Manager()返回的manager提供list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array类型的支持

进程池的使用

  • 进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

  • 进程池中有两个方法:

    • apply同步执行-串行
    • apply_async异步执行-并行(推荐使用)

多进程--方法版

需要用到的模块:

import requests
from fake_useragent import UserAgent
from time import sleep
from multiprocessing import Process,Manager

爬虫主体内容与多线程的基本一致:

def spider(url_queue):
    '''
    从队列里获取url,并且爬取
    '''
    while not url_queue.empty():
        url = url_queue.get()   
        # 获取数据 
        headers={
            'User-agent':UserAgent().chrome
        }
        resp = requests.get(url,headers=headers)
        if resp.status_code == 200:
            print(f'成功获取了:{url}')
        sleep(3)

 创建进程列表,启动列表和获取数据:

if __name__ == '__main__':
    url_queue = Manager().Queue()

    for i in range(1,11):
        url = f'https://www.hupu.com/home/v1/news?pageNo={i}&pageSize=50'
        url_queue.put(url)

    # 创建一个进程列表
    all_process = []
    for i in range(3):
        # 创建进程
        p = Process(target=spider,args=(url_queue,))
        #启动进程
        p.start()
        # 将每个列表增加到进程列表中
        all_process.append(p)
    # 等待所有进程结束
    for p in all_process:
        p.join()

 完整代码如下:

import requests
from fake_useragent import UserAgent
from time import sleep
from multiprocessing import Process,Manager

def spider(url_queue):
    '''
    从队列里获取url,并且爬取
    '''
    while not url_queue.empty():
        url = url_queue.get()   
        # 获取数据 
        headers={
            'User-agent':UserAgent().chrome
        }
        resp = requests.get(url,headers=headers)
        if resp.status_code == 200:
            print(f'成功获取了:{url}')
        sleep(3)

if __name__ == '__main__':
    url_queue = Manager().Queue()

    for i in range(1,11):
        url = f'https://www.hupu.com/home/v1/news?pageNo={i}&pageSize=50'
        url_queue.put(url)

    # 创建一个进程列表
    all_process = []
    for i in range(3):
        # 创建进程
        p = Process(target=spider,args=(url_queue,))
        #启动进程
        p.start()
        # 将每个列表增加到进程列表中
        all_process.append(p)
    # 等待所有进程结束
    for p in all_process:
        p.join()


多进程-- 进程池版

跟方法版差不多,这里创建三个进程:

import requests
from fake_useragent import UserAgent
from time import sleep
from multiprocessing import Pool,Manager

def spider(url_queue):
    '''
    从队列里获取url,并且爬取
    '''
    while not url_queue.empty():
        url = url_queue.get()   
        # 获取数据 
        headers={
            'User-agent':UserAgent().chrome
        }
        resp = requests.get(url,headers=headers)
        if resp.status_code == 200:
            print(f'成功获取了:{url}')
        sleep(3)

if __name__ == '__main__':
    url_queue = Manager().Queue()

    for i in range(1,11):
        url = f'https://www.hupu.com/home/v1/news?pageNo={i}&pageSize=50'
        url_queue.put(url)

    # 创建进程池
    pool = Pool(3)
    #开启进程
    pool.apply_async(func=spider,args=(url_queue))
    pool.apply_async(func=spider,args=(url_queue))
    pool.apply_async(func=spider,args=(url_queue))
    # 等待所有进程结束
    pool.close() 
    # 将每个列表增加到进程列表中
    pool.join()


 协程

网络爬虫速度效率慢,多部分在于阻塞IO这块(网络/磁盘)。在阻塞时,CPU的中内核是可以处理别的非IO操作。因此可以考虑使用协程来提升爬虫效率,这种操作的技术就是协程。

可以让阻塞的子程序让出CPU给可以执行的子程序

一个进程包含多个线程,一个线程可以包含多个协程

多个线程相对独立,线程的切换受系统控制。 多个协程也相对独立,但是其切换由程序自己控制

安装第三方模块

pip install aiohttp

 好~这里我们已经成功安装了:

 接下来我们看看这个库里边的一些常用方法:

剩下的就去官网看吧

属性或方法功能
aiohttp.ClientSession()获取客户端函数
session.get(url)发送get请求
seesion.post(url)发送post请求
resp.status获取响应状态码
resp.url获取响应url地址
resp.cookies获取响应cookie内容
resp.headers获取响应头信息
resp.read()获取响应bytes类型
resp.text()获取响应文本内容

 具体使用:

import aiohttp
import asyncio


async def first():
  async with aiohttp.ClientSession() as session: #  aiohttp.ClientSession() == import requests 模块
    async with session.get('http://httpbin.org/get') as resp:
      rs = await resp.text()
      print(rs)


headers = {'User-Agent':'aaaaaa123'}
async def test_header():
  async with aiohttp.ClientSession(headers= headers) as session: #  aiohttp.ClientSession() == import requests 模块
    async with session.get('http://httpbin.org/get') as resp:
      rs = await resp.text()
      print(rs)


async def test_params():
  async with aiohttp.ClientSession(headers= headers) as session: #  aiohttp.ClientSession() == import requests 模块
    async with session.get('http://httpbin.org/get',params={'name':'bjsxt'}) as resp:
      rs = await resp.text()
      print(rs)


async def test_cookie():
  async with aiohttp.ClientSession(headers= headers,cookies={'token':'sxt123id'}) as session: #  aiohttp.ClientSession() == import requests 模块
    async with session.get('http://httpbin.org/get',params={'name':'bjsxt'}) as resp:
      rs = await resp.text()
      print(rs)


async def test_proxy():
  async with aiohttp.ClientSession(headers= headers,cookies={'token':'sxt123id'}) as session: #  aiohttp.ClientSession() == import requests 模块
    async with session.get('http://httpbin.org/get',params={'name':'bjsxt'},proxy = 'http://name:pwd@ip:port' ) as resp:
      rs = await resp.text()
      print(rs)






if __name__ == '__main__':
  loop = asyncio.get_event_loop()
  loop.run_until_complete(test_cookie())

-------------------------------2023.3.2-----------------------------

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我还可以熬_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值