c++,python实现网络爬虫

news2024/11/15 12:03:54

前言:

社交网络中用户生成的海量数据,社交网络数据的多样性和复杂性

如何高效地从海量的数据中获取和处理我们需要的信息资源?

该微博爬虫能够从社交网络平台中地提取文本、图片和用户之间的转发关系,并将这些数据结构化存储到图数据库中,为后续的数据分析和挖掘提供支持。

总体思路

在爬取静态的文本与图片时,首先使用libcurl库进行http请求,从指定URL下载网页内容,再使用Gumbo解析HTML内容以提取文本和图像URL,并字符串形式储存,Gumbo DOM树转换为Pugixml文档,使用XPath查找图像URL,将提取的文本内容保存到一个文件中,图像URL保存到另一个文件中。

  在爬取动态的转发关系时,使用selenium库模拟用户操作,动态加载网页,beautifulsoup库解析网页内容,如果文本包含//,则被认为转发自其他用户,提取用户名,否则,被认为转发自原始微博,

  最后将拥有用户id,转发时间,转发来源的csv用pandas库读取内容进行数据处理neo4j储存微博用户与转发关系

设计方法

在设计方法上,本实验综合利用了C++的高效性和Python的灵活性。具体方法如下:

2.1工具与库的选择:为了实现高效的网页下载和HTML解析,选择了libcurl和Gumbo库;为了处理动态网页内容和模拟用户操作,选择了selenium库;为了解析HTML并提取特定数据,选择了BeautifulSoup库;为了处理CSV文件和进行数据分析,选择了pandas库;最后,为了实现数据的图数据库存储,选择了Neo4j。

2.2模块化设计:整个系统分为多个功能模块,包括爬取文本和图片模块、爬取转发关系模块、数据处理与存储模块。每个模块负责特定的任务,模块之间相互协作,共同完成整个数据爬取和存储流程。

3.1性能分析:

3.1.1高效性,算法需要能够高效地处理大量网页请求,特别是对动态加载内容的网页,需要快速响应和处理。

3.1.2资源利用,为了减少对系统资源的占用,包括CPU、内存和网络带宽的使用,以提高系统的整体性能。

3.2功能分析:

3.2.1准确性:算法必须准确地提取网页中的文本、图片URL和用户转发关系,确保数据的完整性和正确性

3.2.2鲁棒性:算法需要具备较强的鲁棒性,能够处理各种异常情况,如网页内容变化、网络连接中断等。

3.2.3扩展性:系统设计需要具备良好的扩展性,便于后续增加新的功能模块,例如爬取用户的点赞关系、评论内容等。

part1:用c++实现文本与图片的爬取,直接把我的代码粘过来,注释很详细

在爬取文本与图片时,首先初始化并且使用libcurl库从指定URL下载网页内容,再使用Gumbo解析HTML内容,提取文本和图像URL,并储存到字符串里面,Gumbo DOM树转换为Pugixml文档,使用XPath查找图像URL将提取的文本内容保存到一个文件中,图像URL保存到另一个文件中。

//(爬取文本,转发关系)
#include <iostream>
#include <fstream>//用于文件操作
#include <string>
#include <curl/curl.h>//用于 libcurl 库,进行 HTTP 请求
#include <gumbo.h>//用于 Gumbo 库,进行 HTML 解析
#include <pugixml.hpp>//用于 pugixml 库,进行 XML 操作
#include <vector>//用于 STL 容器
#include <set>//用于 STL 容器
using namespace std;
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    ((string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;//返回处理的数据总大小,告诉 libcurl 已经处理了多少数据。
}
string download_url(const string& url, const string& cookie_string) {
    CURL* curl;//一个指向 CURL 句柄的指针,用于执行 HTTP 请求。
    CURLcode res;// 用于存储 curl 操作的返回码
    string readBuffer;//用于存储下载的内容。
//1,初始化 CURL
    curl = curl_easy_init();//初始化一个 CURL 句柄,如果初始化成功,返回一个 CURL 句柄,否则返回 nullptr
//2,设置 CURL 选项
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());//CURLOPT_URL: 设置要下载的 URL
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);//CURLOPT_WRITEFUNCTION: 设置写入数据的回调函数 WriteCallback。
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);//CURLOPT_WRITEDATA: 设置回调函数的用户数据,这里是 readBuffer,用于存储下载的数据。
        curl_easy_setopt(curl, CURLOPT_COOKIE, cookie_string.c_str());
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");//CURLOPT_USERAGENT: 设置请求的 User-Agent 字符串,模拟浏览器
 //3,执行 CURL 请求
        res = curl_easy_perform(curl);//返回操作的结果码。
        if (res != CURLE_OK) {
            cout<< "下载URL内容错误: " << curl_easy_strerror(res) << endl;//转可读字符串
        }
        curl_easy_cleanup(curl);//清理
    }

    return readBuffer;
}
void search_for_text(GumboNode* node, string& text) {//GumboNode* node: 指向当前处理的 Gumbo 节点的指针;std::string& text: 用于存储提取出的文本内容的字符串引用。
    if (node->type == GUMBO_NODE_TEXT) {//看是不是文本
        text.append(node->v.text.text);//是的话追加到字符串text
    }
    else if (node->type == GUMBO_NODE_ELEMENT && node->v.element.tag != GUMBO_TAG_SCRIPT && node->v.element.tag != GUMBO_TAG_STYLE) {
        GumboVector* children = &node->v.element.children;//获取该节点的子节点集合(GumboVector* children)遍历子节点集合,对每个子节点递归调用 search_for_text 函数。
        for (unsigned int i = 0; i < children->length; ++i) {
            search_for_text(static_cast<GumboNode*>(children->data[i]), text);
        }
    }
}
string extract_text_from_html(const string& html_content) {
    GumboOutput* output = gumbo_parse(html_content.c_str());//调用 gumbo_parse 函数将 html_content 转换为 C 字符串并解析为 Gumbo DOM 树。output 是解析后的 Gumbo 树的根节点
    if (!output) {
        cout << "Gumbo解析失败" << endl;
        return "";
    }

   string text;
    search_for_text(output->root, text);

    gumbo_destroy_output(&kGumboDefaultOptions, output);//销毁
    return text;
}
void traverse_gumbo_node(GumboNode* gumbo_node, pugi::xml_node& pugi_node) {
    if (gumbo_node->type != GUMBO_NODE_ELEMENT) return;//检查当前 Gumbo 节点是否是元素节点,如果不是则直接返回。

    GumboElement* element = &gumbo_node->v.element;//获取当前节点的元素部分并将其存储在 element 中
    const char* tag_name = gumbo_normalized_tagname(element->tag);//获取标准化的标签名,并将其存储在 tag_name 中
    if (tag_name && tag_name[0]) {//检查标签名是否有效(非空且不为空字符串)
        pugi::xml_node new_node = pugi_node.append_child(tag_name);

        // 添加节点的属性
        GumboVector* attributes = &element->attributes;
        for (unsigned int i = 0; i < attributes->length; ++i) {//将每个属性添加到 new_node 中。属性的名称和值分别为 attribute->name 和 attribute->value。
            GumboAttribute* attribute = (GumboAttribute*)attributes->data[i];
            new_node.append_attribute(attribute->name) = attribute->value;
        }

        // 递归处理子节点
        GumboVector* children = &element->children;
        for (unsigned int i = 0; i < children->length; ++i) {
            traverse_gumbo_node((GumboNode*)children->data[i], new_node);
        }
    }
}

void parse_html(const string& html_content, string& text, set<std::string>& images) {
    GumboOutput* output = gumbo_parse(html_content.c_str());
    if (!output) {
        cout << "Gumbo解析失败" <<endl;
        return;
    }

    pugi::xml_document doc;
    // 创建一个 pugixml 文档对象 doc。调用 traverse_gumbo_node 函数,将 Gumbo 的 DOM 树转换为 pugixml 的 DOM 树。
    traverse_gumbo_node(output->root, doc);

    // 提取文本内容
    text = extract_text_from_html(html_content);

    // 提取图像URL
    for (pugi::xpath_node xpath_node : doc.select_nodes("//img")) {
        pugi::xml_node img_node = xpath_node.node();//XPath 表达式 //img 查找 pugixml 文档中所有的 <img> 标签。
        images.insert(img_node.attribute("src").value());
    }

    gumbo_destroy_output(&kGumboDefaultOptions, output);//销毁 Gumbo 解析器的输出对象 output,释放其占用的内存
}

// 函数用于将文本内容保存到文件
void save_text_to_file(const string& text, const string& filename) {//const string& text:需要保存的文本内容。const string& filename:目标文件的文件名。
    ofstream file(filename);//创建一个 ofstream 对象 file,并打开名为 filename 的文件进行输出操作。
    if (file.is_open()) {
        file << text;
        file.close();
    }
    else {
        cout << "打开文件错误: " << filename << endl;
    }
}

// 函数用于将图像URL保存到文件
void save_images_to_file(const set<string>& images, const string& filename) {
    ofstream file(filename);
    if (file.is_open()) {
        for (const string& image : images) {
            file << image << endl;
        }
        file.close();
    }
    else {
        cerr << "打开文件错误: " << filename << endl;
    }
}

int main() {
    string url = "https://s.weibo.com/weibo?q=%E5%88%98%E6%98%8A%E7%84%B6%20%E6%9C%95%E5%92%8C%E5%AC%9B%E5%AC%9B%E4%BD%95%E6%9B%BE%E6%9C%89%E8%BF%87%E5%AB%8C%E9%9A%99&topic_ad=";
    string cookie_string = "SINAGLOBAL=5399883731581.21.1696810732360; ariaMouseten=null; UOR=mp.csdn.net,service.weibo.com,mail.qq.com; SUB=_2A25LYf0kDeRhGeFG7VAS9ynPwzyIHXVoH3DsrDV8PUNbmtANLRXWkW1NeTFXOlSZsbpSTgfXcGAbTof6v4B8rIFe; ALF=02_1720523380; ariaDefaultTheme=default; ariaFixed=true; ariaReadtype=1; ariaStatus=true; _s_tentry=-; Apache=6084155699997.418.1718066762994; ULV=1718066762995:15:11:2:6084155699997.418.1718066762994:1717920771762";

    string html_content = download_url(url, cookie_string);
    if (html_content.empty()) {
        cerr << "从URL下载内容失败。" << endl;
        return 1;
    }

    string text;
    set<std::string> images;
    parse_html(html_content, text, images);

    // 保存文本内容到文件
    save_text_to_file(text, "text_content.txt");

    // 保存图像URL到文件
    save_images_to_file(images, "image_urls.txt");

   cout << "文本内容已保存到 text_content.txt" << std::endl;
    cout << "图像URL已保存到 image_urls.txt" << std::endl;

    return 0;
}

part2:python爬取转发关系

在爬取链接时,使用selenium库,beautifulsoup库爬取转发关系,如果文本包含//,则被认为转发自其他用户,提取用户名,否则,被认为转发自原始微博,最后将拥有用户id,转发时间,转发来源的csv用pandas库读取内容进行数据处理,neo4j储存微博用户与转发关系
#最终
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import re
import time
from datetime import datetime
import pandas as pd
from bs4 import BeautifulSoup
def initialize_browser(driver_path, options, headers):
    print("Initializing browser...")
    service = Service(driver_path)
    browser = webdriver.Edge(service=service, options=options)
    browser.execute_cdp_cmd('Network.enable', {})
    browser.execute_cdp_cmd('Network.setExtraHTTPHeaders', {'headers': headers})
    print("Browser initialized.")
    return browser
def wait_for_page_load(browser, timeout, class_name):
    print("Waiting for page to load...")
    WebDriverWait(browser, timeout).until(
        EC.presence_of_element_located((By.CLASS_NAME, class_name))
    )
    print("Page loaded.")
def get_page_source(browser):
    print("Getting page source...")
    return browser.page_source
def scroll_page(browser):
    print("Scrolling page...")
    last_scroll_height = browser.execute_script("return document.body.scrollHeight")
    while True:
        browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(5)
        new_scroll_height = browser.execute_script("return document.body.scrollHeight")
        if new_scroll_height == last_scroll_height:
            break
        last_scroll_height = new_scroll_height
    print("Finished scrolling page.")
def parse_page(page_html):
    print("Parsing page HTML...")
    soup = BeautifulSoup(page_html, "html.parser")
    original_poster = soup.find("header", class_="woo-box-flex").find("a", class_="ALink_default_2ibt1")
    original_user_id = original_poster.get("aria-label")
    repost_entries = soup.findAll("div", class_="wbpro-scroller-item")
    print("Finished parsing page HTML.")
    return original_user_id, repost_entries
def extract_repost_data(repost_entries, original_user_id, processed_user_ids):
    print("Extracting repost data...")
    scraped_data = []
    for entry in repost_entries:
        # 查找包含转发文本的容器
        repost_text_container = entry.find("div", class_="text").find("span")
        if repost_text_container:
            # 提取容器中的纯文本内容,忽略所有链接
            text_content = "".join([segment for segment in repost_text_container.strings if
                                    segment not in repost_text_container.find_all("a")])
            if "//" in text_content:
                # 如果文本内容中有"//",表示这是转发的微博,查找用户名的链接
                username_anchor = repost_text_container.find("a")
                if username_anchor:
                    username_link = username_anchor.get("href")
                    repost_user = username_link.split("/")[-1]  # 获取用户名
                    repost_info = f"转发自:{repost_user}"
                else:
                    repost_info = f"转发自:未知用户"  # 处理没有用户名链接的情况
            else:
                repost_info = f"转发自:{original_user_id}"  # 直接转发自原始用户

            # 查找当前用户的ID
            user_anchor = entry.find("div", class_="text").find("a", class_="ALink_default_2ibt1")
            if user_anchor:
                current_user_id = user_anchor.get_text(strip=True)
                if current_user_id not in processed_user_ids:
                    processed_user_ids.add(current_user_id)
                    # 查找发布时间信息
                    time_info = entry.find("div", string=re.compile(r'\d{2}-\d{1,2}-\d{1,2} \d{1,2}:\d{2}'))
                    if time_info:
                        post_timestamp = time_info.text.strip()
                        try:
                            # 解析时间格式
                            post_timestamp = datetime.strptime(post_timestamp, '%y-%m-%d %H:%M').strftime(
                                '%Y-%m-%d %H:%M:%S')
                        except ValueError:
                            print(f"时间格式错误:{post_timestamp}")
                        # 保存提取的数据
                        scraped_data.append([current_user_id, post_timestamp, repost_info])
                        print(f"用户ID: {current_user_id}, 时间: {post_timestamp}, 转发关系:{repost_info}")
    print("Finished extracting repost data.")
    return scraped_data

def save_to_csv(data, output_csv):
    print("Saving data to CSV...")
    try:
        data_frame = pd.DataFrame(data, columns=['user_id', 'time', 'repost_source'])
        data_frame.to_csv(output_csv, index=False, encoding='utf-8_sig')
        print(f"数据已保存到 {output_csv}")
    except Exception as save_error:
        print("保存CSV文件时出错: ", str(save_error))

def main():
    driver_path = 'D:\\python310\\Scripts\\msedgedriver.exe'
    options = Options()
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")

    req_headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0",
        "cookie": "SINAGLOBAL=5399883731581.21.1696810732360; UOR=mp.csdn.net,service.weibo.com,mail.qq.com; SUB=_2A25LYf0kDeRhGeFG7VAS9ynPwzyIHXVoH3DsrDV8PUNbmtANLRXWkW1NeTFXOlSZsbpSTgfXcGAbTof6v4B8rIFe; ALF=02_1720523380; ariaDefaultTheme=default; ariaFixed=true; ULV=1718067765857:16:12:3:6228001885489.596.1718067765856:1718066762995; XSRF-TOKEN=1eo5sramGTwy_UcD1QfWa7Wp; WBPSESS=eQZNrz-Wn46RlA5U6QxZX_XMdXGL03Js8_qrxltO2fuSlg9ZjBjrhdtXezA_v15N6m50CLzRQYeD5igzwC15uiMikucPdT9KLGvXo4V-zH6MrZ6iL0wpyjfDdMfGUq7NRQzXh4fOBTtIKuY8cvP8UQ==; ariaReadtype=1; ariaStatus=true"
    }

    target_url = "https://weibo.com/6377374546/OhqKDemDv#repost"
    output_csv = 'pachong.csv'
    processed_user_ids = set()

    try:
        browser = initialize_browser(driver_path, options, req_headers)
        browser.get(target_url)

        wait_for_page_load(browser, 20, "detail_wbtext_4CRf9")
        scroll_page(browser)
        page_html = get_page_source(browser)
        original_user_id, repost_entries = parse_page(page_html)
        scraped_data = extract_repost_data(repost_entries, original_user_id, processed_user_ids)
        save_to_csv(scraped_data, output_csv)

    except Exception as overall_error:
        print("运行中错: ", str(overall_error))

    finally:
        browser.quit()

if __name__ == "__main__":
    main()

part3导入neo4j图数据库,进行可视化

#pandas库读取CSV文件中的数据,然后使用Neo4j数据库来存储微博用户及其转发关系
import pandas as pd#pandas用于数据处理,neo4j用于操作Neo4j图数据库
from neo4j import GraphDatabase

# 读取 CSV 文件内容,pandas的read_csv函数读取文件内容,存储在DataFrame对象df中。
file_path = r'D:\python project\pythonProject\pachong.csv'  # 修改为你的 CSV 文件路径""
df = pd.read_csv(file_path)

# Neo4j 配置
uri = "bolt://localhost:7687"  # 修改为你的 Neo4j URI
user = "neo4j"  # 修改为你的 Neo4j 用户名
password = "zyc679613"  # 修改为你的 Neo4j 密码

# GraphDatabase.driver函数连接到Neo4j数据库
driver = GraphDatabase.driver(uri, auth=(user, password))

def create_user(tx, user_id):#用于创建用户节点。在Neo4j中,节点可以有多个属性,这里我们使用MERGE命令来确保如果节点已经存在,则不会重复创建相同的节点。
    tx.run("MERGE (u:User {id: $user_id})", user_id=user_id)


def create_relationship(tx, user_id, source_id):#这个函数用于创建转发关系。在Neo4j中,关系用于连接两个节点。这里我们使用MERGE命令来确保如果关系已经存在,则不会重复创建相同的关系。
    tx.run("""
    MATCH (u1:User {id: $user_id}), (u2:User {id: $source_id})
    MERGE (u1)-[:REPOSTED]->(u2)
    """, user_id=user_id, source_id=source_id)


with driver.session() as session:#使用Neo4j的driver对象创建一个会话。driver.session()返回一个上下文管理器,用于执行Cypher查询。
    # 创建用户节点
    for user_id in df['user_id'].unique():#遍历DataFrame中不重复的用户ID
        session.execute_write(create_user, user_id)#调用create_user函数创建用户节点,并传递用户ID作为参数。

        # 创建转发关系
    for index, row in df.iterrows():#遍历DataFrame中的每一行,获取用户ID和转发源。
        source_id = row['repost_source'].split(":")[-1]  # 从转发源字段中提取转发源ID。转发源字段的格式是"转发自:xxx",这里使用split函数将其拆分,并取最后一个部分作为转发源ID。
        session.execute_write(create_relationship, row['user_id'], source_id)#调用create_relationship函数创建转发关系,并传递用户ID和转发源ID作为参数。

driver.close()

实验结果与分析

C++提取文本与图片的代码通过

提取图片的文件内容

提取文本的文件内容

python爬取转发关系的代码运行过程

python爬取转发关系的csv文件结果

csv文件导入neo4j的节点截图

Neo4j的转发关系截图

  • 总结与心得体会

在完成这次社交网络爬虫系统设计与实现的过程中,我深刻体会到了整个项目从构思到实现的复杂性和挑战性。通过这个项目,不仅提高了我在网络爬虫、数据处理和图数据库等方面的技能,还让我对大规模数据处理和系统设计有了更深入的理解。

在设计阶段,我首先对社交网络数据的特点和目标进行了详细分析。社交网络上的数据不仅包括静态的文本和图片,还包含动态加载的转发关系、评论和点赞等互动信息。因此,系统需要具备处理不同类型网页内容的能力。基于此,我决定采用C++和Python结合的方法:C++负责静态网页的内容下载和解析,Python负责动态网页的内容提取和数据存储。

在项目实施过程中,我遇到了多个挑战。

处理动态网页内容的挑战动态网页内容需要通过JavaScript加载,传统的静态爬虫无法获取这些数据。为了解决这一问题,我引入了selenium库,通过模拟浏览器操作,加载动态网页,并使用BeautifulSoup解析加载完成的网页内容。

数据量大且复杂的挑战,社交网络上的数据量庞大且格式多样,这对系统的性能和数据处理能力提出了很高的要求。为此,我采用了高效的libcurl库进行网页下载,并利用pandas进行数据清洗和处理,确保系统能够高效处理大规模数据。

反爬机制的挑战,很多社交网络平台都有反爬机制,限制频繁的爬虫行为。我通过设置合理的请求头和cookie,模拟真实用户的浏览行为,同时加入了随机延时机制,避免触发反爬机制。

最后我深刻体会到了合适工具选择的重要性,在本项目中,libcurl、Gumbo、selenium、BeautifulSoup、pandas和Neo4j的组合提供了强大的功能支持,使得系统能够高效地完成数据爬取和处理任务,当然其中包括时下载或者是选择相应的库文件都不是一件简单的事情,需要不断去尝试学习。同时我也感受到心态与坚持的魅力,中途有很多次想要放弃,项目其中也因为各种各样的问题停滞不前,,我想这种发现问题,解决问题的能力将伴随我未来的各种项目,希望我能攻克一个又一个问题。

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

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

相关文章

Python的Windows GUI自动化之Pywinauto(四)

引言&#xff1a; 我们上章节中打开了一个应用程序后&#xff0c;并打印了所有的控件信息&#xff0c;这些对于工具无法定位到的控件有很好的协助作用&#xff08;当然这个可以作为主要的查找控件的用法&#xff0c;也可以辅助使用&#xff0c;我一般是把这个作为辅助使用&…

【C++】初识C++模板与STL

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理 本章将简单分享C模板与STL相关知识&#xff0c;与之相关更多知识将留到下次更详细地来分享给大家 &#x1f3…

MySQL与ES数据实时同步,双写一致

一、简介 在项目的开发与运维过程中&#xff0c;MySQL 是业务数据库的核心角色&#xff0c;以其强大的事务处理能力和数据完整性保障&#xff0c;支撑着系统的稳定运行。随着数据量的急剧增长和查询复杂度的不断提升&#xff0c;单一依赖 MySQL 进行高效的数据检索显得日益吃力…

centos安装软件

1.centos 安装 unrar 提示找不到 使用EPEL仓库&#xff1a; 首先&#xff0c;你需要安装EPEL仓库&#xff1a; yum install epel-release 然后&#xff0c;尝试再次安装unrar&#xff1a; yum install unrar 编译安装&#xff1a; 下载源代码&#xff1a;wget http://www.rarla…

对耳朵伤害最小的耳机类型是哪种?五款口碑绝佳机型安利!

​目前来说&#xff0c;开放式耳机应该算是对耳朵伤害最小的耳机了。当今耳机市场上&#xff0c;开放式耳机以其舒适的佩戴和创新的非入耳设计赢得了众多消费者的喜爱。这种耳机让你在聆听音乐的同时&#xff0c;还能清晰地感知周围环境的声音&#xff0c;便于与人交流&#xf…

clickhouse 原理详解

1、MPP数据库简介 1.1、什么是OLTP与OLAP&#xff1f; 1.1.1、OLTP(OnLine Transaction Processing ) 联机事务处理 系统&#xff0c;例如mysql。擅长事务处理&#xff0c;在数据操作中保持着很强的一致性和原子性 &#xff0c;能够很好的支持频繁的数据插入和修改 &#x…

Java使用Tesseract进行OCR图片文字识别

前言 在当前的文字识别技术应用中&#xff0c;除了采用现有的API服务之外&#xff0c;常见的解决方案包括利用Tessdata、Canvas或OCRAD等工具。以下是对几种技术的简要分析&#xff1a; 百度API的使用体验表明&#xff0c;虽然其识别率令人满意&#xff0c;但并非完美无误。此…

一个月狂撸5.8W,利用AI制作宝宝走秀视频,让宝宝“出海”捞美刀

今天给大家分享的项目是**AI宝宝走秀视频玩法&#xff0c;**在项目拆解之前&#xff0c;先看一下这个账号。这个账号是在Tiktok上的&#xff0c;也就是海外版的抖音。 基本上都是几千万的播放&#xff0c;按照海外版抖音的激励计划&#xff0c;每播放一万次&#xff0c;就能赚8…

紧跟大模型技术趋势,为更大更通用的大模型提供底层支撑!关于智能计算系统:从深度学习到大模型,全新版本,发布!

文章目录 &#x1f4cb;前言&#x1f3af; 关于智能计算系统&#x1f3af; 内容简介&#x1f3af; 作者简介&#x1f3af; 专家推荐&#x1f3af; 目录大纲&#x1f525; 参与方式 &#x1f4cb;前言 “只要你想把大模型做得更好、做得更大、做得更快、做得更省电&#xff0c;…

翻译软件 Fastrans 开发日志 #01

目录 预览前言功能技术待办 预览 Github 仓库链接&#xff1a;https://github.com/YaoqxCN/Fastrans Gitee 仓库链接&#xff1a;https://gitee.com/yaoqx/Fastrans 求求给我点个 star 叭 qaq 现在才是 v1.0.0&#xff0c;给我个 star 鼓励我继续开发下去&#xff01; 我相信…

AI如何帮助普通人实现自我成长和副业变现

前言 最近有没有发现身边的一切都变得越来越"智能"了&#xff1f;连家里的空调都学会了自己调整温度&#xff0c;害得我每天起床都觉得它比我聪明。这不禁让我想到&#xff0c;既然连空调都在进化&#xff0c;我们这些普通人是不是也该搭上AI的快车&#xff0c;来个华…

找出所有子集异或和的和 全排列2

1863.找出所有子集异或和的和 解释&#xff1a;做本题没思路的话&#xff0c;强烈建议看本专栏上一篇博文 class Solution { public:int sum 0;int path 0;int subsetXORSum(vector<int>& nums) {dfs(nums, 0);return sum;}void dfs(vector<int>& nums,…

大模型分布式训练技术(DP、DDP和FSDP)

目录 数据并行&#xff08;PyTorch DP&#xff09; 分布式数据并行&#xff08;PyTorch DDP&#xff09; DP 与 DDP 的区别 补充说明&#xff1a;DP与DDP数据传输过程 完全分片数据并行(PyTorch FSDP) 补充说明&#xff1a;ZeRO FSDP DDP 与 FSDP 的区别 DP、DDP和FSD…

ADW400环保监测模块,用于各省市环保平台对接

ADW400环保监测模块主要用于计量低压网络的三相有功电能&#xff0c;同时可选择四个回路的电流输入&#xff0c;具有RS485通讯和470MHz无线通讯功能&#xff0c;方便用户进行用电监测、集抄和管理。可灵活安装于配电箱内&#xff0c;实现对不同区域和不同负荷的分项电能计量&am…

构建智慧园区的全方位解决方案:技术、部署与挑战应对

在当今数字化转型的浪潮中,智慧园区作为城市智能化的重要组成部分,正在成为各地政府和企业关注的焦点。本文将围绕一套完整的智慧园区解决方案,详细阐述其技术架构、部署流程以及在实施过程中可能遇到的挑战及应对策略。 1. 智慧园区解决方案概述 智慧园区解决方案旨在通过先…

Qt 一个带数据压缩的加解密实现类,压缩率达到了1/3

一.加解密效果 1-1000字符串,所占大小2890(加密前) 1-1000字符串,所占大小1964(加密后) 二.加解密功能实现类 /* Copyright (c) 2011, Andre Somers All rights reserved.Redistribution and use in…

Windows上安装 nodejs,npm 和 yarn详细教程

1、下载Node.js 访问Node.js 官网下载&#xff0c;下载需要版本版本&#xff0c;具体操作如下 2、安装Node.js 具体安装可参考以下知乎教程 https://www.zhihu.com/question/591831850/answer/3423661990 3、配置淘宝镜像 npm config set registry https://registry.npmmirror…

Codeforces Round 925 (Div. 3) E. Anna and the Valentine‘s Day Gift (博弈论*1400)

根据题目条件&#xff0c;我们知道10的m次方就是1后面跟着m个0&#xff0c;也就是说这是个最小的m1位数。 那么只要是最终得来的数的尾数是m1位数就可以通过。 思考影响数位的因素&#xff1f; 在这道题里&#xff0c;安娜能够对数位进行的操作只有删去后导零&#xff0c;由此…

安卓刷机笔记

前置知识 双清— 清除data 、 cache 四清----清除 data 、 cache 、 dalvik分区 、 system分区 四清的好处&#xff1a;卡刷ZIP格式的刷机包都是使用第三方recovery刷入的&#xff0c;所以我们在刷机之前对上一个系统的数据&#xff0c;包括用户数据、系统残留都需要彻底清除&a…

dolphinscheduler 日志乱码

dolphinscheduler 日志乱码如下图所示&#xff0c;检查服务器编码为zh_CN.UTF-8 修改$dolphinscheduler/bin/env/dolphinscheduler_env.sh 增加 JAVA_OPTS"$JAVA_OPTS -Dfile.encodingUTF-8" 参数 重新安装启动 修改前 修改后