1905电影网中国地区电影数据分析(一) - 数据采集、清洗与存储

文章目录

  • 前言
  • 一、数据采集步骤及python库使用版本
    • 1. python库使用版本
    • 2. 数据采集步骤
  • 二、数据采集网页分析
    • 1. 分析采集的字段和URL
      • 1.1 分析要爬取的数据字段
      • 1.2 分析每部电影的URL
      • 1.2 分析每页的URL
    • 2. 字段元素标签定位
  • 三、数据采集代码实现
    • 1. 爬取1905电影网分类信息
    • 2. 爬取电影主页HTML
    • 3. 解析html并把数据保存到csv文件
  • 四、数据清洗与存储代码实现


前言

本项目旨在通过爬取1905电影网的电影数据,展示如何使用Python及相关库进行网页数据采集。本项目将详细介绍数据采集的步骤,包括所需的Python库版本、网页分析、数据提取和保存等环节。我们将使用requests库进行网络请求,利用BeautifulSoup进行HTML解析,并将最终的数据保存为CSV文件,便于后续分析和处理。


一、数据采集步骤及python库使用版本

1. python库使用版本

pythonrequestsbs4beautifulsoup4soupsievelxmlpandassqlalchemymysql-connector-pythonselenium
版本3.8.52.31.00.0.24.12.32.64.9.32.0.32.0.369.0.04.15.2

2. 数据采集步骤

进入1905电影网中国地区电影网页
分析电影分页的URL
保存电影分页为HTML文件
从电影分页的HTML文件中解析出每部电影的URL
保存每部电影主页为HTML文件
从每部电影主页的HTML文件解析出需要的数据
把解析出的数据保存到CSV文件中

二、数据采集网页分析

1. 分析采集的字段和URL

1.1 分析要爬取的数据字段

如下图所示,红框部分是要爬取的数据,包含电影标题、电影类型、电影时长、电影片名、电影别名、电影上映时间、电影编剧、电影导演、电影主演、电影剧情等字段。

在这里插入图片描述

1.2 分析每部电影的URL

访问中国地区的电影地址:https://www.1905.com/mdb/film/list/country-China/

如下图所示,电影是分页显示,每一页有多部电影,点击单部电影后会调转到对应主页,在对应的主页就有需要爬取的数据,所以需要从每页中解析出单个电影的URL。

在这里插入图片描述

如下图所示,检查单部电影的源码后可以看到对应的URL。
复制该部电影的URL为:https://www.1905.com/mdb/film/2248201/(2248201是这部电影的ID)
那么就可以通过解析网页获取到每部电影的URL。

在这里插入图片描述

1.2 分析每页的URL

如下图所示,检查源码后发现如下规律:
第二页的URL为:https://www.1905.com/mdb/film/list/country-China/o0d0p2.html
第三页的URL为:https://www.1905.com/mdb/film/list/country-China/o0d0p3.html
第四页的URL为:https://www.1905.com/mdb/film/list/country-China/o0d0p4.html
第五页的URL为:https://www.1905.com/mdb/film/list/country-China/o0d0p5.html

由此推断出:
第一页的URL为:https://www.1905.com/mdb/film/list/country-China/o0d0p1.html(o0d0p1.html可省略)
第n页的URL为:https://www.1905.com/mdb/film/list/country-China/o0d0p{n}.html

在这里插入图片描述

2. 字段元素标签定位

示例:定位电影标题元素
定位后的CSS选择器内容为:

body > div.topModule.normalCommon.normal_oneLine > div > div > div.topModule_title.clearfix > div.topModule_title_left.fl > h3 > span

在这里插入图片描述


三、数据采集代码实现

1. 爬取1905电影网分类信息

import random
import time
from pathlib import Path

import pandas as pd
import requests
from bs4 import BeautifulSoup

'''
爬取1905电影网分类信息(大分类 main_category,小分类 sub_category,链接 sub_category_link)
'''


def get_request(url, **kwargs):
    time.sleep(random.uniform(0.1, 2))
    print(f'===============================请求地址:{url} ===============================')
    # 定义一组User-Agent字符串
    user_agents = [
        # Chrome
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        # Firefox
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0',
        'Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/117.0',
        # Edge
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2040.0',
        # Safari
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15',
    ]

    # 请求头
    headers = {
        'User-Agent': random.choice(user_agents)
    }

    # 用户名密码认证(私密代理/独享代理)
    username = ""
    password = ""
    proxies = {
        "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password,
                                                        "proxy": '36.25.243.5:11768'},
        "https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password,
                                                         "proxy": '36.25.243.5:11768'}
    }

    max_retries = 3
    for attempt in range(max_retries):
        try:
            response = requests.get(url=url, timeout=10, headers=headers, **kwargs)
            # response = requests.get(url=url, timeout=10, headers=headers, proxies=proxies, **kwargs)
            if response.status_code == 200:
                return response
            else:
                print(f"请求失败,状态码: {response.status_code},正在重新发送请求 (尝试 {attempt + 1}/{max_retries})")
        except requests.exceptions.RequestException as e:
            print(f"请求过程中发生异常: {e},正在重新发送请求 (尝试 {attempt + 1}/{max_retries})")

        # 如果不是最后一次尝试,则等待一段时间再重试
        if attempt < max_retries - 1:
            time.sleep(random.uniform(1, 2))
    print('================多次请求失败,请查看异常情况================')
    return None  # 或者返回最后一次的响应,取决于你的需求


def get_soup(markup):
    return BeautifulSoup(markup=markup, features='lxml')


def save_categories_to_csv(response, csv_file_dir='./data_csv/', csv_file_name='category.csv'):
    """
    从HTML响应中提取分类信息并保存到CSV文件。

    参数:
    response (requests.Response): 包含HTML内容的响应对象。
    csv_file_dir (str): CSV文件存储目录,默认为'./data_csv/'。
    csv_file_name (str): CSV文件名,默认为'category.csv'。
    """
    # 确保目录存在
    csv_file_dir_path = Path(csv_file_dir)
    csv_file_dir_path.mkdir(parents=True, exist_ok=True)

    # 解析HTML文档
    soup = get_soup(response.text)

    # 提取分类信息
    data_list = []
    tag_srh_group = soup.select("body > div.layout.mainCont.clear > div.leftArea > div > div.col-l-bd > dl.srhGroup.clear")
    for tag_srh in tag_srh_group:
        tag_dt = tag_srh.select_one('dt')
        main_category = tag_dt.text.strip() if tag_dt is not None else None
        tag_a_list = tag_srh.select('a')
        print(f'===========================解析后的数据如下:===========================')
        for tag_a in tag_a_list:
            if tag_a is not None:
                sub_category = tag_a.text.strip()
                sub_category_link = 'https://www.1905.com' + tag_a.get('href', '')
                data_dict = {
                    'main_category': main_category,
                    'sub_category': sub_category,
                    'sub_category_link': sub_category_link
                }
                data_list.append(data_dict)
                print(data_dict)

    # 创建DataFrame并清理数据
    df = pd.DataFrame(data_list)
    df_cleaned = df[df['sub_category'].notna() & (df['sub_category'] != '')]
    print(f'===========================文件保存路径:{csv_file_dir + csv_file_name}===========================')
    # 保存到CSV文件
    df_cleaned.to_csv(csv_file_dir + csv_file_name, index=False, encoding='utf-8-sig')


if __name__ == '__main__':
    res = get_request("https://www.1905.com/mdb/film/search/")
    save_categories_to_csv(res)

保存后的文件内容如下图所示:

在这里插入图片描述

2. 爬取电影主页HTML

import random
import time
from pathlib import Path

import requests
from bs4 import BeautifulSoup


def get_request(url, **kwargs):
    time.sleep(random.uniform(0.1, 2))
    print(f'===============================请求地址:{url} ===============================')
    # 定义一组User-Agent字符串
    user_agents = [
        # Chrome
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        # Firefox
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0',
        'Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/117.0',
        # Edge
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2040.0',
        # Safari
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15',
    ]

    # 请求头
    headers = {
        'User-Agent': random.choice(user_agents)
    }

    # 用户名密码认证(私密代理/独享代理)
    username = ""
    password = ""
    proxies = {
        "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password,
                                                        "proxy": '36.25.243.5:11768'},
        "https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password,
                                                         "proxy": '36.25.243.5:11768'}
    }

    max_retries = 3
    for attempt in range(max_retries):
        try:
            response = requests.get(url=url, timeout=10, headers=headers, **kwargs)
            # response = requests.get(url=url, timeout=10, headers=headers, proxies=proxies, **kwargs)
            if response.status_code == 200:
                return response
            else:
                print(f"请求失败,状态码: {response.status_code},正在重新发送请求 (尝试 {attempt + 1}/{max_retries})")
        except requests.exceptions.RequestException as e:
            print(f"请求过程中发生异常: {e},正在重新发送请求 (尝试 {attempt + 1}/{max_retries})")

        # 如果不是最后一次尝试,则等待一段时间再重试
        if attempt < max_retries - 1:
            time.sleep(random.uniform(1, 2))
    print('================多次请求失败,请查看异常情况================')
    return None  # 或者返回最后一次的响应,取决于你的需求


def get_soup(markup):
    return BeautifulSoup(markup=markup, features='lxml')


def save_html_file(save_dir, file_name, content):
    dir_path = Path(save_dir)
    # 确保保存目录存在,如果不存在则创建所有必要的父级目录
    dir_path.mkdir(parents=True, exist_ok=True)
    # 使用 'with' 语句打开文件以确保正确关闭文件流
    with open(save_dir + file_name, 'w', encoding='utf-8') as fp:
        print(f"==============================={save_dir + file_name} 文件已保存===============================")
        fp.write(str(content))


def save_rough_html_file():
    i = 0
    save_dir = './rough_html/china/'
    while True:
        i = i + 1
        file_name = f'o0d0p{i}.html'
        file_path = Path(save_dir + file_name)
        if file_path.exists() and file_path.is_file():
            print(f'===============================文件 {file_path} 已存在===============================')
            continue
        url = f'https://www.1905.com/mdb/film/list/country-China/o0d0p{i}.html'
        response = get_request(url)
        soup = get_soup(response.text)
        tag_ul = soup.select_one('body > div.layout.mainCont.clear > div.leftArea > ul')
        if tag_ul.text.strip() is None or tag_ul.text.strip() == '':
            print(f'===============================网页爬取完成===============================')
            break
        save_html_file(save_dir, file_name, response.text)


def save_detail_info_html_file():
    i = 0
    save_dir = './detail_html/china/'
    while True:
        i = i + 1
        url = f'https://www.1905.com/mdb/film/list/country-China/o0d0p{i}.html'
        response = get_request(url)
        soup = get_soup(response.text)
        tag_ul = soup.select_one('body > div.layout.mainCont.clear > div.leftArea > ul')
        if tag_ul.text.strip() is None or tag_ul.text.strip() == '':
            print(f'===============================网页爬取完成===============================')
            break
        tag_li_list = tag_ul.select('li')
        for tag_li in tag_li_list:
            tag_a_href = tag_li.find('a').attrs.get('href')
            movie_url = f'https://www.1905.com{tag_a_href}'
            movie_id = tag_a_href.split('/')[-2]
            file_name = f'{movie_id}.html'
            file_path = Path(save_dir + file_name)
            if file_path.exists() and file_path.is_file():
                print(f'===============================文件 {file_path} 已存在===============================')
                continue
            detail_response = get_request(movie_url)
            if detail_response is None:
                continue
            save_html_file(save_dir, file_name, detail_response.text)


if __name__ == '__main__':
    # save_rough_html_file()
    save_detail_info_html_file()

爬取后保存的部分html文件如下图所示:

在这里插入图片描述

3. 解析html并把数据保存到csv文件

from pathlib import Path

import pandas as pd
from bs4 import BeautifulSoup


def get_soup(markup):
    return BeautifulSoup(markup=markup, features='lxml')


def parse_detail_html_to_csv():
    # 定义CSV文件路径
    csv_file_dir = '../1905movie/data_csv/'
    csv_file_name = 'detail_1905movie_dataset.csv'
    csv_file_path = Path(csv_file_dir + csv_file_name)
    csv_file_dir_path = Path(csv_file_dir)
    csv_file_dir_path.mkdir(parents=True, exist_ok=True)

    detail_dir = Path('./detail_html/china/')
    detail_file_list = detail_dir.rglob('*.html')

    movie_data_list = []
    i = 0
    count = 0
    for detail_file in detail_file_list:
        movie_id = str(detail_file).split('\\')[-1].split('.')[0]
        movie_url = f'https://www.1905.com/mdb/film/{movie_id}/'
        soup = get_soup(open(file=detail_file, mode='r', encoding='utf-8'))
        tag_img_url = soup.select_one('div.topModule_bottom_poster.picHover.fl img')
        movie_img_url = tag_img_url.attrs.get('src') if tag_img_url is not None else None
        tag_div_topmodule_title_right = soup.select_one('div.topModule_title_right.fr')
        tag_evaluation_name = tag_div_topmodule_title_right.select_one('div.evaluation-name')
        tag_judge_soon_fl = tag_div_topmodule_title_right.select_one('div.judge-soon.fl')
        movie_rating = tag_evaluation_name.text if tag_evaluation_name is not None else None
        movie_status = tag_judge_soon_fl.text if tag_judge_soon_fl is not None else '已上映'
        tag_topmodule_title_left_fl = soup.select_one('div.topModule_title_left.fl')
        tag_h3_span = tag_topmodule_title_left_fl.select_one('h3 > span')
        movie_title = tag_h3_span.text if tag_h3_span is not None else None
        tag_li = tag_topmodule_title_left_fl.select_one('li.topModule_line')
        movie_genres = str(tag_li.find_next_sibling('li').text.strip()).split() if tag_li is not None else None
        tag_li5 = tag_topmodule_title_left_fl.select_one('div > ul > li:nth-child(5)')
        movie_duration = tag_li5.text.strip() if tag_li5 is not None else None
        tag_div_left_top = soup.select_one('div#left_top')
        tag_ul_consmodule_infos = tag_div_left_top.select_one(
            'ul.consModule_infos.consModule_infos_l.fixedWidth.fl') if tag_div_left_top is not None else None
        tag_li_em_release_date = tag_ul_consmodule_infos.find(name='span',
                                                              string='上映时间') if tag_ul_consmodule_infos is not None else None
        movie_release_date = tag_li_em_release_date.find_next_sibling().text.strip() if tag_li_em_release_date is not None else None
        tag_li_em_director = tag_ul_consmodule_infos.select_one(
            'li > em > a') if tag_ul_consmodule_infos is not None else None
        movie_director = tag_li_em_director.text.strip() if tag_li_em_director is not None else None
        tag_ul_consmodule_infos_r = tag_div_left_top.select_one(
            'ul.consModule_infos.consModule_infos_r.fl') if tag_div_left_top is not None else None
        tag_alternative_titles = tag_ul_consmodule_infos_r.select_one(
            'li > em') if tag_ul_consmodule_infos_r is not None else None
        movie_alternative_titles = tag_alternative_titles.text if tag_alternative_titles is not None else None
        tag_adaptation_source = tag_ul_consmodule_infos_r.find(name='span',
                                                               string='改编来源') if tag_ul_consmodule_infos_r is not None else None
        movie_adaptation_source = tag_adaptation_source.find_next_sibling().text if tag_adaptation_source is not None else None
        tag_screenwriter = tag_ul_consmodule_infos_r.select_one(
            'li > em > a') if tag_ul_consmodule_infos_r is not None else None
        movie_screenwriter = tag_screenwriter.text if tag_screenwriter is not None else None
        tag_lead_actors = soup.select_one('#left_top > div > ul > li')
        tag_lead_actors_a_list = tag_lead_actors.select('a') if tag_lead_actors is not None else None
        movie_lead_actors = [tag.text for tag in tag_lead_actors_a_list] if tag_lead_actors_a_list is not None else []
        tag_plot = soup.select_one('#left_top > ul > li.plotItem.borderStyle > div > a')
        movie_plot = tag_plot.text if tag_plot is not None else None

        movie_data_dict = {
            'movie_id': movie_id,
            'movie_url': movie_url,
            'movie_img_url': movie_img_url,
            'movie_duration': movie_duration,
            'movie_title': movie_title,
            'movie_director': movie_director,
            'movie_release_date': movie_release_date,
            'movie_status': movie_status,
            'movie_rating': movie_rating,
            'movie_genres': movie_genres,
            'movie_lead_actors': movie_lead_actors,
            'movie_alternative_titles': movie_alternative_titles,
            'movie_adaptation_source': movie_adaptation_source,
            'movie_screenwriter': movie_screenwriter,
            'movie_plot': movie_plot
        }
        i = i + 1
        print(f'===============================第{i}行数据,解析后的数据如下:===============================')
        print(movie_data_dict)
        print('=============================================================================================')
        movie_data_list.append(movie_data_dict)
        count = count + 1
        if count == 200:
            df = pd.DataFrame(movie_data_list)
            if not csv_file_path.exists():
                df.to_csv(csv_file_dir + csv_file_name, index=False, encoding='utf-8-sig')
            else:
                df.to_csv(csv_file_dir + csv_file_name, index=False, encoding='utf-8-sig', mode='a', header=False)
            movie_data_list = []
            count = 0
            print(
                f'===============================解析后的电影数据已保存到 {csv_file_dir + csv_file_name} 文件===============================')

    if count != 0:
        df = pd.DataFrame(movie_data_list)
        df.to_csv(csv_file_dir + csv_file_name, index=False, encoding='utf-8-sig', mode='a', header=False)
    print(
        f'===============================解析后的电影数据已全部保存到 {csv_file_dir + csv_file_name} 文件===============================')


if __name__ == '__main__':
    parse_detail_html_to_csv()

保存后的文件内容如下图:

在这里插入图片描述


四、数据清洗与存储代码实现

import re
from datetime import datetime

import pandas as pd
from sqlalchemy import create_engine


def read_csv_to_df(file_path):
    # 加载CSV文件到DataFrame
    return pd.read_csv(file_path, encoding='utf-8')


def contains_hours(text):
    if pd.isna(text):  # 检查是否为 NaN 或 None
        return False
    pattern = r'\d+\s*(小时|h|hours?|hrs?)'
    return bool(re.search(pattern, text))


def convert_to_minutes(duration_str):
    parts = str(duration_str).replace('小时', ' ').replace('分钟', '').split()
    hours = int(parts[0]) if len(parts) > 0 else 0
    minutes = int(parts[1]) if len(parts) > 1 else 0
    return hours * 60 + minutes


# 定义一个函数来清理和标准化日期
def clean_and_standardize_date(date_str):
    date_str_cleaned = str(date_str)
    # 移除括号及其内容
    if '(' in date_str_cleaned:
        date_str_cleaned = date_str.split('(')[0]

    # 尝试匹配并解析完整的日期格式
    if "年" in date_str_cleaned and "月" in date_str_cleaned and "日" in date_str_cleaned:
        date_obj = datetime.strptime(date_str_cleaned, "%Y年%m月%d日")
    elif "年" in date_str_cleaned and "月" in date_str_cleaned:
        date_obj = datetime.strptime(date_str_cleaned, "%Y年%m月")
        date_obj = date_obj.replace(day=1)  # 设置为该月的第一天
    elif "年" in date_str_cleaned:
        date_obj = datetime.strptime(date_str_cleaned, "%Y年")
        date_obj = date_obj.replace(month=1, day=1)  # 设置为该年的第一天
    else:
        return None  # 如果不符合任何已知模式,则返回 None 或其他默认值

    return date_obj.strftime("%Y-%m-%d")  # 返回标准格式的字符串


# 定义函数:清理和转换数据格式
def clean_and_transform(df):
    # 筛选出电影状态为“已上映”的数据
    df = df[df['movie_status'] == '已上映']
    # 删除电影标题为空的行
    df.dropna(subset=['movie_title'], inplace=True)
    # 删除id相同的数据
    df.drop_duplicates(subset=['movie_id'], inplace=True)
    # 电影时长字段处理
    df['movie_duration'] = df['movie_duration'].apply(lambda x: x if contains_hours(x) else None)
    if df['movie_duration'].isnull().sum() != 0:
        df['movie_duration'] = df['movie_duration'].fillna(method='ffill')
    df['movie_duration'] = df['movie_duration'].apply(convert_to_minutes)
    # 发布日期字段处理
    df['movie_release_date'] = df['movie_release_date'].apply(clean_and_standardize_date)
    if df['movie_release_date'].isnull().sum() != 0:
        df['movie_release_date'] = df['movie_release_date'].fillna(method='ffill')
    # 评分字段处理
    df['movie_rating'] = df['movie_rating'].astype('float').round(1)
    if df['movie_rating'].isnull().sum() != 0:
        df['movie_rating'] = df['movie_rating'].interpolate()
    # 类型字段处理
    if df['movie_genres'].isnull().sum() != 0:
        df['movie_genres'] = df['movie_genres'].fillna(method='ffill')
    # 其他空值字段处理
    df = df.fillna('未知')
    return df


def save_df_to_db(df):
    # 设置数据库连接信息
    db_user = 'root'
    db_password = 'zxcvbq'
    db_host = '127.0.0.1'  # 或者你的数据库主机地址
    db_port = '3306'  # MySQL默认端口是3306
    db_name = 'movie1905'

    # 创建数据库引擎
    engine = create_engine(f'mysql+mysqlconnector://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}')
    # 将df写入MySQL表
    df.to_sql(name='movie1905_china', con=engine, if_exists='replace', index=False)
    print("所有csv文件的数据已成功清洗并写入MySQL数据库")


if __name__ == '__main__':
    csv_file = r'./data_csv/detail_1905movie_dataset.csv'
    dataframe = read_csv_to_df(csv_file)
    dataframe = clean_and_transform(dataframe)
    save_df_to_db(dataframe)

清洗并存储后的部分数据如下图所示:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qpython+Flask监控添加发送语音中文信息功能

对QpythonFlask实现对小孩学习的监控-CSDN博客中html页面进行改造&#xff0c;利用Ajax&#xff0c;提交一段文字&#xff0c;发送到数据库&#xff0c;再在服务器&#xff0c;发送该段文件给手机端&#xff0c;然手机端TTS朗读出来&#xff0c;增加了父母监控小孩学习&#xf…

【note】MCTS

MCTS survey 参考 http://arxiv.org/abs/2103.04931 基本概念 MDP 可以表示为一个四元组 ( S , A S , P a , P w ) (S,A_S,P_a,P_w) (S,AS​,Pa​,Pw​)&#xff1a; S S S&#xff1a;状态空间 A s A_s As​&#xff1a;状态 s s s 下的可行动作集合 P a ( s , s ′ ) P_…

Couchbase UI: Server

在 Couchbase UI 中的 Server&#xff08;服务器&#xff09;标签页主要用于管理和监控集群中的各个节点。以下是 Server 标签页的主要内容和功能介绍&#xff1a; 1. 节点列表 显示集群中所有节点的列表&#xff0c;每个节点的详细信息包括&#xff1a; 节点地址&#xff1…

顶刊JFR|ROLO-SLAM:首个针对不平坦路面的车载Lidar SLAM系统

摘要 基于激光雷达&#xff08;LiDAR&#xff09;的同步定位与地图构建&#xff08;SLAM&#xff09;被认为是在恶劣环境中提供定位指导的一种有效方法。然而&#xff0c;现成的基于激光雷达的SLAM方法在经过不平坦地形时&#xff0c;尤其是在垂直方向相关的部分&#xff0c;会…

枪支消音器的 CFD 模拟

探索应用于枪支消音器的计算流体动力学的迷人世界。 了解枪支消音器 枪支消音器&#xff0c;也称为抑制器&#xff0c;是安装在枪支枪管上的装置&#xff0c;用于降低子弹发射时产生的噪音。消音器的作用是减缓和冷却子弹离开枪管时迅速膨胀的热气体。这一过程有助于降低声音…

Object类(1)

大家好&#xff0c;今天我们来学习一个常用类-Object类&#xff0c;这个类可以说是所有类的父类&#xff0c;因此它的重要性不言而喻&#xff0c;那么话不多说&#xff0c;来看。 大家可能会有一个疑问&#xff0c;java中不是只能继承一个类吗&#xff0c;那么我们继承了Objec…

【数据资产】数据资产管理概述

导读&#xff1a;数据资产管理在企业的数字化转型和业务发展中扮演着至关重要的角色。它直接关系到企业的决策效率、运营优化、业务创新以及风险防控等多个方面。数据资产作为企业的重要战略资源&#xff0c;能够为企业带来经济利益&#xff0c;其价值可能来自于数据本身的稀缺…

Qt监控系统辅屏预览/可以同时打开4个屏幕预览/支持5x64通道预览/onvif和rtsp接入/性能好

一、前言说明 在监控系统中&#xff0c;一般主界面肯定带了多个通道比如16/64通道的画面预览&#xff0c;随着电脑性能的增强和多屏幕的发展&#xff0c;再加上现在监控摄像头数量的增加&#xff0c;越来越多的用户希望在不同的屏幕预览不同的实时画面&#xff0c;一个办法是打…

51单片机开发:独立键盘实验

实验目的&#xff1a;按下键盘1时&#xff0c;点亮LED灯1。 键盘原理图如下图所示&#xff0c;可见&#xff0c;由于接GND&#xff0c;当键盘按下时&#xff0c;P3相应的端口为低电平。 键盘按下时会出现抖动&#xff0c;时间通常为5-10ms&#xff0c;代码中通过延时函数delay…

【翻转硬币——莫比乌斯函数、分块、卷积、埃氏筛】

题目 暴力代码&#xff0c;官网过55% #include <bits/stdc.h> using namespace std; int main() {int n;cin >> n;vector<bool> a(n 1);a[1] 1;int res 1;for (int i 2; i < n; i){if (a[i] 0){for (int j i; j < n; j i)a[j] a[j] ^ 1;res;}…

Hive:内部表和外部表,内外转换

内部表和外部表 内部表示例 给表添加数据 外部表示例 给表添加数据 外部表示例 用location指定表目录位置,那么表的位置在实际指定的位置,但是可以被映射 外部表和内部表的区别 删除表后使用show tables in shao; 已经没有被删除的表,说明元数据已经被删除(mysql里面存放),但是…

算法题(49):反转链表II

审题&#xff1a; 需要我们对指定范围的链表进行反转&#xff0c;并返回反转后链表的头结点 思路&#xff1a; 方法一&#xff1a;vector法 我们先遍历一次链表&#xff0c;并把数据对应的存在数组中&#xff0c;然后利用数组的reverse方法进行反转数据&#xff0c;最后再遍历一…

Unreal Engine 5 C++ Advanced Action RPG 十一章笔记

第十一章 In Game Widgets 本章节就是做UI2-Template Button Widget 这章节创建不同的UI 结束UI胜利UI暂停菜单主菜单加载UI新建一个按钮小组件作为模版 3-Pause Menu Template Button 继续做更多模版UI 4-Lose Screen(游戏失败UI) 做失败的UI 之前按钮模版的调度程序就在这起…

基于OpenCV实现的答题卡自动判卷系统

一、图像预处理 🌄 二、查找答题卡轮廓 📏 三、透视变换 🔄 四、判卷与评分 🎯 五、主函数 六、完整代码+测试图像集 总结 🌟 在这篇博客中,我将分享如何使用Python结合OpenCV库开发一个答题卡自动判卷系统。这个系统能够自动从扫描的答题卡中提取信…

Go:基于Go实现一个压测工具

文章目录 写在前面整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理 客户端模块Http客户端处理Grpc客户端处理Websocket客户端处理 连接处理模块GrpcHttp 统计数据模块统计原理实现过程 写在前面 本篇主要是基于Go来实现一个压测的工具&#xff0c;关于压测的内…

ES6 简单练习笔记--变量申明

一、ES5 变量定义 1.在全局作用域中 this 其实就是window对象 <script>console.log(window this) </script>输出结果: true 2.在全局作用域中用var定义一个变量其实就相当于在window上定义了一个属性 例如: var name "孙悟空" 其实就相当于执行了 win…

2025数学建模美赛|赛题翻译|E题

2025数学建模美赛&#xff0c;E题赛题翻译 更多美赛内容持续更新中...

Android AOP:aspectjx

加入引用 在整个项目的 build.gradle 中&#xff0c;添加 classpath "com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10" 可以看到测试demo的 gradle 版本是很低的。 基于 github 上的文档&#xff0c;可以看到原版只支持到 gradle 4.4 。后续需要使…

【SpringBoot教程】Spring Boot + MySQL + HikariCP 连接池整合教程

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 在前面一篇文章中毛毛张介绍了SpringBoot中数据源与数据库连接池相关概念&#xff0c;今天毛毛张要分享的是关于SpringBoot整合HicariCP连接池相关知识点以及底层源码…

GIS 中的 SQLAlchemy:空间数据与数据库之间的桥梁

利用 SQLAlchemy 在现代应用程序中无缝集成地理空间数据导言 地理信息系统&#xff08;GIS&#xff09;在管理城市规划、环境监测和导航系统等各种应用的空间数据方面发挥着至关重要的作用。虽然 PostGIS 或 SpatiaLite 等专业地理空间数据库在处理空间数据方面非常出色&#…