当前位置: 首页 > news >正文

用PHP异步协程控制python爬虫脚本,实现多协程分布式爬取

背景

公司需要爬取指定网站的产品数据。但是个人对python的多进程和协程不是特别熟悉。所以,想通过php异步协程,发起爬取url请求控制python爬虫脚本,达到分布式爬取的效果。

准备

  • 1.准备一个mongodb数据库用于存放爬取数据
  • 2.引入flask包,方便php通过调用url发起请求控制脚本
  • 3.引入selenium、BeautifulSoup4、webdriver等python包
  • 4.使用php的swoole异步协程发送url请求

python爬虫脚本

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from flask import Flask,jsonify,request
from pymongo import MongoClient
from datetime import datetime
from gevent import pywsgi
import sys
import requests
import re
from tornado.httpserver import HTTPServer
from tornado.wsgi import WSGIContainer
from tornado.ioloop import IOLoop#创建一个服务,赋值给APP
app = Flask(__name__)@app.route('/get_ic_product_list',methods=['post']) #指定接口访问的路径,支持什么请求方式get,post
def get_ic_product_list():# url = 'https://www.ic.com/psen/ClassList2.aspx?id=3'# url = 'https://www.ic.com/ClassList2.aspx?id=3'chrome_options = webdriver.ChromeOptions()chrome_options.add_argument('--no-sandbox')chrome_options.add_argument('--headless')chrome_options.add_argument('--disable-gpu')chrome_options.add_argument('--ignore-certificate-errors')browser = webdriver.Chrome()conn = MongoClient('192.168.0.143', 27017)try:uri = request.form.get('url')# 是否按照零库存处理 yes-是 no-否isContinue = request.form.get('is_continue_stock', 'yes')# uri = sys.argv[1]# isContinue = sys.argv[2]if uri == '':return jsonify({'status': 0, 'msg': 'uri is null'})browser.get(uri)browser.implicitly_wait(3)time.sleep(2)# 连接mongodatabase = conn.iccollection = database.ic_product# 时间格式化nowtime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')spiderTime = datetime.now().strftime('%Y%m%d')spidertime = int(spiderTime)# 总页数pageTag = browser.find_element(By.CLASS_NAME, 'P_Page')total_page = pageTag.text.strip().split('/')[1]# 分类列表,不按照stock=0处理cateMap = ['21', '43', '175','179','184','241','250','268','306','317','325','343','397','394','409','467','547','556','606','638','657','678','1150','1158','2315','2383']if total_page:t_page = int(total_page)if t_page > 20:totalPage = 55else:totalPage = t_pageelse:totalPage = 20stop = 0soup = BeautifulSoup(browser.page_source, 'html.parser')tables = soup.findAll(name="table", attrs={"class": "prilist"})if len(tables) > 0:for table in tables:# 阶梯价price_tb = table.findAll('tr')price = [tb.text.strip() for tb in price_tb]# 行数据cols = table.parent.parentitem = [col.text.strip() for col in cols]time.sleep(2)print('==========item==========')print(item)# 库存为0,终止程序stock = item[11]if stock == '-':stop += 1continuepos = item[3].find('Promotion')if pos != -1:sku = str(item[3].replace('(Promotion)', ''))else:sku = item[3]# 格式化数据collection.insert_one({'datasheet': str(item[0]),'img_url': str(item[1]),'productDescEn': str(item[2]),'part': sku,'manufacturer': str(item[5]),'description': str(item[7]),'pdfLinkUrl': str(item[10]),'availability': str(item[11]),'price': price,'created_at': nowtime,'spider_time': spidertime,'sync_time': 20010101,'updated_at': '2001-01-01 00:00:00',})# 接口请求在clickfor i in range(totalPage):print('==========i==========')print(i)browser.find_element(By.XPATH, './/div[@id="Pager1"]/a[9]').click()soup = BeautifulSoup(browser.page_source, 'html.parser')tables = soup.findAll(name="table", attrs={"class": "prilist"})print('==========stop==========')print(stop)if stop>10 and isContinue=='yes':breakif len(tables) < 1:return jsonify({'status': 0, 'msg': 'product list empty'})print('==========tables==========')print(tables)mongoData = []for table in tables:# 阶梯价price_tb = table.findAll('tr')price = [tb.text.strip() for tb in price_tb]# 行数据cols = table.parent.parentitem = [col.text.strip() for col in cols]time.sleep(2)print('==========item==========')print(item)# 库存为0,终止程序stock = item[11]if stock == '-':stop += 1continuepos = item[3].find('Promotion')if pos != -1:sku = str(item[3].replace('(Promotion)', ''))else:sku = item[3]# 格式化数据mongoData.append({'datasheet': str(item[0]),'img_url': str(item[1]),'productDescEn': str(item[2]),'part': sku,'manufacturer': str(item[5]),'description': str(item[7]),'pdfLinkUrl': str(item[10]),'availability': str(item[11]),'price': price,'created_at': nowtime,'spider_time': spidertime,'sync_time': 20010101,'updated_at': '2001-01-01 00:00:00',})# 插入mongomongoData and collection.insert_many(mongoData)print('================mongoData================')print(mongoData)del price, tablestime.sleep(5)return jsonify({'status': 1,'msg': 'ok'})except Exception as error:return jsonify({'status':0,'msg':error})finally:conn.close()browser.close()if __name__ == '__main__':app.run(host='0.0.0.0',port=8005,debug=True)          # 启动服务器# Tornado启动服务
# s = HTTPServer(WSGIContainer(app))
# s.listen(8005) # 监听 8080 端口
# IOLoop.current().start()

php协程调用curl请求封装

在laravel 框架下创建command服务
此处有用到redis队列的,有不熟悉的请阅读redis相关资料

<?php
/*** 爬取IC任务*/
namespace App\Console\Commands;use App\Models\IcProductCategoryModel;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
use Swoole\Timer;class SpiderIcProductList extends Command
{/*** The name and signature of the console command.** @var string*/protected $signature = 'spider:ic_product';/*** The console command description.** @var string*/protected $description = '每天定时爬取IC网站数据';/*** Create a new command instance.** @return void*/public function __construct(){parent::__construct();}/*** Execute the console command.** @return int*/public function handle(){$this->getProduct();return 0;}public function getProduct(){/*** ic product_num> 0, 分类约345个* 目前15min【900 * 1000】爬取10个分类,一天能爬取960个分类,一天能爬2次*/Timer::tick(60 * 15 * 1000,function (){$categoryModel = new IcProductCategoryModel();$key = $categoryModel::getCategoryQueue();echo 'time:' .date('H:i:s') .space();if (Redis::lLen($key) > 0) {$data = Redis::lRange($key,0,9);foreach ($data as $categoryId){go(function () use ($categoryId){$client = new \Swoole\Client(SWOOLE_SOCK_TCP);// 尝试与指定 TCP 服务端建立连接(IP和端口号需要与服务端保持一致,超时时间为0.5秒)if ($client->connect("127.0.0.1", 9505, 0.5)) {// 建立连接后发送内容$data = ['service' => 'RemoteApiSpider','method' => 'getProduct','param' =>  ['category_id' => $categoryId,'platform' => PLATFORM_IC,],];$sendData = jsonE($data);echo  'send=' .$sendData  .' ,'. date('H:i:s')   .space();$client->send($sendData);// 打印接收到的消息echo $client->recv();// 关闭连接$client->close();} else {echo "connect failed.";}});}Redis::lTrim($categoryModel::getCategoryQueue(),10,-1);unset($data);}});echo 'spider product end time:' .date('H:i:s') .space();}
}

创建服务端Server

<?phpnamespace App\Console\Commands;use App\Services\RemoteApiSpider;
use App\Services\TcpService;
use App\Services\TestService;
use Swoole\Database\MysqliConfig;
use Swoole\Database\MysqliPool;
use Swoole\Server;class Swoole extends Base
{protected $ws;/*** The name and signature of the console command.** @var string*/protected $signature = 'swoole {action} {--d}';/*** The console command description.** @var string*/protected $description = 'swoole service command';/*** Create a new command instance.** @return void*/public function __construct(){parent::__construct();}/*** Execute the console command.** @return int*/public function handle(){global $argv;$action = $this->argument('action');$argv[0] = 'wk';$argv[1] = $action;$argv[2] = $this->option('d') ? '-d' : '';$this->startServer();return 0;}public function startServer(){$server = new \Swoole\Server("127.0.0.1", 9505);// 设置异步任务的工作进程数量$log_path = storage_path() . '/logs/server.log';$server->set(['daemonize' => true,'log_file' =>  $log_path,'task_worker_num' => 50,]);//收到请求时触发$server->on('receive', function(\Swoole\Server $server, $fd, $from_id, $data) {//投递异步任务$task_id = $server->task($data);echo "异步任务投递成功: id=$task_id , recv={$data} " .his() . space();$server->send($fd, "task_id[{$task_id}],recv={$data},数据已接收,处理中... " .his() . space());});// 处理异步任务$server->on('Task', array($this, 'onTask'));//        $server->on('task', function (\Swoole\Server $server, $task_id, $from_id, $data) {
//            echo "新的待处理异步任务[id=$task_id] ".his() . space();
//            /**
//             $data = ['data' => [],'code' => '200','msg' => 'false']
//             */
//            $service = new RemoteApiSpider();
//            $service->setDebug(true);
//            if($data && is_string($data)){
//                $data = jsonD($data);
//            }
//            $ret = false;
//            if($data['code']==200 && $data['msg'] == 'ok'){
//                if(isset($data['data']['category_id']) && $data['data']['category_id']){
//                    $categoryId = $data['data']['category_id'];
//                    $ret = $service->getProduct($categoryId);
//                }
//            }
//            // todo 处理异步任务
//            // 返回任务执行的结果
//            $msg = "task_id[{$task_id}] ,category_id:" .$data . " ,ret:".$ret . " ," . his() . space();
//            $server->finish($msg);
//        });// 处理异步任务的结果$server->on('finish', function (\Swoole\Server $server, $task_id, $data) {echo "异步任务[$task_id] 处理完成: $data ". his() . space();});$server->start();}public function process(){$server = new TcpService();// 定义连接建立回调函数$server->onConnect = function ($conn) {echo "onConnect -- accepted " . stream_socket_get_name($conn, true) . "\n";};// 定义收到消息回调函数$server->onMessage = function ($conn, $msg) {echo "onMessage --" . $msg . "\n";$service = new RemoteApiSpider();$service->setDebug(true);$content = $service->getProduct($msg);fwrite($conn, "received " . $msg . "\n");};// 定义连接关闭回调函数$server->onClose = function ($conn) {echo "onClose --" . stream_socket_get_name($conn, true) . "\n";};// 启动服务器主进程$server->run();}public function onTask($serv, $task_id, $from_id, $data){//传类名、方法、参数实现公共使用try {if (!$data) {throw new \Exception(' task_id=' . $task_id . ',暂无需要处理的task任务', 400);}if (is_string($data)) {$data = jsonD($data);}echo 'recv: ' . jsonE($data) . space();$className = "App\Services\\{$data['service']}";if (!class_exists($className)) {throw new \Exception(' task_id=' . $task_id . ',未找到服务类名', 401);}$class = new $className;$func = $data['method'];if(isset($data['param'])){$ret = $class->$func($data['param']);}else{$ret = $class->$func();}return jsonE($ret);} catch (\Exception $e) {$msg = ' task_id=' . $task_id . ' ,error: ' . $e->getMessage();echo jsonE($msg) . space();}$serv->finish($msg);//每分钟执行一下service下的start方法,发送二维数组请求给tcp服务端,服务端调用service下的process方法实现业务逻辑//服务端拿到数据后,处理后结果格式:['code'=> 200,'msg'=> 'ok','data' => maxid]
//        $data = [
//            'service' => 'TestService',
//            'method' => 'process',
//            'param' => ['debug'=> true,'send' =>'sucess'],
//        ];//暂时留空 2.3部分会完善}}

curl发送异步请求调用python脚本

<?php
/*** 爬取接口封装*/
namespace App\Services;use App\Library\Oneyac\Oneyac;
use App\Models\HqchipProductCategoryModel;
use App\Models\HqchipProductMongoModel;
use App\Models\IcProductCategoryModel;
use App\Models\IcProductMongoModel;
use App\Models\LcscProductCategoryModel;
use App\Models\LcscProductMongoModel;
use App\Models\OneyacProductCategoryModel;
use App\Models\OneyacProductMongoModel;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;class RemoteApiSpider extends Base
{/*** 根据分类循环分页爬取产品列表* @param $data* @return int* @throws \GuzzleHttp\Exception\GuzzleException*/public function getProduct($data){$cateId = 0;$categoryId = $data['category_id'] ?? $cateId;$platform = $data['platform'] ?? PLATFORM_LCSC;$platform = strtolower(trim($platform));$categoryId = (int)$categoryId;switch ($platform) {case PLATFORM_IC:$cateModel = new IcProductCategoryModel();Redis::hDel($cateModel::getCategoryListKey(),$categoryId);//TODO 调用python API接口爬取产品数据//s2 20分钟处理4个 与 s1 20分钟处理6个 $header = [];$header['Content-Type'] = 'application/json;charset=UTF-8';$query_param['page'] = 1;$res = $this->getIcProduct($categoryId, $platform,$query_param, $header);$res && $cateId = $categoryId;break;}return $cateId;}/*** 获取ic产品信息* @param $categoryId* @param $platform* @param $query_param* @param $header* @return bool* @throws \GuzzleHttp\Exception\GuzzleException*/public function getIcProduct($categoryId, $platform, $query_param, $header){$module =  'product_list';$this->getPlatformConf(PLATFORM_IC,$module);$msg = ' ' . $platform . '_' . $module . ' ';echo $msg. ' ,category_id:' . $categoryId . ' spidering' .space();try {//$uri = 'https://www.ic.com/psen/ClassList2.aspx?id=3';$uri = $this->base_uri . $this->uri . '?id=' . $categoryId;# todo 3的倍数推入s2,其他推入s1$config = config('ic');# 重点:此处可以部署到不同服务器进行爬取,我这里只部署了2台服务,s1与s2if(($categoryId%3)===0){//s2$curl = $config['spider_uri']['s2'] ?: 'http://192.168.0.124:8005/get_ic_product_list';}else{//s1$curl = $config['spider_uri']['s1'] ?: 'http://192.168.0.127:8005/get_ic_product_list';}$response = curlPost($curl,['url' => $uri,'is_continue_stock' => 'yes']);$flag = false;if(isset($response) && !empty($response)){$response = is_array($response) ? $response : jsonD($response);$flag = ($response['msg']=='ok' && $response['status']==1);}if ($flag) {$this->debug && Log::info($msg . 'category_id:' . $categoryId . ' ,mongo-batch-insert:' . $flag);} else {throw new \Exception($msg.'ic爬虫异常,请检查python爬虫');}unset($response);return  $flag;}catch (\Exception $e){Log::error($msg .'爬取产品异常,异常原因:'.$e->getMessage());return false;}}

nginx配置

server {listen 8080;server_name spidertest.test *.spidertest.test;root "D:/WWW/spidertest/";location / {proxy_pass http://127.0.0.1:8005;}charset utf-8;
}
  • 注:
    1.在不同服务器上部署python爬虫脚本,并配置nginx服务。配置完成后安装下面命令启动脚本。接下来开启异步多线程执行python爬虫脚本即可。
    2.记得启动swoole服务。命令如下:
php artisan swoole start

运行

python脚本启动
在这里插入图片描述

postman测试:
![在这里插入图片描述](https://img-blog.csdnimg.cn/c24295c2a30c4f79a377856df4bb9767.png

php启动协程命令:
在这里插入图片描述

爬取回来的数据结果:在这里插入图片描述

相关文章:

用PHP异步协程控制python爬虫脚本,实现多协程分布式爬取

背景 公司需要爬取指定网站的产品数据。但是个人对python的多进程和协程不是特别熟悉。所以&#xff0c;想通过php异步协程&#xff0c;发起爬取url请求控制python爬虫脚本&#xff0c;达到分布式爬取的效果。 准备 1.准备一个mongodb数据库用于存放爬取数据2.引入flask包&a…...

VUE3写后台管理(3)

VUE3写后台管理&#xff08;3&#xff09; 1.环境1.node2.vite3.Element-plus4.vue-router5.element icon6.less7.vuex8.vue-demi9.mockjs10.axios11.echarts 2.首页1.布局Main2.头部导航栏CommonHeader3.左侧菜单栏CommonLeft4.首页Home1.从后端获取数据显示到前端table的三种…...

机器学习笔记之最优化理论与算法(十二)无约束优化问题——共轭梯度法

机器学习笔记之最优化理论与方法——共轭梯度法 引言回顾&#xff1a;共轭方向法的重要特征线性共轭梯度法共轭方向公式的证明过程 关于线搜索公式中参数的化简关于线搜索公式中步长部分的化简关于线搜索公式中共轭方向系数的化简参数化简的目的 非线性共轭梯度法(FR,PRP方法)关…...

JVM中的java同步互斥工具应用演示及设计分析

1.火车站售票系统仿真 某火车站目前正在出售火车票&#xff0c;共有50张票&#xff0c;而它有3个售票窗口同时售票&#xff0c;下面设计了一个程序模拟该火车站售票&#xff0c;通过实现Runnable接口实现&#xff08;模拟网络延迟&#xff09;。 伪代码&#xff1a; Ticket类…...

数据治理-数据质量

实现数据质量的前提就是数据本身是可靠和可信的。 导致数据质量低下的因素 组织缺乏对低质量数据影响的理解&#xff0c;缺乏规划、孤岛式系统设计、不一致的开发过程、不完整的文档、缺乏标准或缺乏治理等。 所有组织都会遇到与数据质量有关的问题。数据质量需要跨职能的承诺…...

[sqoop]hive3.1.2 hadoop3.1.1安装sqoop1.4.7

参考: Hadoop3.2.4Hive3.1.2sqoop1.4.7安装部署_hadoop sqoop安装_alicely07的博客-CSDN博客 一、安装 1、解压 tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /home/data_warehouse/module mv sqoop-1.4.7.bin__hadoop-2.6.0 sqoop-1.4.72、配置文件 sqoop-env.s…...

js事件的详细介绍

11.事件 1.什么是事件 js属于事件驱动编程,把驱动,执行,调用通过一些交互,触发一些函数事件:发起-->执行绑定事件-->触发事件on 绑定 emit触发 off解绑2.事件分类 鼠标事件 点击事件 onclick 双击事件 ondblclick 按下事件 onmousedown 抬起事件 onmouseup 鼠标进…...

虚幻4学习笔记(12)操控导入的角色、动画蓝图、播放蒙太奇和打包、角色重定向

虚幻4学习笔记 操控导入的角色设置鼠标旋转关掉动态模糊 动画蓝图、播放蒙太奇和打包角色走路奔跑动画shift 奔跑F 跳舞移动打断 跳舞 打包角色重定向姿势调整解决跑步 腿分太开隐藏剑 B站UP谌嘉诚课程&#xff1a;https://www.bilibili.com/video/BV164411Y732 操控导入的角色…...

hive with tez:无法从链中的任何提供者加载aws凭据

环境信息 hadoop 3.1.0 hive-3.1.3 tez 0.9.1 问题描述 可以从hadoop命令行正确地访问s3a uri。我可以创建外部表和如下命令&#xff1a; create external table mytable(a string, b string) location s3a://mybucket/myfolder/; select * from mytable limit 20; 执行正…...

Ubuntu修改静态IP、网关和DNS的方法总结

Ubuntu修改静态IP、网关和DNS的方法总结 ubuntu系统&#xff08;其他debian的衍生版本好像也可以&#xff09;修改静态IP有以下几种方法。&#xff08;搜索总结&#xff0c;可能也不太对&#xff09; /etc/netplan (use) Ubuntu 18.04开始可以使用netplan配置网络&#xff0…...

Eureka服务器注册

一。Eureka服务器注册 1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://mav…...

Windows安装GPU版本的pytorch详细教程

文章目录 chatGLM2-6B安装教程正式安装 chatGLM2-6B ChatGLM2-6B版本要装pytorch2.0&#xff0c;而且要2.0.1 &#xff0c;因此CUDA不能用12.0 &#xff0c;也不能用10.0&#xff0c;只能用11.x 版本。 安装教程 pip install直接下载安装 官网&#xff1a; https://pytorch.…...

理解Kruskal算法的前提----深入理解并查集【超简单~】

并查集的实现思路 并查集主要分为两个部分&#xff1a;第一部分就是需要找到点对应的祖宗节点&#xff0c;第二部分&#xff0c;是要将属于同一个集合节点的祖宗节点进行统一&#xff0c;也就是结合操作。 Find函数实现 // parent数组用来存储下标值所对应的父节点值 // 比如…...

Jenkins+Gitee+Docker+Ruoyi项目前后端分离部署

前言 描述&#xff1a;本文主要是用来记录 如何用标题上的技术&#xff0c;部署到云服务器上通过ip正常访问。 一、总览 1.1、Docker做的事 拉取 mysql 镜像拉取 redis 镜像拉取 jdk 镜像拉取 nginx 镜像 解释说明&#xff1a;前端项目的打包文件放在 nginx容器运行。后端…...

笙默考试管理系统-MyExamTest----codemirror(23)

笙默考试管理系统-MyExamTest----codemirror&#xff08;23&#xff09; 目录 笙默考试管理系统-MyExamTest----codemirror&#xff08;23&#xff09; 一、 笙默考试管理系统-MyExamTest 二、 笙默考试管理系统-MyExamTest 三、 笙默考试管理系统-MyExamTest 四、 笙…...

重学Java (一) 泛型

1. 前言 泛型编程自从 Java 5.0 中引入后已经超过15个年头了。对于现在的 Java 码农来说熟练使用泛型编程已经是家常便饭的事情了。所以本文就在不对泛型的基础使用在做说明了。 如果你还不会使用泛型的话&#xff0c;可以参考下面两个链接 Java 泛型详解The Java™ Tutorial…...

Docker 部署 Redis 服务

拉取最新版本的 Redis 镜像: $ sudo docker pull redis:latest在本地预先创建好 data 目录和 conf/redis.conf 文件。 使用以下命令来运行 Redis 容器: $ sudo docker run -itd --name redis --privilegedtrue -p 6379:6379 -v /home/ubuntu/docker/redis/data:/data -v /ho…...

阿里云产品试用系列-负载均衡 SLB

阿里云负载均衡&#xff08;Server Load Balancer&#xff0c;简称SLB&#xff09;是云原生时代应用高可用的基本要素。通过将流量分发到不同的后端服务来扩展应用系统的服务吞吐能力&#xff0c;消除单点故障并提升应用系统的可用性。阿里云SLB包含面向4层的网络型负载均衡NLB…...

drf 对象级权限

drf 对象级权限 Django REST Framework&#xff08;DRF&#xff09;提供了对象级别权限&#xff08;Object-level permissions&#xff09;来控制特定对象的访问权限。 简单来说&#xff1a;通过视图类中的self.get_object(pk)得到一个obj对象(视图对象)&#xff0c;在与requ…...

八大排序(二)--------冒泡排序

本专栏内容为&#xff1a;八大排序汇总 通过本专栏的深入学习&#xff0c;你可以了解并掌握八大排序以及相关的排序算法。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;八大排序汇总 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...