python爬虫【3】—— 爬虫反反爬

news2024/11/24 3:55:52

一、常见的反爬手段和解决方法

二、splash 介绍与安装

三、验证码识别

图片验证码的处理方案
  • 手动输入(input) 这种方法仅限于登录一次就可持续使用的情况
  • 图像识别引擎解析 使用光学识别引擎处理图片中的数据,目前常用于图片数据提取,较少用于验证码处理
  • 打码平台 爬虫常用的验证码解决方案
  • 打码平台:
    • 超级鹰
    • 斐斐打码

以超级鹰举例:
1、注册用户
2、下载 Python语言Demo
3、打开 项目
在这里插入图片描述
4、修改验证码类型、用户名、登录密码等信息
在这里插入图片描述

可以修改并封装代码方便以后调用

#!/usr/bin/env python
# coding:utf-8

import requests
from hashlib import md5

class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()

    def PostPic_base64(self, base64_str, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
            'file_base64':base64_str
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()

def get_code(img_src,cpt_type):
    chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001')  # 用户中心>>软件ID 生成一个替换 96001
    im = open(img_src, 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    return chaojiying.Postpic(im.cap_type).get('pic_str')


if __name__ == '__main__':												#本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    print(get_code('chaojiying_Python/a.jpg',1004))											#1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    #print chaojiying.PostPic(base64_str, 1902)  #此处为传入 base64代码

三、验证码登录

1、可以先输入一个错误的登录账号 找到登录接口
在这里插入图片描述

2、点击验证码 找到获取验证码图片的接口

在这里插入图片描述
编写代码:

import requests
from chaojiying.chaojiying import get_code

def login_input():
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
    }
    session = requests.Session()

    login_url = 'https://www.chaojiying.com/user/login/'
    img_url = 'https://www.chaojiying.com/include/code/code.php?u=1&t=0.5925062343043659'
    
    # 获取验证码
    img_resp = session.get(img_url,headers=headers)
    with open('tmp.png', 'wb') as f:
        f.write(img_resp.content)

    code= input('请输入验证码:')
    # 构造登录参数
    params = {
        "user": "ls1233456",
        "pass": "123456",
        "imgtxt": code,
        "act": "1"
    }
    # 登录
    resp = session.post(login_url,data=params,headers=headers)
    print(resp.text)

def login_auto():
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
    }
    session = requests.Session()

    login_url = 'https://www.chaojiying.com/user/login/'
    img_url = 'https://www.chaojiying.com/include/code/code.php?u=1&t=0.5925062343043659'

    img_resp = session.get(img_url,headers=headers)
    with open('tmp.png', 'wb') as f:
        f.write(img_resp.content)
    # 识别验证码
    code= get_code('tmp.png',1004)
    # 构造登录参数
    params = {
        "user": "ls1233456",
        "pass": "123456",
        "imgtxt": code,
        "act": "1"
    }
    # 登录
    resp = session.post(login_url,data=params,headers=headers)
    print(resp.text)

if __name__ == "__main__":
    login_auto()


在这里插入图片描述

四、Chrome抓包分析JS数据源

目标:获取所有英雄并下载每个英雄的壁纸

找到每位英雄的壁纸接口
在这里插入图片描述

找到外层每位英雄的列表数据

在这里插入图片描述

编写代码逻辑

import requests
import os
from time import sleep

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}
hero_js = requests.get('https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js', headers=headers)
for hero in hero_js.json().get('hero'):
    id = hero.get('heroId')
    hero_name = hero.get('name')

    url = f'https://game.gtimg.cn/images/lol/act/img/js/hero/{id}.js'
    js_resp = requests.get(url, headers=headers)
    for sk in js_resp.json().get('skins'):
        file_name = sk.get('name').replace(' ','_')
        img_url = sk.get('mainImg')
        chromas = sk.get('chromas')
        if chromas == '0':
            img_resp = requests.get(img_url, headers=headers)
            sleep(1)
            print(f'正在下载:{file_name} 图片')

            file_dir = f'img/{hero_name}'
            if not os.path.exists(file_dir):
                os.mkdir(file_dir)
            with open(f'img/{hero_name}/{file_name}.png', 'wb') as f:
                f.write(img_resp.content)

在这里插入图片描述

五、JS逆向的操作思路

六、python执行JS代码

# pip install PyExecJS
import execjs
# pip install js2py
import js2py


js = '''
function add(num1, num2){
    return num1+num2;
}
function show(){
    return "hello python2js";
}
'''
def func1():
    ctx = execjs.compile(js)
    rs = ctx.call('add', 1, 2)
    print(rs)
    print(ctx.call('show'))

def func2():
    context = js2py.EvalJs(js)
    context.execute(js)
    # result = context.add(1,2)
    result = context.show()
    print(result)

if __name__ == '__main__':
    func2()

七、JS逆向生成加密数据

解密 微信公众平台 的登录密码 实现登录

下面是解密思路:

假设这里:账号是123,密码是123456,可以发现 密码已经被加密处理了,通过常规的 密码来登录是不好使的

在这里插入图片描述

找到这个对密码进行加密的 js 函数,直接拿出来 放到我们的 python 中,这样我们可以通过它提供的加密规则 ,生成需要的密码来实现登录

首先搜索一下 谁调用了这bizlongin
在这里插入图片描述
推测可能的 js 函数
在这里插入图片描述
这里查找出9个相关的内容 只有上图这里出现了passwd字样 为了验证 ,可以直接打上断点进行调试 这里试过之后好像不是,直接搜索 pwd 进行断点调试 最终找到函数
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
直接把这段js代码拷贝到我们的代码中

js = ‘’‘
拷贝的js代码
’‘’

import execjs

ctx = execjs.compile(js)
rs = ctx.call('g.exports', '123456')
print(rs)

实例:某猫小说加密数据生成JS加密逆向分析探索

八、常见的加密使用 base64、md5

def test_base64():
    import base64
    msg = 'hello'
    rs = base64.b32encode(msg.encode())
    print(rs)
    rs2 = base64.b32encode(rs)
    print(rs2)


def test_md51():
    import hashlib
    m = hashlib.md5()
    m.update('hello'.encode())
    pwd = m.hexdigest()
    print(pwd)

def test_md52():
    import hashlib
    pwd = hashlib.new('md5',b'hello').hexdigest()
    print(pwd)

if __name__ == '__main__':
    test_base64()
    # test_md52()

DES/AES

RSA

九、python使用Node

下载Node

安装node

创建 js 文件

function add(a,b){
    return a+b
}
tmp_a = parseInt(process.argv[2])
tmp_b = parseInt(process.argv[3])
console.log(add(tmp_a,tmp_b))

node 执行 js

def test_node1():
    import os
    a = 1
    b = 2
    cmd_line = (f'node js02.js {a} {b}')
    with os.popen(cmd_line) as nodejs:
        rs = nodejs.read().replace('\n', '')
        print(rs)
def test_node2():
    import subprocess
    a = 1
    b = 2
    cmd_line = (f'node js02.js {a} {b}')
    p = subprocess.Popen(cmd_line.split(),stdout=subprocess.PIPE)
    rs = p.stdout.read().decode().replace('\n','')
    print(rs)

if __name__ == '__main__':
    test_node1()
    test_node2()

十、IP代理池

日志模块

日志模块用于记录程序运行过程中的重要信息,这些信息可以帮助开发者调试程序,监控程序的运行状态,追踪错误和异常等。使用日志的好处包括:

  • 记录程序的运行情况:方便查看请求是否成功、代理是否有效等。
  • 错误追踪:当程序出错时,能够快速定位问题。
  • 性能监控:可以记录每次请求的响应时间,帮助优化爬虫性能。
import logging

def setup_logging(log_file='./proxy_sys/my.log'):
    logging.basicConfig(
        filename=log_file,
        level=logging.INFO,  # 设置日志级别为INFO
        format='%(asctime)s - %(levelname)s - %(message)s',  # 设置输出格式
    )

def log_message(message):
    logging.info(message)

# 使用示例
if __name__ == "__main__":
    setup_logging()
    log_message("程序启动成功")
    log_message("正在获取代理IP")

请求模块

请求模块负责实际的网络请求,它会使用代理池中的代理IP进行请求,并处理响应结果。一个好的请求模块应该:

  • 自动选择代理IP:从代理池中随机选择一个可用的代理。
  • 处理异常:在请求失败时能够妥善处理,比如重试或切换代理。
  • 记录请求日志:在请求过程中记录相关信息,包括请求状态和代理的使用情况。

以下是一个简单的请求模块示例,利用前面定义的日志模块进行记录:

import requests
import random
import logging

from setup_logging import setup_logging


class ProxyPool:
    def __init__(self):
        self.proxies = [
            'http://username:password@proxy1.com:port',
            'http://username:password@proxy2.com:port',
            'http://username:password@proxy3.com:port',
        ]

    def get_random_proxy(self):
        return random.choice(self.proxies)


class RequestModule:
    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool

    def make_request(self, url):
        proxy = self.proxy_pool.get_random_proxy()
        logging.info(f"使用代理: {proxy} 进行请求")

        try:
            response = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=5)
            response.raise_for_status()  # 如果响应状态码不是200,抛出异常
            logging.info(f"成功请求: {url}, 状态码: {response.status_code}")
            return response.text
        except requests.exceptions.RequestException as e:
            logging.error(f"请求失败: {e}")
            return None


# 主程序
if __name__ == "__main__":
    setup_logging()
    proxy_pool = ProxyPool()
    request_module = RequestModule(proxy_pool)

    url = "https://httpbin.org/ip"  # 测试获取IP的地址
    response = request_module.make_request(url)
    if response:
        print(response)  # 打印响应内容

在这里插入图片描述

数据库模块

import sqlite3

class Database:
    def __init__(self, db_file='data.db'):
        """初始化数据库连接和创建表"""
        self.connection = sqlite3.connect(db_file)
        self.cursor = self.connection.cursor()
        self.create_table()

    def create_table(self):
        """创建存储数据的表"""
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS scraped_data (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                url TEXT NOT NULL,
                content TEXT NOT NULL
            )
        ''')
        self.connection.commit()

    def insert_data(self, url, content):
        """插入数据"""
        self.cursor.execute('INSERT INTO scraped_data (url, content) VALUES (?, ?)', (url, content))
        self.connection.commit()

    def fetch_all_data(self):
        """查询所有数据"""
        self.cursor.execute('SELECT * FROM scraped_data')
        return self.cursor.fetchall()

    def close(self):
        """关闭数据库连接"""
        self.connection.close()

# 示例:使用数据库模块
if __name__ == '__main__':
    db = Database()

    # 假设我们从爬虫获取了以下数据
    sample_data = [
        ("https://httpbin.org/ip", "178.128.123.45"),
        ("https://httpbin.org/user-agent", "Mozilla/5.0"),
    ]

    # 插入数据
    for url, content in sample_data:
        db.insert_data(url, content)
        print(f"已插入数据: {url}")

    # 查询并打印所有数据
    print("查询到的数据:")
    all_data = db.fetch_all_data()
    for row in all_data:
        print(row)

    db.close()

代理IP验证

代理IP验证的目的
  • 确保有效性:过滤掉无法连接或响应时间过长的IP,以确保可用代理的质量。
  • 提高请求成功率:使用经过验证的代理IP进行请求,提高爬虫的效率和稳定性。
  • 避免封禁:使用有效的IP降低被目标网站封禁的风险。
验证的方法

1、简单GET请求:通过向一个稳定且不限制请求频率的URL(如 http://httpbin.org/ip)发起请求来验证代理IP是否可用。

2、响应时间检测:同时,可以记录请求的响应时间,以评估代理的性能。

3、状态码检查:检查返回的HTTP状态码,以判断请求是否成功(状态码200表示成功)。

4、特定内容验证:有些情况下,可以验证返回内容是否符合预期(如获取的IP是否与代理IP一致)。

import requests
import time

class ProxyPool:
    def __init__(self):
        # 模拟代理IP列表
        self.proxies = [
            'http://username:password@proxy1.com:port',
            'http://username:password@proxy2.com:port',
            'http://username:password@proxy3.com:port',
            # 更多代理IP
        ]

    def validate_proxy(self, proxy):
        """验证代理IP的有效性"""
        url = 'http://httpbin.org/ip'  # 验证代理的URL
        try:
            start_time = time.time()  # 记录请求开始时间
            response = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=5)

            if response.status_code == 200:
                # 检查返回的IP
                return response.json()['origin']  # 返回获得的IP
            else:
                print(f"代理{proxy}返回状态码: {response.status_code}")
                return None  # IP无效
        except requests.exceptions.RequestException as e:
            print(f"代理{proxy}验证失败: {e}")
            return None
        finally:
            elapsed_time = time.time() - start_time
            print(f"请求耗时: 0.0684秒")

    def validate_all_proxies(self):
        """验证代理池中的所有代理IP"""
        valid_proxies = []
        for proxy in self.proxies:
            print(f"正在验证代理: {proxy}")
            ip = self.validate_proxy(proxy)
            if ip:
                print(f"代理{proxy}有效, 获取的IP: {ip}")
                valid_proxies.append(proxy)
            else:
                print(f"代理{proxy}无效")
        
        return valid_proxies

# 使用实例
if __name__ == '__main__':
    proxy_pool = ProxyPool()
    valid_proxies = proxy_pool.validate_all_proxies()
    print("有效的代理IP列表:", valid_proxies)

下载代理IP

下载代理IP的思路

1、选择代理IP源:选择一些提供免费代理IP的网站,这些网站定期更新其代理IP列表。

2、发送请求:使用爬虫发送HTTP GET请求,获取代理IP页面的HTML内容。

3、解析HTML:提取所需的代理IP信息,包括IP地址、端口、匿名类型等。

4、去重与有效性验证:将提取的IP地址进行去重和有效性验证,确保代理IP池中的IP是可用的。可以在下载时进行简单的有效性检查。

5、存储:将可用的代理IP存储到数据库或内存中,以供后续使用。

pip install requests beautifulsoup4
import requests
from bs4 import BeautifulSoup


class ProxyDownloader:
    def __init__(self, url):
        self.url = url

    def download_proxies(self):
        """从指定URL下载代理IP"""
        try:
            response = requests.get(self.url, timeout=5)
            response.raise_for_status()  # 检查响应状态
            return self.parse_proxies(response.text)
        except requests.exceptions.RequestException as e:
            print(f"下载代理时出现错误: {e}")
            return []

    def parse_proxies(self, html):
        """解析HTML并提取代理IP"""
        soup = BeautifulSoup(html, 'html.parser')
        proxies = set()  # 使用集合去重
        # 根据网站的HTML结构提取IP和端口
        for row in soup.find_all('tr')[1:]:  # 跳过表头
            columns = row.find_all('td')
            if len(columns) >= 2:  # 确保有足够的列
                ip = columns[0].text.strip()  # 第一列是IP地址
                port = columns[1].text.strip()  # 第二列是端口
                proxies.add(f"{ip}:{port}")  # 添加到集合

        return list(proxies)


# 使用示例
if __name__ == '__main__':
    url = 'http://www.ip3366.net/free/?stype=3'  # 指定代理源网站
    downloader = ProxyDownloader(url)
    proxies = downloader.download_proxies()

    print("下载到的代理IP:")
    for proxy in proxies:
        print(proxy)

IP代理池的调度器

调度器的主要功能
  • 获取代理IP:从代理池中获取当前可用的代理IP。
  • 负载均衡:合理分配请求到不同的代理IP,以避免某个代理过载。
  • 监控代理状态:监测代理的使用情况(成功率、响应时间等),根据反馈动态调整代理的有效性。
  • 代理更新:在需要时更新代理池,移除失效的代理IP,并添加新的可用IP。
调度器的基本结构

一个简单的IP代理池调度器通常包括以下几个部分:

  • 代理池:存储和管理代理IP的集合。
  • 请求管理:处理请求并分发给合适的代理IP。
  • 状态监控:记录和分析每个代理的使用情况。
import random
import requests
import time

class ProxyPool:
    def __init__(self):
        # 初始化代理IP列表
        self.proxies = []

    def add_proxy(self, proxy):
        """添加代理IP到池中"""
        self.proxies.append(proxy)

    def remove_proxy(self, proxy):
        """从池中移除代理IP"""
        self.proxies.remove(proxy)

    def get_random_proxy(self):
        """获取随机代理IP"""
        if self.proxies:
            return random.choice(self.proxies)
        else:
            return None

class Scheduler:
    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool
        self.success_count = {}  # 用于记录每个代理的成功请求数
        self.fail_count = {}  # 用于记录每个代理的失败请求数

    def make_request(self, url):
        """使用代理池进行请求"""
        proxy = self.proxy_pool.get_random_proxy()
        if not proxy:
            print("没有可用的代理IP!")
            return None

        print(f"使用代理: {proxy}")
        try:
            response = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=5)
            response.raise_for_status()  # 检查响应状态
            self.success_count[proxy] = self.success_count.get(proxy, 0) + 1
            return response.text
        except requests.exceptions.RequestException as e:
            print(f"请求失败: {e}")
            self.fail_count[proxy] = self.fail_count.get(proxy, 0) + 1
            # 如果失败次数达到阈值,可以将该代理从代理池移除
            if self.fail_count[proxy] >= 3:
                print(f"代理{proxy}失效,移除。")
                self.proxy_pool.remove_proxy(proxy)
            return None

# 使用示例
if __name__ == '__main__':
    # 创建代理池并手动添加代理(实际使用中通常是从代理源下载的)
    proxy_pool = ProxyPool()
    proxy_pool.add_proxy('http://username:password@proxy1.com:port')
    proxy_pool.add_proxy('http://username:password@proxy2.com:port')
    proxy_pool.add_proxy('http://username:password@proxy3.com:port')

    # 创建调度器
    scheduler = Scheduler(proxy_pool)

    # 循环发送请求(可根据需求调整循环次数和请求间隔)
    for _ in range(5):
        content = scheduler.make_request('http://httpbin.org/ip')
        if content:
            print("请求成功,响应内容:", content)
        # 短暂休息以避免过快请求
        time.sleep(2)

API接口

API 接口的主要功能

1、获取可用代理IP:提供一种方式让用户获取当前可用的代理IP。
2、添加代理IP:允许外部程序将新代理IP添加到代理池中。
3、删除代理IP:提供接口以便外部程序删除无效或不需要的代理IP。
4、查询代理IP状态:查询特定代理IP的使用情况,如是否有效、请求成功率等。

常见的RESTful API设计(使用HTTP动词)如下:

  • GET /proxies:获取可用代理IP列表
  • POST /proxies:添加新代理IP
  • DELETE /proxies/{ip}:删除特定的代理IP
  • GET /proxies/{ip}:查询代理IP的状态
pip install Flask
from flask import Flask, jsonify, request
import random

app = Flask(__name__)

class ProxyPool:
    def __init__(self):
        self.proxies = {}  # 用字典存储代理和状态

    def add_proxy(self, proxy):
        self.proxies[proxy] = {'status': 'valid', 'success_count': 0, 'fail_count': 0}

    def remove_proxy(self, proxy):
        if proxy in self.proxies:
            del self.proxies[proxy]

    def get_all_proxies(self):
        return [(proxy, details['status']) for proxy, details in self.proxies.items() if details['status'] == 'valid']

    def get_proxy_status(self, proxy):
        return self.proxies.get(proxy, None)

# 创建全局代理池实例
proxy_pool = ProxyPool()

# 初始化一些代理(实际使用中应该从真实源下载)
proxy_pool.add_proxy('http://username:password@proxy1.com:port')
proxy_pool.add_proxy('http://username:password@proxy2.com:port')

@app.route('/proxies', methods=['GET'])
def get_proxies():
    """获取可用代理IP列表"""
    proxies = proxy_pool.get_all_proxies()
    return jsonify(proxies)

@app.route('/proxies', methods=['POST'])
def add_proxy():
    """添加新代理IP"""
    data = request.json
    proxy = data.get('proxy')
    if proxy:
        proxy_pool.add_proxy(proxy)
        return jsonify({"message": "Proxy added successfully."}), 201
    return jsonify({"error": "Proxy not provided."}), 400

@app.route('/proxies/<string:proxy>', methods=['DELETE'])
def delete_proxy(proxy):
    """删除特定的代理IP"""
    proxy_pool.remove_proxy(proxy)
    return jsonify({"message": f"Proxy {proxy} removed successfully."}), 200

@app.route('/proxies/<string:proxy>', methods=['GET'])
def proxy_status(proxy):
    """查询代理IP的状态"""
    status = proxy_pool.get_proxy_status(proxy)
    if status:
        return jsonify({"proxy": proxy, "status": status['status'], "success_count": status['success_count'], "fail_count": status['fail_count']})
    return jsonify({"error": "Proxy not found."}), 404

if __name__ == '__main__':
    app.run(debug=True)

将上述代码保存为 proxy_pool_api.py,并在终端中运行。

python proxy_pool_api.py

使用API测试工具,如Postman或curl,测试API端点。

获取可用的代理IP列表:

curl -X GET http://127.0.0.1:5000/proxies

在这里插入图片描述

添加一个新的代理IP:

curl -X POST http://127.0.0.1:5000/proxies -H "Content-Type: application/json" -d '{"proxy": "http://username:password@proxy3.com:port"}'

删除一个代理IP:

curl -X DELETE http://127.0.0.1:5000/proxies/http://username:password@proxy1.com:port

查询特定代理的状态:

curl -X GET http://127.0.0.1:5000/proxies/http://username:password@proxy2.com:port

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1951404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零搭建pytorch模型教程(八)实践部分(二)目标检测数据集格式转换

前言 图像目标检测领域有一个非常著名的数据集叫做COCO&#xff0c;基本上现在在目标检测领域发论文&#xff0c;COCO是不可能绕过的Benchmark。因此许多的开源目标检测算法框架都会支持解析COCO数据集格式。通过将其他数据集格式转换成COCO格式可以无痛的使用这些开源框架来训…

【计算机网络】DNS命令练习与抓包分析实验

一&#xff1a;实验目的 1&#xff1a;掌握DNS缓存的清除方法&#xff0c;了解DNS缓存的作用和影响。 2&#xff1a;熟悉nslookup和dig等DNS查询工具的使用&#xff0c;理解DNS查询的基本原理和过程。 3&#xff1a;通过抓包和分析&#xff0c;深入了解DNS查询和响应消息的格…

探索 LLamaWorker 本地大模型API服务的新功能:函数调用

LLamaWorker 是一个基于 LLamaSharp 项目开发的可以在本地运行大模型服务&#xff0c;并提供与 OpenAI / Azure OpenAI 兼容的 API。同时&#xff0c;通过工具提示词的配置&#xff0c;提供函数调用 Function Call 能力&#xff0c;为开发者提供更多的可能。 1. 背景 在人工智…

Robot Operating System——AsyncParametersClient监控Parameters的增删改行为

大纲 同步创建SyncParametersClient设置监控回调回调函数主体测试完整代码 异步创建AsyncParametersClient设置监控回调测试完整代码 在《Robot Operating System——Parameter设置的预处理、校验和成功回调》一文中&#xff0c;我们使用Node::add_post_set_parameters_callbac…

Django项目中报错:django.template.exceptions.TemplateDoesNotExist: index.html

访问127.0.0.1&#xff1a;8000访问出错 查看报错原因 到Django项目当中找到settings.py&#xff0c;找到TEMPLATES中的DIRS: 添加如下代码&#xff0c;并导入OS模块&#xff1a; "DIRS": [os.path.join(BASE_DIR,templates)] 再次访问IP地址&#xff1a;

【JVM基础07】——类加载器-什么是类加载器?类加载器有哪些?双亲委派了解吗?

目录 1- 引言&#xff1a;类加载器1-1 类加载器是什么&#xff1f;(What)1-2 为什么要用类加载器&#xff1f; 作用&#xff1a;类加载的过程&#xff1f;(Why) 2- ⭐核心&#xff1a;类加载器详解(How)2-1 类加载器分类2-2 什么是双亲委派模型&#xff1f;2-3 为什么采用双亲委…

开始尝试从0写一个项目--前端(三)

器材管理板块 添加器材管理导航 src\views\home\Home.vue src\router\index.js src\views\equipment\Equipment.vue <template><div>hello!</div></template> 测试 搜索导航分页查询 src\views\equipment\Equipment.vue <template><div&…

C#、Net6、WebApi报表方案

目录 1 Pdf表单方案 1.1出现如下错误提示: 1.2 字体路径使用 2 Docx报表模板方案 2.1 pdf方案缺陷 2.2 解决方案 3 Spire.Doc报表方案 3.1 Docx方案缺陷 3.2 解决方案 4 插入复选框 5 WebApi文件流下载接口 6 软件获取方式 1 Pdf表单方案 使用【Adobe Acrobat P…

0726,没什么用的SELECT和没用的我

目录 select 可恶&#xff01;&#xff01;&#xff01; 一对多聊天室 select&#xff1a;&#xff08;抄抄抄 最怕人类开始思考 补一对一的 select 喵&#xff1a;&#xff08;抄抄抄 &#xff1f;&#xff1f;今天就这么结束了&#xff1f;&#xff1f;&#xff1f; …

全能Ai助手:写作到设计,宝藏神器帮你事半功倍

今天&#xff0c;就让我们一起踏上这场寻找“隐藏”宝藏的旅程&#xff0c;探索这些AI工具如何改变我们的生活&#xff01; 一、高效生产力的提升之道 1. 文案创作助手 案例&#xff1a;某位自媒体博主使用了一款智能写作工具&#xff0c;不仅大大节省了写作时间&#xff0c;…

JMeter接口测试:测试中奖概率!

介绍 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试。JMeter 最初被设计用于 Web 应用测试&#xff0c;但后来扩展到了其他测试领域&#xff0c;可用于测试静态和动态资源&#xff0c;如静态文件、Java 小服务程序、CGI 脚本、J…

c语言第四天笔记

关于 混合操作&#xff0c;不同计算结果推理 第一种编译结果&#xff1a; int i 5; int sum (i) (i) 6 7 13 第二种编译结果&#xff1a; int i 5; int sum (i) (i) 6 7 7 7 前面的7是因为后面i的变化被影响后&#xff0c;重新赋值 14 第一种编译结果&#xff…

Llama + Dify,在你的电脑搭建一套AI工作流

theme: smartblue 点赞 关注 收藏 学会了 本文简介 最近字节在推Coze&#xff0c;你可以在这个平台制作知识库、制作工作流&#xff0c;生成一个具有特定领域知识的智能体。 那么&#xff0c;有没有可能在本地也部署一套这个东西呢&#xff1f;这样敏感数据就不会泄露了&…

Redis的两种持久化方式---RDB、AOF

rdb其实就是一种快照持久化的方式&#xff0c;它会将Redis在某个时间点的所有的数据状态以二进制的方式保存到硬盘上的文件当中&#xff0c;它相对于aof文件会小很多&#xff0c;因为知识某个时间点的数据&#xff0c;当然&#xff0c;这就会导致它的实时性不够高&#xff0c;如…

Scrapy 爬取旅游景点相关数据(三)

这一节我们将之前爬取到的景点数据进行解析&#xff0c;并且保存为excel&#xff0c;便于后续使用&#xff0c;本节包含 &#xff08;1&#xff09; 景点数据解析 &#xff08;2&#xff09;数据保存到excel 1 编写爬虫 这次继续改进第二节的爬虫&#xff0c;新建一个爬虫文…

C#如何引用dll动态链接库文件的注释

1、dll动态库文件项目生成属性中要勾选“XML文档文件” 注意&#xff1a;XML文件的名字切勿修改。 2、添加引用时XML文件要与DLL文件在同一个目录下。 3、如果要是添加引用的时候XML不在相同目录下&#xff0c;之后又将XML文件复制到相同的目录下&#xff0c;需要删除引用&am…

蓝桥强化宝典(3)BFS

一、定义 广度优先搜索&#xff08;Breadth-First Search, BFS&#xff09;是另一种用于遍历或搜索树或图的算法。与深度优先搜索&#xff08;DFS&#xff09;沿着树的深度遍历不同&#xff0c;广度优先搜索会逐层遍历图的顶点。它从一个指定的源顶点开始&#xff0c;首先访问这…

失业潮下,有人靠天工AI做副业年入10万?

前言 你好&#xff0c;我是咪咪酱 这篇文章总结2个AI副业项目&#xff0c;不用写代码&#xff0c;就能做的2个副业项目。 第一&#xff1a;AI生成微信表情包&#xff0c;上传到微信表情包平台等&#xff0c;坚持下去&#xff0c;会有可观的收入。 第二&#xff1a;AI生成连载…

Java 8 中 20 个高频面试题及答案

文章目录 前言20 道高频题问题 1&#xff1a;给定一个整数列表&#xff0c;使用 Stream 函数找出列表中所有的偶数&#xff1f;问题 2&#xff1a;给定一个整数列表&#xff0c;使用 Stream 函数找出所有以 1 开头的数字&#xff1f;问题 3&#xff1a;如何使用 Stream 函数在给…