最近用 ai 辅助编写了一个校园卡号码筛选小脚本,爬了有 9000+条号码数据号码筛选页面实现的功能:特定号码字段的搜索特定规则预制筛选点击号码标记为已喜爱,方便后续筛选在已喜爱界面右键号码可以添加备注标红显示符合规则的数字(方便查看)支持自定义添加靓号规则(实现模块化)而在爬虫页面实现的功能:支持设置停止条件支持设置随机等待间隔(防止访问过快被 ban)支持自定义搜索字段由于已经选到心仪的号码,便决定不再维护此项目,上传的 github 上去,因此便学了学 git 的使用git 使用教程1.首先先在 github 上新建一个仓库,记录下 git 的地址2.输入git init，git init在当前项目的目录中生成本地的git管理（会发现在当前目录下多了一个.git文件夹）3.输入git add . git add . 这个是将项目上所有的文件添加到本地仓库中的意思，如果想添加某个特定的文件，只需把.换成这个特定的文件名即可,例如:git add envlist.txt4.用git status 可以查看当前仓库的提交状态(这一步可以忽略，只是查看提交到本地的代码是否成功);git status5.输入git commit -m "first commit"；git commit -m "first commit双引号内部表示对这次提交的注释，双引号里面的内容可以根据个人的需要改。会出现在文件的后方6.输入git remote add origin https://github.com/huangzhenhong520/test.git ,将本地的仓库关联到github上。git remote add origin https://github.com/huangzhenhong520/test.git7.输入git push -u origin master，把代码上传到github仓库git push -u origin master实际遇到的问题:1.第七步执行失败,提示error: src refspec master does not match any error: failed to push some refs to 'https://github.com/shiyunqi001/phone_select.git'是由于仓库中不是 master 而是 main,将名称替换即可2.提交时提示To https://github.com/shiyunqi001/phone_select.git ! [rejected] main -> main (fetch first) error: failed to push some refs to 'https://github.com/shiyunqi001/phone_select.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.这是因为远程仓库和本地文件不同步导致的,(比如仓库新增 README.md,而本地没有这个文件),解决办法就是先将仓库的内容合并到本地git pull origin main接着再 push 到远程仓库即可3.远程仓库和本地出现分叉时设置合并策略git config pull.rebase falsepull.rebase false 就是 merge 策略。这个设置是一次性的，设置好之后，以后在这个项目里就不用再输了。4.显示隐私信息git config --global user.name "shiyunqi001"修改提交的 ID5.修改终端的显示方式直接自定义终端提示符（Prompt）的显示格式。终端用的是 Zsh (因为末尾是 %)，所以可以通过修改 ~/.zshrc 文件来实现。打开终端使用一个文本编辑器打开 Zsh 的配置文件。 用 nano 这个简单的行内编辑器来操作。Bashnano ~/.zshrc(如果提示文件不存在，不用担心，这会创建一个新文件。)在文件末尾添加一行喜欢的格式。 将下面这行代码复制并粘贴到 nano 编辑器的窗口里：BashPROMPT='%~ %# '这是一个非常流行和简洁的格式。%~ 代表“显示当前路径”（例如 ~ 或 ~/Documents）。%# 会在普通用户下显示 %，在 root 用户下显示 #。保存并退出。按 Control + O (是字母O，不是零) 来保存文件，然后按 Enter 确认。按 Control + X 来退出 nano 编辑器。让配置立即生效。 在终端里运行下面的命令，或者直接重启终端。Bashsource ~/.zshrc现在，无论用户名和主机名是什么，终端提示符都会变成非常简洁的样子： ~ % 或者进入一个项目文件夹时： ~/code/phone_picker %这样既简洁高效，又能最大限度地保护隐私。
0x0 简介用这个教程简单记录一下 conda 在 mac 上的安装教程以及怎样在 vscode 中切换环境[引用]https://blog.csdn.net/Linshaodan520/article/details/1387342340x1 什么是 conda?在初学Python之时，就常听别人说用 conda 有多方便，一直不以为然，直到接触需要调用有大量依赖库及版本间有显著差异的深度强化学习领域时，才知道用 conda 管理环境会有多方便，那么什么是 conda？Conda 发行并开源于 2012 年，是一个可以在Windows、maxOS和Linux上运行的包和环境管理系统，它能够适用于任何语言的打包和分发，包括Python、R、Ruby、Lua、Java、C/C++等。Conda 允许用户方便地安装、运行和更新不同版本的二进制软件包与该计算平台所需要的所有库（以及库的依赖项）。在实际当中，利用 conda 最主要的目的是为了使得不同版本Python环境、不同版本模块能够共存和灵活切换。除了 conda，我们常常看到的 Anaconda 和 Miniconda 又是什么呢？接下来将介绍 conda 与它们之间的区别。0x1.1 Conda 与 Anaconda 的区别诸如 Anaconda、Miniconda、Bioconda（用于计算生物学）等都是基于 conda 的工具软件，这些软件均包含 conda 包和环境管理器，但两者的概念仍要进行一定的区分。Anaconda 是一个大而全的软件发行版，是一个预先建立和配置好的模块集，能够安装在操作系统上使用。它包含了Python本身和数百个第三方开源项目的二进制文件，如 numpy、scipy、ipython、matplotlib等，这些库基本是为了方便处理数据科学相关的问题。Miniconda 也是一个软件发行版，但它仅包含python、conda 和 conda 的依赖项，本质上就是一个空的用来安装 conda 环境的安装器，它没有 Anaconda 中那么多的包，可以理解为 Anaconda 的精简版，能够方便用户按照自己的需求，从零开始构建任意的环境。尽管可以独立地下载安装 conda 而不用 Anaconda 和 Miniconda，但后两者为提供了 conda 安装环境，使用起来会更方便。0x2 下载安装这里我们演示 Miniconda 的下载安装，软件包的下载来源有两种：官方网站：https://docs.anaconda.com/free/miniconda/miniconda-install/清华源：https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/，个人试了下镜像源关闭了，好像是因为未取得 Anaconda 和 Miniconda 的授权。(1)检查系统条件是否满足在下载安装 Miniconda 之前，先检查下电脑的系统及硬件等条件是否符合安装要求。如果因为系统版本较旧的原因，可以下载对应的旧版本 Miniconda，以下是官网中对系统要求的描述.(2)下载相应的安装包如下图，以 Mac installers 为例，不同版本的 Miniconda 安装包可以支持的最高版本的 python 情况不同，可以按需下载，这里我下载了支持 python3.12 的软件版本.(3)执行安装下载到后缀为 pkg 的 miniconda 文件后,一路点安装即可,这里不再赘述(4)检查是否安装成功完场上述步骤之后，需要再检查下 conda 是否能够正常使用打开终端，在终端中输入 **conda --version，回车如果返回了 conda 版本信息则说明安装成功。0x3 配置并使用conda至此完成了 conda 包和环境管理工具的安装，此时我们可以进行一些简单的配置并尝试创建 conda 环境，安装需要的库和运行简单的 python 程序。配置下载源Conda 包管理器下载各类库的来源是国外的服务器，常常会面临下载速度慢的问题。可以为 conda 添加软件包通道（channel），以清华源为例，在打开的 **Anaconda prompt 控制台窗口中，输入如下命令可以将清华源的两个地址添加到通道。 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/为了在查看 conda 软件包通道的下载链接时能显示我们手动配置的通道地址，可以通过如下命令进行设置： conda config --set show_channel_urls yes如果不配置下载源，conda 会使用默认的软件包通道，即从官方 Anaconda 仓库获取软件包。具体的软件包通道情况可以通过 conda config --show 命令查看，返回的信息不仅能看到下载源的地址信息，还能看到创建的 conda 环境所在的文件夹。如果想要重置下载源的信息，可以用 conda config --remove-key channels 命令实现。环境管理现在来到 conda 的另一大功能，就是环境管理，它可以创建、管理和切换不同的环境，这些环境之间是相互独立的，每个环境当中的 Python 版本和软件包版本可以不相同，使得我们可以把依赖版本不同的项目放在同一台设备上的不同 conda 环境中运行。1.创建(删除)环境要创建一个新的 conda 环境，可以使用 conda create 命令，指定该环境下所需的 Python 版本和要安装的软件包。例如：conda create --name myenv python=3.8 numpy matplotlib这将创建一个名为 myenv 的环境，并在其中安装 Python 3.8、NumPy 和 Matplotlib。在创建环境时，会有软件包列表的提示。输入 y 确认后即等待环境创建即可。如果不想要一个环境了，例如我们要把 myenv 这个名字的环境删除，可以通过如下命令进行删除： conda remove --name myenv --all注意： 如果你的环境没有一个明确的名字（比如它直接在项目文件夹里创建），你可能需要使用路径来删除。在 conda env list 的输出中找到它的路径，然后使用 --prefix 或 -p 参数：Bash # 假设路径是 /Users/your_username/your_project/.conda conda env remove --prefix /Users/your_username/your_project/.conda执行这个命令后，Conda 会尝试移除环境，当它发现文件夹已经不在时，通常会直接清理掉其在配置文件中的条目。2.激活(切换)环境经过环境的创建之后，我们用 conda env list 来查看已有的 conda 环境，发现已经创建好了名为 myenv 的环境，但是此时我们根据如下位置判断我们所在的 conda 环境仍然是名为 base 的环境，因此我们要激活并切换到 myenv 环境中。通过如下命令可实现激活并切换环境的功能 conda activate myenv如果不切换环境，而只是退出当前环境，可以用 conda deactivate 退出当前的 conda 环境。3.下载(卸载)库当我们要在不同环境下安装库时，需要先切换到指定环境当中，例如我们要下载或者卸载 **scipy，可以执行如下命令进行： # 下载安装 conda install scipy # 卸载 conda remove scipy4.导出环境当我们想要保存某个环境的配置信息，例如下载源信息、环境的Python版本信息、安装的包的版本信息等，可以先切换到指定环境下，通过以下命令将这些配置信息导出： conda env export > environment.yml该命令会将当前的环境配置信息导出到为 environment.yml 配置信息文件，文件导出地址默认为当前工作目录（也可以指定输出的绝对地址）。这时候，我们将配置文件传到另一台电脑，想基于该配置文件创建 conda 环境，可以通过以下命令： conda env create -f environment.yml0x4 常见问题记录一些常见问题conda无法访问清华源conda无法访问清华源怎么结束jupyter notebook的进程运行情况一：启动 Jupyter 的终端窗口还在这是最常见也是最推荐的方式。找到那个终端窗口：就是你之前输入 jupyter notebook 或 jupyter lab 命令后，它一直在输出日志信息的那个窗口。按下 Control + C：在键盘上同时按下 Control 键和 C 键。确认关闭：终端会提示你 Shutdown this notebook server (y/[n])?。意思是“是否要关闭这个 notebook 服务器？”输入 y 然后按 回车（Enter） 键确认。稍等片刻，Jupyter 服务就会被干净地关闭，所有相关的进程也会被终止。情况二：找不到原来的终端窗口（或已经关闭）如果你不小心关掉了那个终端窗口，或者是在一个远程服务器上启动后断开了连接，Jupyter 服务其实还在后台运行。这时你需要手动找到并“杀死”这个进程。步骤 1: 查找正在运行的 Jupyter 服务Jupyter 有一个内建命令可以列出所有正在运行的服务和它们的端口号。在任意一个新的终端窗口中输入：Bashjupyter server list或者使用旧一点的命令：Bashjupyter notebook list你会看到类似下面的输出：Currently running servers: http://localhost:8888/?token=... :: /Users/your_username/Documents从这里你可以知道，有一个 Jupyter 服务正在 8888 端口上运行。记下这个端口号。步骤 2: 通过端口号找到进程并终止它现在我们知道了端口号，就可以用它来找到对应的进程ID（PID），然后终止该进程。查找进程 ID (PID)：在终端输入以下命令（将 8888 替换成你上一步找到的端口号）：Bashlsof -i :8888这个命令会列出所有正在使用 8888 端口的进程。输出结果中，找到 COMMAND 为 Python 或 jupyter 的那一行，然后记下它在 PID 列的数字。COMMAND PID USER ... NODE NAME Python 52891 your_username ... TCP localhost:8888 (LISTEN)在这个例子中，进程ID（PID）是 52891。终止进程 (Kill)：使用 kill 命令加上你找到的 PID 来终止它。Bashkill 52891这个命令会给进程发送一个“请正常关闭”的信号。通常这就足够了。强制终止 (如果需要)：如果上面的 kill 命令没有效果，你可以使用 -9 参数来强制终止进程。这相当于“任务管理器”里的“强制结束”，可能会导致未保存的工作丢失，所以请作为最后手段使用。Bashkill -9 52891执行完 kill 命令后，Jupyter 服务就会被彻底终止。如何在 vscode 里切换 conda 环境在编辑器里使用 cmd+shift+p唤出快捷键后,查找 python,选择Select Interpreter接下来选择 想要的 conda 环境即可,可以新建也可以选中已有的环境怎样在 vscode 中使用 git 时使用代理# 设置 HTTP 代理 git config --global http.proxy http://127.0.0.1:7890 # 设置 HTTPS 代理 git config --global https.proxy http://127.0.0.1:7890 # 如果后续需要取消代理 # git config --global --unset http.proxy # git config --global --unset https.proxy # 仅对本项目生效就去掉 globle 参数
[hplayer][Music server="netease" id="31649312" type="song"/][/hplayer]写在前面失败总是贯穿人生始终。为什么要提起这段话呢，因为我在博客内使用了emoji表情，而导致之前写的两千多字全部丢失，让人遗憾。在短暂的错愕后，决定重振旗鼓，再次凭借记忆写写之前写下的话。第一遍写下的幼稚的话就不再写第二遍咯。这篇文章写在2023年2月17日，严格意义上也不算是年终总结，不过我还是愿意将其归类为年终总结，前年的年终总结：[post cid="94" cover="" size=""/]下面开始吧。感情[scode type="red" size="simple"]有遗憾，更多的是希望[/scode]回看自己曾经在博客记下的舔狗日记，不禁微微苦笑，曾经也是个被情所伤的人呢。不过往事随风，过去的事情也都过去了，也不再去回想好了。好在遇见现在依旧在身边的VC同学，她天真可爱，身材也很好，即使偶尔有小脾气我们之间也能彼此尊重，努力解决，实属良配。我能做的只有好好去爱，努力从情侣的激情转变为家庭的责任。生活[scode type="red" size="simple"]迷茫，还是迷茫。[/scode]仔细想想，在20出头的年纪里，也该到了为事业发愁的时候了。关注过很多博客的博主，一个个技术出众，比我好的简直不是一点半点，我也当然清楚自己是属于最普通的一类，原本想提升的技术这两年也有所停滞，不能说一点没学，只能说进步不大。当然我也不是没有努力，知道有一些试错成本的情况下，我也曾经尝试过许多职业。因为从小文采尚可，便在2022简单尝试网络小说创作。说是简单，实际上那段时间吃得苦却一点也不少，没日没夜思考故事情节，天天昼夜颠倒，看各种教程，和各种编辑对线。经历过无数的拒签/退稿之后，终于发布了自己的作品，当然，也曾经上了小推荐和大推荐，但终究还是没有坚持下来，或许是看不到未来吧，最终只收获三百元全勤稿费。也尝试过卖货/主播/代练....一系列，没有一项适合我。或许以后还是当个码农？或许从事网安？一切都说不准，但还是想在互联网行业待下去的。但现阶段除了迷茫又能做什么呢？只能加油了，任何时候觉醒都不晚。写下这篇博客的目的同样也是对生活的记录，希望日后翻看是有种“轻舟已过万重山”的畅快。关于未来[scode type="red" size="simple"]希望考研上岸[/scode]想了很久，还是把这块的主题定为：希望考研上岸。也算对自己的美好祝愿吧。原本第一版博客中分析了很多各种出路，以及自己内心纠结的抉择。不过我隐隐约约瞧见了未来前途最明朗的一条路。当下ChatGPT的爆火，让我看到了未来人工智能有无限的可能，或许修一个人工智能专业的硕士甚至博士，对未来的找工作以至于创业有更多的可能。目前想了几个构想，一个是AI+理发行业，另一个是AI+桌游，还有就是AI+游戏制作。AI到未来十年二十年内的趋势，应该都是和许多行业结合起来。倘若能深入内部学习算法，能自己独立创作AI，或许真的抓住了这个时代的风口。至少在我看起来，应该比这几年大力宣传的安全有更广阔的市场。写写2023的目标吧，明年五六月回来挖[goal title="2023"][item check="false"] 考研上岸人工智能，加油。[/item][item check="false"] 戒掉坏习惯，恢复跑步，练出腹肌 [/item][item check="false"] 和VC去更多更好玩的地方，维持美好的感情 [/item][item check="false"] 培养一些爱好吧，多读几本书 [/item][/goal]写在后面希望自己终究踏破重重迷雾，找到自己的路，加油。也有自己想要的未来，也有独特的想法，那就尽力去实现吧。或许这一年内的主旋律就是考研的记录了，到时候会多拍几张图片，记录考研经历。2024年年终总结再见！
计算机网络内容总结第一章 网络概述一、 计算机网络最重要的功能1、数据通信2、资源共享3、分布处理4.重要基本特点连通性和共享二、 因特网的两大组成部分1.2.三、 三种交换方式1.分组交换2.报文交换3.电路交换四、计算机网络的分类：按地域（中英文名称）五、 时延：时延的4个组成部分、计算。1.发送时延2.传播时延3.发送和传播图解4.处理时延5.排队时延6.时延带宽积带宽就是发送速率，单位是比特每秒时延带宽积单位是Bit六、 协议（定义、三要素及其含义）1.定义2.组成要素七、OSI参考模型、TCP/IP协议的层次结构及其作用1.OSI（开放系统互连）2.TCP\IP`八、5层体系结构各层及功能1.模型2.发送数据过程3.作用4.协议数据单元PDU1.物理层:比特bit2.数据链路层帧:Frame3.网络层:数据报Packet4.传输层:报文段Segment第二章 物理层物理层的四个特性:机械特性,电气特性,功能特性,规程特性一、关于信道（通信方式三种）1.单向通信（单工）2.双向交替通信（半双工）3.双向同时通信（双工）4.计算系统的最大传输速率理想系统无噪声:奈氏准则有噪声的信道:香农定理:香农公式表明，信道的带宽或信道中的信噪比越大，信息的极限传输速率就越高二、 常用的导向性传输媒体及其特性1.双绞线比同轴电缆快，比光缆慢，抗电磁干扰能力强2.同轴电缆抗干扰能力强3.光缆带宽大，更轻三、常用的非导向传输媒体短波、微波、地面接力、卫星四、信道复用1.FDM频分复用。所有用户在同样的时间占用不同的带宽。2.TDM时分复用。所有用户在不同的时间占用同样的频带宽度。3.STDM统计时分复用。STDM帧中的时隙不固定的分配给每个用户。4.WDM波分复用。光的频分复用5.CDMA码分复用（码分多地址）。每个用户可以在同样的时间使用同样的频带进行通信。各用户使用经过特殊挑选的不同码型，因此不会造成干扰。五、 CDMA工作原理及计算1.原理2.计算算出来1则发送1，算出来-1则发送了0，算出来0则不发送数据。第三章 数据链路层一、数据链路层协议的三个基本问题1.定义2.三个问题（1）封装成帧当IP数据报长度超过最大传输单元后，进行拆分（2）透明传输字节填充法图解：（3）差错检测存在比特差错：策略：冗余信息与正确信息存在某种数学关系，接收方根据冗余信息判断数据是否正确纠错码：充足的冗余信息检错码：适当的冗余信息二、差错检测检错码：循环冗余检验原理步骤 举例 计算添加在数据后面的校验位：多项式为n阶P是n+1位，余数要求n位，不够在前面补零三、PPP协议1.协议组成(1) 提供一个将IP数据报封装到串行链路的方法。(2) 链路控制协议LCP（Link Control Protocol）当线路不再需要时，挑出这些线路，测试它们，商议选择，并仔细地再次释放链路控制协议。（3）一套网络控制协议NCP（Network Control Protocol）其中每一个协议支持不同的网络层协议，如IP、OSI的网络层等。2.PPP帧格式3.字节填充法4.零比特填充法四、 局域网按拓扑结构的分类新鲜幻术五、CSMA/CD协议CSMA:载波监听 多点接入CD:碰撞检测六、最短帧长的计算争用期:长度/信号传播速率最短帧长=争用期内可发送的比特数七、以太网（标准局网）的最短帧长（以太网的MTU 1500字节）64字节八、 MAC帧格式（首部长度）九.以太网标准10BaseT的含义在双绞线上传输速率为10mb/s的以太网十.扩展的以太网集线器、网桥、交换机工作的层次集线器:物理层 一个端口对多个端口网桥：数据链路层 一个端口对一个端口交换机：数据链路层 多个端口 = 多接口网桥使用交换机和集线器的以太网每个用户的平均带宽交换机：不损失带宽，例如3个100M用户连入交换机，总带宽为300M集线器：取决于集线器自身的属性，若为10M集线器，假如是1G的带宽用集线器连入三台用户，三个用户的带宽也只有10M，而且集线器同一时间只能有一个用户发送数据网桥（交换机）转发分组时使用的地址（硬件地址/物理地址/mac地址）mac地址交换机自学习算法第四章 网络层一.网络层的主要协议IP协议与IP协议配套使用实现其功能的还有地址解析协议ARP逆地址解析协议RARP因特网报文协议ICMP因特网组管理协议IGMP二.网络层提供的两种服务及其特点可靠的面向连接的网络服务不可靠的无连接的网络服务三.网络互联的设备（路由器），路由器的任务（转发收到的分组）路由器转发收到的分组四.IP地址五.ARP协议全称：地址解析协议将IP地址映射成MAC地址原理流程：五.IP数据报的格式TTL:该字段指定IP包被路由器丢弃之前允许通过的最大网段数量片偏移：用该分片数据在原始数据的位置/8 （不包括首部的20）六.子网划分、子网掩码子网划分时至少留两位当主机位，因为只有1位时只有0和1七.无分类编址CIDR的编址方案/后面的数代表前多少位相同构造超网，也称为路由聚合。为什么要进行路由聚合：因为如果不聚合的话，路由转发表将会很大，例如下图，将会在路由转发表上增加5条记录，而聚合后就只增加一个了。八.RIP路由选择距离向量算法
第一章 绪论数据结构定义、数据逻辑结构的分类、两类物理存储方式及特点、时间复杂度的计算。1.数据结构定义数据结构(Data structure)： 相互之间存在一种或多种特定关系的数据元素的集合。程序=算法+数据结构2.数据逻辑结构的分类集合：结构中的数据元素除了同属于一种类型外，别无其它关系。线性结构：结构中的数据元素之间存在一对一的关系树型结构：结构中的数据元素之间存在一对多的关系。图状结构或网状结构：结构中的数据元素之间存在多对多的关系。3.两类物理存储方式及特点顺序存储结构（顺序映像）：逻辑相邻的元素物理存储位置相邻；链式存储结构（非顺序映像）：逻辑相邻的元素物理存储位置无关。4.时间复杂度的计算时间度量方法：语句执行的频度（次数）是问题规模的函数补充：第二章 线性表线性表的定义、非空循环单链表的特点；顺序表中插入、删除操作移动元素的个数；单链表的插入与删除操作时间复杂度计算，双向循环链表插入结点操作。1.线性表的定义定义： 0个或多个数据元素组成的有限序列。L=（a1,..., ai-1, ai, ai+1, ..., an）2.顺序表中插入、删除操作移动元素的个数插入移动元素：n-i+1个元素的后移删除移动元素：n-i 个元素的前移补充：删除元素的算法 算法时间主要耗费在移动元素的操作上假设删除元素的位置是随机等概率的，即概率为 1/n，则平均移动次数（期望值）为：(n-1)/23.非空循环单链表的特点从任意结点开始，可以找到表中其他结点。4.单链表的插入与删除操作时间复杂度计算均不需移动元素，时间复杂度为O(1)5.双向循环链表插入结点操作第三章 栈和队列栈和队列的逻辑特性，顺序栈的出栈、入栈，栈的常见应用，循环顺序队列出队和入队操作时队首队尾指针变化，循环顺序队列如何判队空、判队满、求队中元素个数。1.栈和队列的逻辑特性栈(stack)：只允许在序列一端进行操作的线性结构类型栈的操作特点：后进先出队列(queue)：只允许在序列两端进行操作的线性结构类型队列的特点：先进先出栈和队列统称为“操作受限”的线性结构2.顺序栈的出栈、入栈补充：InitStack：初始化空栈Push：进栈／入栈Pop：出栈／弹栈GetTop：读栈顶元素StackEmpty ：判断栈是否为空StackLength：返回栈的长度3.栈的常见应用4.循环顺序队列出队和入队操作时队首队尾指针变化//循环队列入队： int EnQueue(SqQueue &sq,int x)//入队 { if((sq.rear+1)%MaxSize==sq.front)//判断队满 { return 0; } sq.rear = (sq.rear+1)%MaxSize;//就相当于往上偏离了一个位置满了就会到初始的位置，因为模除循环 sq.data[sq.rear] = x;//把值写入 return 1; }//循环队列出队： int DeQueue(SqQueue &sq,int *x) { if(sq.rear==sq.front){//判断队空 return 0; } sq.front = (sq.front+1)%MaxSize;//就相当于往下偏离了一个位置满了就会到初始的位置因为模除 *x =sq.data[sq.front]; return 1; }5.循环顺序队列如何判队空、判队满font：队头rear：队尾Q.rear == Q.front 认为队空(Q.rear+1)% Q.maxSize == Q.front 则认为队满 //因为是循环队列6.求队中元素个数if(Q.rear>Q.front) length = Q.rear – Q.front; else//如果rear大于maxsize即到了新的循环 length = Q.maxSize + Q.rear – Q.front;第四章 串串的定义，空串和空格串的区别，了解串的模式识别算法。1.串的定义串是由零个或多个字符组成的有限序列，一般记为 s=‘a1a2…an’ (n≥0)相关概念：串的长度：串中字符的个数；空串：长度为0的串；空格串：由若干空格组成的串；子串：串中任意个连续的字符组成的子序列称为该串的子串，该串称为子串的主串；位置：字符在序列中的序号称为该字符在串中的位置。2.空串和空格串的区别空串：长度为0的串；空格串：由若干空格组成的串；3.了解串的模式识别算法BF算法（又称古典的、经典的、朴素的、穷举的）KMP算法（特点：速度快）BF算法若n为主串长度，m为子串长度，最坏情况下的比较次数：(n-m+1)*m若m<<n，则算法复杂度O(n*m)int Index(Sstring S,Sstring T,int pos){ i=pos; j=1; while (i<=S[ 0 ] && j <=T[ 0 ]){ //s0t0表示的应该是字符串的长度 if ( S[ i ]==T[ j ]) {++i; ++j;} else //检测到不同的字符就退回 {i=i-j+2; j=1;} } if ( j>T[ 0 ]) return i－T[0]; else return 0; }第五章 数组和广义表数组和广义表的定义，二维数组按行（列）优先地址的计算；上三角矩阵按列（行）优先存放地址的计算；广义表的定义及求表头、表尾操作。1.数组和广义表的定义数组：编程语言中的数组是一组同型数据的顺序存储结构；数据结构中的数组是一个逻辑概念；一维数组：同型元素为数据元素的线性表；多维数组：同型线性表为数据元素的线性表。广义表：广义表（列表）： n (>=0)个表元素组成的有限序列，记作LS = (a1, a2, …, an)ai的两种形态：广义表(子表)、数据元素(原子)。2.二维数组按行（列）优先地址的计算以行序为主序：LOC(i,j)=LOC(0,0)+(n*i+j)*L 0<=i<=m-1, 0<=j<=n-1以列序为主序：LOC(i,j)=LOC(0,0)+(j*m+i)*L 0<=i<=m-1, 0<=j<=n-1;3.上三角矩阵按列（行）优先存放地址的计算4.广义表的定义及求表头，表尾操作广义表（列表）： n ( >= 0 )个表元素组成的有限序列， 记作LS = (a1, a2, …, an)ai的两种形态：广义表(子表)、数据元素(原子)。广义表表头是元素或广义表，不用加括号广义表表尾只能是广义表，必须加括号第六章 树和二叉树树和二叉树的定义、结点的度、树的度、树的高度（深度）、完全二叉树、满二叉树的概念；二叉树的五个性质；二叉树的先序、中序、后序遍历，普通树结点个数、度、和分支数的关系；树和二叉树、森林和二叉树之间的转换及其遍历方法的对应关系；二叉链表存储线索二叉树的空指针个数，线索二叉树中序遍历方法，Huffman树的特点、构造方法、利用Huffman树求Huffman编码的方法。1.树和二叉树树：一对多的关系，顶层只有一个元素，各分支不相交二叉树：二叉树是n（n≥0）个结点（元素和向下的分支）构成的集合，它或为空树（n = 0），或为非空树T：（1）有且仅有一个根（root）结点/顶层结点（2）其余结点被划分为最多两个互不相交的子集L和R（3）L和R也是一棵二叉树，分别称为左子树和右子树；左右子树也可以是空树二叉树是有序树！结点度：结点拥有子结点的数量树的度：树的度指其中结点的度最大值。结点的层次: 从根结点开始定义，根为第1层，根的孩子为第2层，如此计数，直到该结点为止。树的高度（深度）：树中结点的最大层次完全二叉树：每个结点的编号和满二叉树中编号为 1 至 n 的结点一一对应，称该树为完全二叉树。完全二叉树叶子节点的个数：n0 = ⌊（n+1）/2⌋ （向下取整）满二叉树：每层都“充满”了结点2.二叉树的五个性质1）在二叉树的第i层上至多有2i-1个结点(i>=1)2）深度为k的二叉树至多有2k-1个结点。3）对于任意一棵二叉树，如果度为0的结点个数为n0，度为2的结点个数为n2，则n0 = n2+14）具有n个结点的完全二叉树的深度为└log2n┘+1（向下取整）5）对于含n个结点的完全二叉树中编号为i（1≤i≤n）的结点：（1） 对于i>1的每个结点，其双亲的编号为 i/2 ；（2）对于2i<=n的每个结点，其左孩子的编号为2i，否则没有左孩子；（3）对于2i+1<=n的每个结点，其右孩子的编号为2i+1，否则没有右孩子。3.二叉树的先序、中序、后序遍历先序遍历(DLR)：先访问根结点，再先序遍历左子树，最后先序遍历右子树中序遍历(LDR)：先中序遍历左子树，再访问根结点，最后中序遍历右子树后序遍历(LRD)：先后序遍历左子树，再后序遍历右子树，最后访问根结点4.普通树结点个数、度、和分支数的关系树的总分叉数=结点总度数结点数=分叉数+1叶子数为结点度数为0的结点（没有子结点）1.设树T的度为4，其中度为1，2，3，4的节点个数分别为4，2，1，1，则T中的叶子数为？解：叶子的度数为0；那么设叶子数为x，则此树的总分叉数为1x4+2x2+3x1+4x1=15；此树的节点个数为16(此处涉及到一个公式;节点数=分叉数+1，由图形便可以观察出来)。又根据题目可以知道顶点数目还可以列出一个式子：4+2+1+1+x便可以得到等式：4+2+1+1+x=16；x=8为叶子数。5.树和二叉树、森林和二叉树之间的转换及其遍历方法的对应关系树与二叉树间的转换：第一个孩子作为左孩子，第一个右兄弟作为右孩子。森林与二叉树的转换：每棵树的树根当作兄弟，第一棵树的根作为转换二叉树的根第一个孩子作为左孩子，第一个右兄弟作为右孩子。树的遍历：先根遍历：根、（先根遍历）每棵子树后根遍历：（后根遍历）每棵子树、根将树转化为二叉树后：树的先根遍历可借用二叉树的先序遍历算法实现;树的后根遍历可借用二叉树的中序遍历算法实现。森林的遍历森林的先序遍历即为其对应的二叉树的先序遍历森林的中序遍历即为其对应的二叉树的中序遍历6.二叉链表存储线索二叉树的空指针个数二叉树所有空指针的个数为n+1是众所周知的事(n为二叉树结点个数)7.线索二叉树中序遍历方法中序线索化思路1、先线索化左子树2、找到线索化的起始点—当前节点的左节点为空 node.getLeft() == null3、然后把当前节点右指针指向前驱结点4、在处理后继结点，并把前驱结点的右指针设置为当前节点5、最后把当前节点设置为前驱结点6、线索化右子树中序线索化遍历思路1、 先找到线索化的起始点2、输出当前节点信息3、然后寻找当前结点的后继结点，并输出8.Huffman树的特点、构造方法、利用Huffman树求Huffman编码的方法特点：具有n个叶子结点的二叉树中，带权路径长度最小的二叉树，也称为最优二叉树。Huffman树特点：没有单分支结点总结点数=2xn-1根权值=叶子权值和构造赫夫曼树：①两棵树合并时，总是合并森林中根结点权值最小的两棵；②每构造一次，F中少一棵树；③n个权值经过n-1次构造完成。综合规则1和规则2，以报文中n个字符作为叶子结点构造赫夫曼树后进行编码，得到的编码称为赫夫曼编码（最优前缀编码）。编码过程：（1）构造赫夫曼树；（2）为赫夫曼树中的每个分支进行编码，左分支为“0”，右分支为“1”，（3）从根出发，到达每个叶子结点所经过的路径上的编码组合，作为该叶子结点的编码序列。第七章 图图的定义、结点度的计算。无向图的连通分量的概念，图的深度和广度优先遍历方法；图(或网)的存储（邻接表、邻接矩阵）方法及特点；最小生成树的概念及求法，拓扑排序和关键路径求法。1.图的定义、结点度的计算图：Graph=(V,E)V：顶点(数据元素)的有穷非空集合；E：边（关系）的有穷集合。图中任意两个顶点间都可能有关系，是一个多对多的结构。2.无向图的连通分量的概念首先要清楚什么是无向图，在图的结构中每两个点之间最多只有一条线，这条线即代表了由a指向b，也代表了由b指向a，连通分量的概念：在上图中连通分量就是4.所以说连通分量就是在图中非连通子图的数量。连通图的连通分量只有1个n个顶点的无向图连通分量最多n个，最少1个3.图的深度和广度优先遍历方法https://www.cnblogs.com/nr-zhang/p/11236369.html深度遍历：一条路走到头，再回退的过程中遇到分叉再走进去广度遍历：先找出所有跟开始节点间隔0层的结点，再找出所有跟开始结点间隔一层的结点....空间复杂度相同，都是O(n)(借用了堆栈或队列）时间复杂度只与存储结构（邻接矩阵或邻接表）有关，而与搜索路径无关。4.图(或网)的存储（邻接表、邻接矩阵）方法及特点邻接表存储法：使用一维数组存储顶点信息；对每个顶点vi 建立一个单链表，把与vi相关联的边链接起来；将单链表的头指针与对应的顶点vi一起存储。包含e条边的无向图的邻接表中有 2e个边结点。包含e条边的有向图的邻接表中有 e 个边结点数组表示法（邻接矩阵表示法）:一维数组存储顶点信息、 二维数组存储边/弧的信息第i个顶点的出度=第i行元素之和第i个顶点的入度=第i列元素之和第i个顶点的度=出度 + 入度无向图的邻接矩阵是对称的；顶点i 的度＝第 i 行（或第i列）元素之和完全图的邻接矩阵：对角元素为0，其余15.最小生成树的概念及求法生成树：一次遍历过程中访问的顶点和访问时经过的边构成的集合普里姆(Prim)算法Prim算法的时间复杂度为O(n^2)，与图中的边数无关，故十分适合于稠密图克鲁斯卡尔(Kruskal)算法1)首先将边按照权重由小到大排序，记录边两侧的节点信息2)再从上到下依次将边回填入图中3)每进行一次回填，就检测图中是否有成环部分，若有则跳过这条边4)当图中边的总个数等于总结点个数-1时，完成最小二叉树的构建T(n) = O(nlog2n),适用于边少的稀疏图6.拓扑排序和关键路径求法拓扑排序：在AOV网络中选一个没有直接前驱（入度为0）的顶点, 并输出之;从图中删去该顶点, 同时删去由它出发的所有弧;重复以上两步, 直到：全部顶点均输出[scode type="red"]注意：排序结束后若还有未输出的顶点：拓扑排序失败拓扑排序失败的AOV网络中必定存在回路/环。[/scode]关键路径：https://www.bilibili.com/video/BV1kK4y1W7Zu源点：开头的点汇点：结尾的点关键路径可能不止有一条第九章 查找顺序表查找的平均查找长度，二分（折半）查找的过程及查找失败时的比较次数，动态查找和静态查找的概念，二叉排序树的平均查找长度、平衡二叉树的定义及构造，哈希表的构造（除留余数法）、解决冲突的方法（线性探测再散列法、二次探测再散列法），哈希查找的查找成功时平均查找长度(ASL)的计算。1.顺序表查找的平均查找长度ASLs(n)=(1+2+ ... +n)/n =(n+1)/2查找不成功时的平均查找长度：ASLf =n+1平均查找长度为：2.二分（折半）查找的过程及查找失败时的比较次数设表长为n，low、high和mid分别指向待查元素所在区间的上界、下界和中点,k为待查找值初始时，令low=1,high=n计算mid=|(low+high)/2|向下取整让k与mid指向的记录比较若k==R[mid].key，查找成功若k<R[mid].key，则high=mid-1若k>R[mid].key，则low=mid+1重复1、2步,直到low>high，查找失败查找成功的情况下最多比较几次？h = |log2 n | + 1查找成功时的平均查找长度：查找失败时的比较次数：|log2n|+13.动态查找和静态查找的概念静态查找就是我们平时概念中的查找，是“真正的查找”。之所以说静态查找是真正的查找，因为在静态查找过程中仅仅是执行“查找”的操作，即：（1）查看某特定的关键字是否在表中（判断性查找）；（2）检索某特定关键字数据元素的各种属性（检索性查找）。这两种操作都只是获取已经存在的一个表中的数据信息，不对表的数据元素和结构进行任何改变，这就是所谓的静态查找。动态查找看到上面静态查找的概念，动态查找就很好理解了，个人总觉得动态查找不像是“查找”，更像是一个对表进行“创建、扩充、修改、删除”的过程。动态查找的过程中对表的操作会多两个动作：（1）首先也有一个“判断性查找”的过程，如果某特定的关键字在表中不存在，则按照一定的规则将其插入表中；（2）如果已经存在，则可以对其执行删除操作。动态查找的过程虽然只是多了“插入”和“删除”的操作，但是在对具体的表执行这两种操作时，往往并不是那么简单。4.二叉排序树的平均查找长度平均查找长度和二叉排序树的形态有关：最好：log2(n+1)（形态匀称，与二分查找的判定树相似）最坏: （n+1)/2（单支树）5.平衡二叉树的定义及构造建立形态均匀的二叉排序树：让二叉排序树左右子树差不多高结点的平衡因子：左、右子树高度差；平衡二叉树：所有结点的平衡因子绝对值≤1的二叉排序树，即二叉排序树中每个结点的平衡因子只可能为：-1、0、1。按照二叉排序树的规则进行结点的插入，新插入的结点平衡因子为0；每插入一个结点后，从插入位置开始往上，重新计算其祖先的平衡因子；当某个结点“失衡”后，根据旋转法则进行调整。**LL平衡旋转RR平衡旋转LR平衡旋转RL平衡旋转**6.哈希表的构造（除留余数法）H(key) = key % p ， (p≤m)m：映射地址区间长度——哈希表长%: 求余操作 p：不大于m的整数，p一般取接近m的质数或不包含小于20的质因子的合数7.解决冲突的方法（线性探测再散列法、二次探测再散列法）8.哈希查找的查找成功时平均查找长度(ASL)的计算平均查找长度ASL取决于： 哈希函数 处理冲突的方法 哈希表的装填因子第十章 排序排序的分类，冒泡排序、直接插入排序、堆排序、希尔排序、简单选择排序、快速排序的排序过程；堆排序的适用情况；各类排序算法的稳定性及时间和空间复杂度。https://blog.csdn.net/weixin_60954394/article/details/1214319221.排序的分类插入排序交换排序选择排序归并排序基数排序2.冒泡排序基本思想从待排序列的首元素开始，从前往后依次进行比较，若大于则交换，将其继续与后面元素比较，直到被放至正确位置。否则迭代至与其比较的元素，重复上面的步骤。动图演示代码实现void Swap(int* px, int* py) { int tmp = *px; *px = *py; *py = tmp; } void BubbleSort(int* a, int n) { for (int j = 0; j < n; j++) { for (int i = 0; i < n - j - 1; i++) { if (a[i] > a[i + 1]) { Swap(&a[i], &a[i + 1]); } } }3.直接插入排序基本思想每次从一个有序序列开始，将待排元素与有序序列中的元素从后往前逐个比较，若有序序列中的元素大于待排元素，则将较大的元素往后覆盖；否则，将待排元素插入其前面，并结束此轮比较。动图演示代码实现void InsertSort(int* a, int n) { for (int i = 0; i < n - 1; i++) { int end = i; int x = a[end + 1]; while (end >= 0) { if (a[end] > x) { a[end + 1] = a[end]; end--; } else break; } a[end + 1] = x; } }4.堆排序利用堆完成排序的时间复杂度：T(n) = O(nlog2n)从第n/2个元素起，至第一个元素止，进行反复筛选1.建大顶堆结束后，将堆顶元素与堆中最后一个元素互换；2.“删除最后一个元素”后，对新的根结点进行筛选，得到新的堆，新堆的堆顶即为次大值；3.重复上面的两步，直到排序完成。5.希尔排序基本思想先选定一个整数作为 gap ,将待排序列以 gap 为间隔分成 gap 组，先对每组进行直接插入排序，然后再适当缩小 gap ,重复上述步骤。当 gap = 1 时，此时序列已经进行了多次预排序，接近有序。这时再对序列进行直接插入排序，就能达到优化的效果。图示void ShellSort(int* a, int n) { //多次预排序(gap > 1) + 直接插入( gap == 1) int gap = n; while (gap > 1) { //使gap最后一次一定能到1 gap = gap / 3 + 1; //多组一起排 for (int i = 0; i < n - gap; ++i) { int end = i; int x = a[end + gap]; while (end >= 0) { if (a[end] > x) { a[end + gap] = a[end]; end -= gap; } else break; } a[end + gap] = x; } } }6.简单选择排序基本思想每一次从待排序的数据元素中选出最小(或最大)的一个元素，存放在序列的起始(末尾)位置，直到全部待排序的数据元素排完 。动图演示以每次选出最小值为例void Swap(int* px, int* py) { int tmp = *px; *px = *py; *py = tmp; } void SelectSort(int* a, int n) { int begin = 0; while (begin < n - 1) { int mini = begin; for (int i = begin; i < n; i++) { if (a[i] < a[mini]) mini = i; } Swap(&a[begin], &a[mini]); ++begin; } }7.快速排序任取待排序元素序列中的某元素作为基准值，按照该排序码将待排序集合分割成两子序列，左子序列中所有元素均小于基准值，右子序列中所有元素均大于基准值，然后最左右子序列重复该过程，直到所有元素都排列在相应位置上为止。void QuickSort(int* a, int left, int right) { if (left >= right) return; //先将选定的基准值排好 int keyi = Partion(a, left, right); //再通过递归排序其左右子序列 QuickSort(a, left, keyi - 1); QuickSort(a, keyi + 1, right); }Partion函数分析Partion函数在这里的作用是：将选定的基准值排到正确位置，并将待排序列分成比基准值小的左子序列，比基准值大的右子序列。将区间按照基准值划分为左右两半部分的常见方式有：基本思想：选择待排序列的最左值的下标为基准值所指下标，当区间左下标小于区间右下标时，先从右开始找比基准值小的值，找到后再从左开始找比基准值大的值，都找到后，将左右下标对应的值交换，然后从右开始重复上述步骤，直到左右下标相等。当左右下标相等时，将下标所指向的值与基准值互换。动图演示：int Partion(int* a, int left, int right) { int keyi = left; while (left < right) { //右边先走，找小 while (left < right && a[right] >= a[keyi]) { --right; } //左边走，找大 while (left < right && a[left] <= a[keyi]) { ++left; } Swap(&a[left], &a[right]); } Swap(&a[keyi], &a[left]); return left; }8.各类排序算法的稳定性及时间和空间复杂度
第一二章作业1.信息安全的四个目标是什么1）机密性2）完整性 3）认证性 4）不可否认性2.密码学的定义是什么密码学是一门涉及数学,计算机信息科学的综合学科，是编码学和密码分析学的统称。3.密码体制由哪五部分组成？安全性通常由哪部分决定？明文.密文.加密算法.解密算法.密钥 五部分组成安全性通常由密钥决定。4.根据密钥的使用情况的不同，密码体制通常分为哪两类？对称密码体制和非对称密码体制第三章作业[scode type="red"]注意：本章字母转换为数字是从0开始的，即A对应0，B对应1,...依次类推**[/scode]即 字母转数字时：先转数字，再按通常情况下的数字转化-1数字转字母时：先按通常情况下数字+1，再转字母题目：1.希尔（Hill）密码加密密钥为一个nxn的非奇异矩阵，解密密钥为这个矩阵的逆矩阵。逆矩阵的求法： 先求矩阵A的伴随矩阵注意：伴随矩阵是(-1)^(i+j)x代数余子式,最后再对这个矩阵求转置再用伴随矩阵除以|A|得到逆矩阵注意：因为后面有mod26 所以任意除法都可以看做分子分母同时乘分母的逆元（mod26），这样就可以把除法化成乘法。加密就是用英文字母转化为对应数字然后乘以矩阵即可2.早期密码学主要是通过字符的哪两种操作实现的？换位 和 代换3.周期置换密码加密密钥为（1 5 6 2 3） 解密密钥则为（3 2 6 5 1）具体解释为原字符串第一个字母放在第五个位置原字符串第五个位置放在第六个位置...原字符串第三个位置放在第一个位置4.移位密码加密密钥为k=x即将原字符串字母转化为数字之后，再加上密钥k 模 26 得到的数字转化为字母即为加密后的密文5.仿射密码加密密钥为（p，q）加密方式为 字母转数字后得到xs=(x×p+q) mod 26解密密钥为 （y，q）y=3 mod 26的逆元解密时就用 （s-q）×y mod26即为解密密文6.维吉尼亚密码加密密钥为一串数字先将字母转化为数字，再将其分组，分组长度为加密密钥数字的长度，再将其进行移位密码处理例如：明文ABC加密密钥XYZ密文(mod26)A+XB+YC+Z第四章作业分组密码是一类对称密码1.分组密码的设计要实现哪两个目标？扩散和混乱2.分组密码算法的非线性性质主要有哪部分实现？S盒。S盒是许多算法唯一的非线性部件，它的密码强度直接决定了整个算法的安全强度。S变换(代替)S盒起到混乱的作用，P盒起到扩散的作用3.雪崩效应雪崩效应指的是输入(明文或密钥)即使只有很小的变化，也会导致输出产生巨大的变化现象。4.DES的S3盒的输入是101101，求输出b1b2b3b4b5b6=101101行对应b1b6=11=3列对应b2b3b4b5=0110=4所以对应S3盒的3行6列注意:S盒的行和列都是从0开始计数的。5.DES面临哪些攻击穷搜索攻击 线性分析 差分分析 6.DES和AES的分组长度是多少？有效密钥长度呢？DES的分组长度：64位 密钥长度：56位AES的分组长度：128比特 密钥长度：可为128,192,256比特7.除了子密钥异或，DES的一轮迭代还包含哪三种操作？选择拓展运算和选择压缩运算8.写出DES一轮迭代的算法表达式，并画出一轮迭代的框图。9.画出AES的加密算法框图10.AES一轮迭代主要包含哪四种操作？轮密钥加 字节代换 行位移 列混淆11.DES是面向比特的操作，那AES呢？AES是面向字节的操作第五章作业1.反馈移位寄存器主要包括哪两个部分？是由 n位的寄存器 和 反馈函数 组成的2.序列密码（流密码）的安全强度主要取决于什么密钥流的随机性3.4.n级线性反馈移位寄存器寄存器能够生成的序列最大周期是多少2^n -15.用BM算法破译n级线性反馈移位寄存器，需要已知多长的密钥流？2n第六章作业1.哈希函数是用来做什么的？哈希函数的这种单向特征和输出数据的长度固定的特征使得它可以生成消息或其他数据块的“数据指纹”，因此在数据完整性认证和数字签名等领域有广泛的应用，在现代密码学中起着重要作用。**2.什么是哈希函数的单向性？单向性指的是从一个明文到密文的不可逆映射，即只有加密过程，不能解密。3.什么叫哈希函数的抗弱碰撞性和抗强碰撞性？抗弱碰撞性：对于给定的消息M1，要发现另一个消息M2，满足H（M1）=H（M2）在计算上是不可行的。**抗强碰撞性：找任意一对不同的消息M1,M2,使H（M1）=H（M2），在计算上是不可行的。**4.MD5和SHA1分别产生多长的哈希值？MD5:128比特SHA1:160比特5.MD5和SHA1将消息分成多长的消息分组？512位6.生日悖论和集合相交问题是用来攻击什么的？哈希函数第七章作业1.什么叫做陷门单向函数？2.RSA算法、EIGamal算法和ECC算法的安全性分别依赖于什么数学困难问题?目前安全的密钥长度至少是多少比特?RSA算法：大整数因子分解的困难性。ElGamal算法:求解有限域上的离散对数问题的困难性ECC算法：基于椭圆曲线上的离散对数问题的难解性。目前的安全密钥至少为256位3.RSA算法和ElGamalRSA算法：1）参数：选定两个大素数p，qn＝pxqf(n)=(p-1)(q-1)随机选一个数字e，满足e和f(n)互素计算d=emodf(n)的逆元则公钥为(e,n) 私钥为d 可以销毁p,q2)加解密：要加密消息m，则计算c=m^e mod n若要解密消息c，则计算m=c^dmod nElGamal算法：1)参数：选定一个大素数pg为Zp的生成元随机选一个数x 小于p计算y=g^x mod p则公钥为（p，y，g），密钥为x2)加解密：首先选择一个数k 令k小于p-1c1=g^k mod pc2=m×y^k mod p则密文为(c1,c2)解密时用私钥计算m=c2(c1^x)^-1 modp4.数域筛法和指数积分法分别是用来攻击什么的?RSA 和 ElGamal5.相对于对称密码,非对称密码的优缺点?**优点:**密钥分发简单需秘密保存的密钥量减少可以满足互不认识的人之间的私人谈话的保密性的要求可以实现数字签名和认证**缺点:**公钥密码算法比对称密码算法慢公钥密码算法提供更多的信息对算法进行攻击有数据拓展公钥密码算法一般建立在对一个特定的数学难题的求解上,这种困难往往只是一种设想第八章作业1.数字签名的用途数字签名是利用数学方法和密码算法对该电子文档进行关键信息提取并进行加密而形成的.2.数字签名与手写签名的不用之处3.一个普通的数字签名方案由哪五部分构成**P.S,K,Sig,Ver**P:明文空间 S:签名空间 K:密钥空间 Sig:签名算法 Ver:验证算法4.数字签名方案应用哈希函数的优点是什么可以增强安全性RSA 签名方案和 ElGamal签名方案第九章作业1.一个三层的密钥层次结构里密钥分为哪三层?1)会话密钥2)密钥加密密钥3)主密钥shamir门限
一.事件概率事件，必然事件，不可能事件帽子分开戴，中间符号反过来概率的概念与性质P(A∪B∪C)=P(A)+P(B)+P(C)-P(AB)-P(AC)-P(BC)+P(ABC)二.古典概型古典概型也叫等可能概型 用样本数估计概率抽签原理 不放回摸出特定奖的概率不变三.条件概率乘法公式：对条件概率公式进行的变化，用来求P(AB)四.全概率公式与贝叶斯公式考试经常会出两个Bi仅有B和非B的简化版，如下计算题第一题 10分第一步 把事件假设出来第二步 根据已知概率把假设的时间概率表示出来第三步 用全概率公式计算某一个事件的概率**第四步 用计算过的概率计算贝叶斯公式（当分母）**五.事件的独立性概率为0的事件未必是不可能事件六.离散型随机变量及其分布分布律x有n个取值，则分布函数后面就有n+1行等号都在大于等于上面，第一条一定是0 最后一条一定是1七.常见的离散型随机变量二项分布，泊松分布八.连续型随机变量及其分布连续型随机变量单点概率为0：因为某一段上有无穷多个点概率等于零的点未必为不可能事件 知道 分布函数F(x) 求 概率密度函数f(x) -> 求导知道 概率密度函数f(x) 求 分布函数F(X) -> 求积分知道x的分布函数与概率密度函数 求 y 的概率密度函数1）确定y的取值2）确定y的分布函数3）求概率密度函数九.常见的连续随机变量十.二维离散型随机变量十一.二维连续型随机变量十二.二维随机变量函数的分布把x或者y用z和另一个变量替代再求积分这时候要注意可能会出现积分线的不同，要分段求x当纵坐标 z当横坐标十三.期望与方差数学期望：数学期望主要是描述数据大概分布的一个值，一个期望值方差：描述样本和期望值的离散程度，一般方差越小说明预测效果越准确数学期望数学期望的性质2,3,4条经常考到方差和标准差平方的期望-期望的平方方差的性质 常见的期望和方差正态分布：已知X，要求Y，只要算出Y的期望和方差，就能写出Y的正态分布函数正态函数加减乘除一个常数依旧是正态分布对谁求积分 就在哪条轴上划线对x 求积分dx 即找出x的取值范围为0到y十四.协方差与相关系数 如果X跟Y不相关，那么协方差等于0 Cov(X,Y)=0相关系数描述了两个随机变量X,Y之间的依赖关系如果越接近1说明越为正相关，越接近-1说明越为负相关 0说明无关已知X,Y的方差，和二者的相关系数，可以求出x和y的协方差十五.中心极限定理一些随机变量的加和概率 并且 发现这些随机实验独立同分布->要运用中心极限定理计算十六.抽样分布常用统计量：g（x1,x2,x3,...,xn）这种不含位置参数的变量叫做常用统计量常用分布十七.矩估计1.计算出一个总体均值的表达式2.令总体均值等于样本均值，反解出未知参数关于样本均值的函数3.求出样本均值，带入求估计值十八.最大似然估计（离散型）十九.最大似然估计（连续型）二十.无偏估计
近期参加了一个项目，主要是负责数据部分，现在这个时候也没我什么事情了，写一下项目中用到的爬虫总结。0.总结1)pymysql连接数据库 config = { "host": "xxx.com", "port": 0, "user": "xxx", "password": "xxx", "database": "xxx" } db = pymysql.connect(**config) cursor = db.cursor() #获取游标 sql = "xxx" #要执行的sql语句 cursor.execute(sql) #执行sql db.commit() # 提交数据 cursor.close() db.close()#关闭游标和数据库单次执行一条sql语句效率不如批量执行多条，也就是db.commit()可以在for循环最后执行。使用数据库后应关闭游标和数据库2）request.get()在长时间运行后报错可以运用get中的参数timeout= 和try来进行再次尝试，一般一到两次即可成功,网上查阅了很多资料，目前只有这一种管用。 i = 0 while i < 5: try: raw = requests.get(link, headers=header, proxies=proxies, timeout=2).text break except requests.exceptions.RequestException: i = i + 1 print('请求超时,正在重试...2')3）代理ip爬酷推时遇到了限制ip访问的情况，可以选用代理ip。https://www.xiaoxiangdaili.com/** 短效ip 一块钱一天，还挺合算 def changeip(): ip = requests.get('xxx').text while ip=='{"code":1010,"success":false,"data":null,"msg":"请求过于频繁"}': time.sleep(5) ip = requests.get('xxx').text print("更换ip成功" + ip) proxies = { 'http': ip, 'https': ip } return proxies在request.get()函数中只需要带上proxies=proxies即可raw = requests.get(link, headers=header, proxies=proxies, timeout=2)4）保存数据到数据库时遇到的代码报错原因是数据库用的字符格式是utf8,而emoji表情大多需要utf8mb4格式，其中包括utf8，遇到该类错误首先更改数据库字符格式，其次将emoji替换，可以用正则也可以用emoji包，最后再无法解决可以用replace替换附上从网上找到的正则替换代码 def filter_emoji(desstr, restr=''): # 过滤表情 try: co = re.compile(u'[\U00010000-\U0010ffff]') except re.error: co = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]') return co.sub(restr, desstr)5）beautifulsouprequest到的数据先用bs4解析 soup = BeautifulSoup(raw, "html.parser")soup.select真是个好东西，下面是他的选择方法6）正则主要是用到re.compile()和re.findall()以及re.sub()re.compile()：定义正则规则re.findall()：查找 参数为正则规则，数据，返回值为列表re.sub()：替换 参数为正则规则，要替换成的数据，数据1.简书简书的爬虫是我这三个爬虫中最好写的一个，没有任何反爬，用F12确定元素定位后，可以用正则，可以用bs4解析即可获得内容。不过写简书的翻页请求数据开始花了点功夫，请求的页数数据要写在post请求数据包里，用一个for循环即可解决，还有一个难点就是一开始数据出现大量重复，查阅资料后发现需要在request请求头里更新cookie数据，否则数据会出现重复，降低效率。ajax异步加载需要用F12抓包获取请求地址数据整理替换去重时使用正则替换re.sub()和text.replace() # -*- codeing = utf-8 -*- # @Time : 2021/8/3 16:17 # @Author : yunqi # @Fire : jianshu.py # @Software : PyCharm import os import requests from bs4 import BeautifulSoup import re import time import xlwt import pymysql global header,config,cookie header = { 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36', 'X-PJAX': 'true' # 'sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217b3466849938b-08f7999168164d-4343363-2073600-17b3466849ace1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%7D%7D; sajssdk_2015_cross_new_user=1; Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1628420549,1628422073,1628423751,1628671739; locale=zh-CN; _ga=GA1.2.1168608088.1628671739; _gid=GA1.2.896180568.1628671739; UM_distinctid=17b346685e9346-0002a4ae6d88e7-4343363-1fa400-17b346685eae44; _m7e_session_core=f67ec2211a28225502a4d2b81632bcc0; signin_redirect=https%3A%2F%2Fwww.jianshu.com%2F; read_mode=day; default_font=font2; Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1628682890; CNZZDATA1279807957=288995723-1628668245-%7C1628679045; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217b3466849938b-08f7999168164d-4343363-2073600-17b3466849ace1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%2217b3510ac62318-05af7b13d1ca09-4343363-2073600-17b3510ac636e3%22%7D' } config = { } global workbook, worksheet global id, postdata postdata='' def main(): global cookie,header response = requests.get("https://www.jianshu.com/", headers=header) cookie = requests.utils.dict_from_cookiejar(response.cookies) global workbook, worksheet, id #startexcel() id=0 #=====================正则==== auth=re.compile(r'(.*?)') textre=re.compile(r' ') img1=re.compile(r' \n \n \n \n \n .*? \n ') timere=re.compile(r'data":{"is_author":.*?,"last_updated_at":(.*?),"public_title"') passre=re.compile('<.*?>') #===================== for num in range(1,15): #简书首页最多获取15页内容 links,seenid,jianjies=GetUrl(num) for v,i in enumerate(links): global config db = pymysql.connect(**config) cursor = db.cursor() sql = "SELECT nid FROM article WHERE nid=" + seenid[v] # 查询文章绝对id是否存在 msg = cursor.execute(sql) cursor.close() db.close() if msg==1: print("该条数据已经存在") continue try: i = "https://www.jianshu.com" + i id += 1 raw = requests.get(i, headers=header).text #获取文章详情界面的内容 soup = BeautifulSoup(raw, "html.parser") title=soup.select('h1') #获取文章标题 auther=re.findall(auth,str(soup))[0] #获取作者 time1=int(re.findall(timere,str(soup))[0]) timeArray = time.localtime(time1) Time = time.strftime("%Y-%m-%d %H:%M:%S", timeArray) #从时间戳转换到发布日期 nid=seenid[v] jianjie=jianjies[v] except IndexError: print('获取数据失败 跳过 可能是文章正在审核') print(i) id-=1 continue #----------对内容进行简单的处理 text=str(soup.select('article')[0]) text=re.sub(textre,"",text) text=re.sub(img1,"[https:",text) text = re.sub(img2, "]", text) text=text.replace(" ","").replace(" ","\n").replace(" ","\n").replace(" ","\n").replace("","\n").replace("",'\n').replace(" ",'\n') #内容替换 text = re.sub(passre, " ", text) data=(title[0].text,auther,jianjie,text,Time,i,nid) #SaveDataxls(data) print(data) SaveMyql(data) os.system('python Article_Keywords.py') # 保存 #workbook.save('data.xls') #time.sleep(30) # 休息三十秒 def GetUrl(num): #从简书首页获取文章链接列表 #======================================正则 seenidre=re.compile(r' ') getlink=re.compile(r'.*?')#获取文章links的正则 jianjiere=re.compile(r' \n (.*?)\n ') #===================================== global header,cookie global postdata print("page=" + str(num) + postdata) raw = requests.post("https://www.jianshu.com/trending_notes",data="page="+str(num)+postdata,headers=header,cookies=cookie).text #对page进行更改可以获取不同页数 urls=re.findall(getlink,raw) seenid=re.findall(seenidre,raw) jianjie=re.findall(jianjiere,raw) for esid in seenid: postdata=postdata+'&seen_snote_ids%5B%5D='+str(esid) return (urls,seenid,jianjie) #返回七个文章链接 每次加载七个 def SaveMyql(data): global config db = pymysql.connect(**config) cursor = db.cursor() #获取游标 sql = "INSERT INTO article(title,author,summary,content,create_time,link,nid) VALUES"+str(data) cursor.execute(sql) db.commit() # 提交数据 print("success") cursor.close() db.close() def SaveDataxls(data): global workbook, worksheet dataid=int(data[0]) # 写入excel # 参数对应 行, 列, 值 worksheet.write(dataid, 0, str(dataid)) worksheet.write(dataid, 1, data[1]) worksheet.write(dataid, 2, data[2]) worksheet.write(dataid, 3, data[3]) worksheet.write(dataid, 4, data[4]) worksheet.write(dataid, 5, data[5]) worksheet.write(dataid, 6, data[6]) worksheet.write(dataid, 7, data[7]) def startexcel(): global workbook, worksheet # 创建一个workbook 设置编码 workbook = xlwt.Workbook(encoding='utf-8') # 创建一个worksheet worksheet = workbook.add_sheet('data') # 参数对应 行, 列, 值 初始化 worksheet.write(0, 0, "id") worksheet.write(0, 1, "title") worksheet.write(0, 2, "auther") worksheet.write(0, 3, "summary") worksheet.write(0, 4, "content") worksheet.write(0, 5, "update") worksheet.write(0, 6, "source") worksheet.write(0, 7, "nid") if __name__ == "__main__": main()2.少数派少数派这个网站还是项目里其他组员推荐的，于是就改了改简书的爬虫把它写下来了，基本大同小异，甚至比简书少了一步post时的数据校验。 # -*- codeing = utf-8 -*- # @Time : 2021/8/3 16:17 # @Author : yunqi # @Fire : ssp.py # @Software : PyCharm import os import requests from bs4 import BeautifulSoup import re import time import xlwt import pymysql import json global header,config,cookie header = { 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36', 'X-PJAX': 'true' # 'sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217b3466849938b-08f7999168164d-4343363-2073600-17b3466849ace1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%7D%7D; sajssdk_2015_cross_new_user=1; Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1628420549,1628422073,1628423751,1628671739; locale=zh-CN; _ga=GA1.2.1168608088.1628671739; _gid=GA1.2.896180568.1628671739; UM_distinctid=17b346685e9346-0002a4ae6d88e7-4343363-1fa400-17b346685eae44; _m7e_session_core=f67ec2211a28225502a4d2b81632bcc0; signin_redirect=https%3A%2F%2Fwww.jianshu.com%2F; read_mode=day; default_font=font2; Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1628682890; CNZZDATA1279807957=288995723-1628668245-%7C1628679045; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217b3466849938b-08f7999168164d-4343363-2073600-17b3466849ace1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%2217b3510ac62318-05af7b13d1ca09-4343363-2073600-17b3510ac636e3%22%7D' } global workbook, worksheet global id, postdata postdata='' def main(): global cookie,header response = requests.get("https://sspai.com/", headers=header) cookie = requests.utils.dict_from_cookiejar(response.cookies) global workbook, worksheet, id #startexcel() #=====================正则==== textre=re.compile(r' ') img1=re.compile(r'<img.*? data-original=".*?" src="') img2=re.compile(r'\?imageView.*?/>') passre=re.compile('<.*?>') #===================== for num in range(1,15): #首页最多获取15页内容 urls,jianjie,nid,title,author,creat_time=GetUrl(num) for v,i in enumerate(urls): global config db = pymysql.connect(**config) cursor = db.cursor() sql = "SELECT nid FROM article WHERE nid=" + str(nid[v]) # 查询文章绝对id是否存在 msg = cursor.execute(sql) cursor.close() db.close() if msg==1: print("该条数据已经存在------"+title[v]) continue try: raw = requests.get(i, headers=header).text #获取文章详情界面的内容 soup = BeautifulSoup(raw, "html.parser") # ----------对内容进行简单的处理 text = str(soup.select('.article-body')[0]) text = re.sub(textre, "", text) text = re.sub(img1, "\n[", text) text = re.sub(img2, "]", text) text = text.replace(" ", "").replace(" ", "\n").replace(" ", "\n").replace(" ","\n").replace("", "\n").replace("", '\n').replace(" ", '\n').replace("\"/>","") # 内容替换 text = re.sub(passre, " ", text) timeArray = time.localtime(creat_time[v]) Time = time.strftime("%Y-%m-%d %H:%M:%S", timeArray) data = (title[v], author[v], jianjie[v], text, Time, i, nid[v]) # SaveDataxls(data) print(data) SaveMyql(data) except IndexError: print('获取数据失败 跳过 可能是文章正在审核') print(i) time.sleep(10) continue time.sleep(1) os.system('python Article_Keywords.py') # 保存 #workbook.save('data.xls') #time.sleep(30) # 休息三十秒 def GetUrl(num): #从简书首页获取文章链接列表 #======================================正则 urls=[] jianjie=[] title=[] author=[] creat_time=[] nid=[] #===================================== global header,cookie timeArray = str(time.time()) raw=requests.get("https://sspai.com/api/v1/article/index/page/get?limit=10&offset="+str(num*10)+"&created_at="+timeArray,headers=header,cookies=cookie) jsondata=json.loads(raw.text)['data'] for i in jsondata: nid.append(i['id']) title.append(i['title']) jianjie.append(i['summary']) author.append(i['author']['nickname']) creat_time.append(i['released_time']) urls.append('https://sspai.com/post/'+str(i['id'])) return (urls,jianjie,nid,title,author,creat_time) #返回七个文章链接 每次加载七个 def SaveMyql(data): global config db = pymysql.connect(**config) cursor = db.cursor() sql = "INSERT INTO article(title,author,summary,content,create_time,link,nid) VALUES"+str(data) cursor.execute(sql) db.commit() # 提交数据 print("success") cursor.close() db.close() def SaveDataxls(data): global workbook, worksheet dataid=int(data[0]) # 写入excel # 参数对应 行, 列, 值 worksheet.write(dataid, 0, str(dataid)) worksheet.write(dataid, 1, data[1]) worksheet.write(dataid, 2, data[2]) worksheet.write(dataid, 3, data[3]) worksheet.write(dataid, 4, data[4]) worksheet.write(dataid, 5, data[5]) worksheet.write(dataid, 6, data[6]) worksheet.write(dataid, 7, data[7]) def startexcel(): global workbook, worksheet # 创建一个workbook 设置编码 workbook = xlwt.Workbook(encoding='utf-8') # 创建一个worksheet worksheet = workbook.add_sheet('data') # 参数对应 行, 列, 值 初始化 worksheet.write(0, 0, "id") worksheet.write(0, 1, "title") worksheet.write(0, 2, "auther") worksheet.write(0, 3, "summary") worksheet.write(0, 4, "content") worksheet.write(0, 5, "update") worksheet.write(0, 6, "source") worksheet.write(0, 7, "nid") if __name__ == "__main__": main()3.酷推酷推是专门整合各类信息的网站，获取更多数据竟然还要充值季度会员，怒花10块大洋。爬了一些文章后，提示ip被ban，只能上代理了，这里用的是小象代理。https://www.xiaoxiangdaili.com/短效ip 一块钱一天，还挺合算 # coding = utf8mb4 import os import requests from bs4 import BeautifulSoup import time from retry import retry import multiprocessing import re global config import pymysql import text_summarizer import emoji config = { } def main(): wordlinks=[] #wordlinks.append('https://www.tuicool.com/ah/101050000/') #wordlinks.append('https://www.tuicool.com/ah/101040000/') # wordlinks.append('https://www.tuicool.com/ah/101000000/') # wordlinks.append('https://www.tuicool.com/ah/0/') # wordlinks.append('https://www.tuicool.com/topics/10050043?st=1&lang=1&pn=') # wordlinks.append('https://www.tuicool.com/topics/10050042?st=1&lang=1&pn=') # wordlinks.append('https://www.tuicool.com/topics/10050828?st=1&lang=1&pn=') # wordlinks.append('https://www.tuicool.com/topics/10050001?st=1&lang=1&pn=') wordlinks.append('https://www.tuicool.com/topics/11020012?st=1&lang=1&pn=') wordlinks.append('https://www.tuicool.com/topics/22120059?st=1&lang=1&pn=') wordlinks.append('https://www.tuicool.com/topics/22190243?st=1&lang=1&pn=') wordlinks.append('https://www.tuicool.com/topics/22120138?st=1&lang=1&pn=') requests.adapters.DEFAULT_RETRIES = 20 for w,wordlink in enumerate(wordlinks): for page in range(0, 2): proxies = changeip() header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36", "Connection": "close", "cookie": "UM_distinctid=17c275c006ece3-083b66b719969d-a7d173c-384000-17c275c006fe78; __gads=ID=96df49f668e51a53-22c50fc1eecb00b5:T=1632748471:RT=1632748471:S=ALNI_MZ6tw2ZepbAUa-I3s2IIpLh2yOvCA; CNZZDATA5541078=cnzz_eid%3D620993454-1632739373-https%253A%252F%252Fwww.baidu.com%252F%26ntime%3D1632756015; _tuicool_session=[binary]%3D--da792ede16542253ae36372e2225d41a90ea6760" } i = 0 while i < 5: try: raw = requests.get(wordlink + str(page), headers=header, proxies=proxies, timeout=2).text break except requests.exceptions.RequestException: i = i + 1 print('请求超时,正在重试...1') if i == 5: continue if str(raw)=="<Response [404]>": break soup = BeautifulSoup(raw, "html.parser") textlistdata = soup.select(".title a") textlist = [] ids = [] for i in textlistdata: textlist.append("https://www.tuicool.com" + i['href']) ids.append(i['href']) #p = multiprocessing.Process(target=spider, args=(textlist,wordname[w],ids,header,proxies)) #p.start() spider(textlist,ids,header,proxies) # time.sleep() time.sleep(5) print("第" + str(page) + "页采集成功...") os.system('python Article_Keywords.py') os.system('python classify.py') def changeip(): ip = requests.get( 'https://api.xiaoxiangdaili.com/ip/get?appKey=760113727143301120&appSecret=uRjSbv3w&cnt=&wt=text').text while ip=='{"code":1010,"success":false,"data":null,"msg":"请求过于频繁"}': time.sleep(5) ip = requests.get( 'https://api.xiaoxiangdaili.com/ip/get?appKey=760113727143301120&appSecret=uRjSbv3w&cnt=&wt=text').text print("更换ip成功" + ip) proxies = { 'http': ip, 'https': ip } return proxies def spider(textlist,ids,header,proxies): global config imgre1=re.compile('<img.*?src="') imgre2=re.compile('!web.*?>') passre = re.compile('<.*?>') db = pymysql.connect(**config,charset="utf8mb4") cursor = db.cursor() for v, link in enumerate(textlist): sql = "SELECT nid FROM article WHERE nid='" + (str(ids[v]).replace('/','')+"'") # 查询文章绝对id是否存在 msg = cursor.execute(sql) if msg == 1: print("该条数据已经存在------" ) continue i = 0 while i < 5: try: raw = requests.get(link, headers=header, proxies=proxies, timeout=2).text break except requests.exceptions.RequestException: i = i + 1 print('请求超时,正在重试...2') if i == 5: proxies = changeip() continue soup = BeautifulSoup(raw, "html.parser") try: article = str(soup.select(".article_body")[0]) article=article.replace('\xa0','').replace('xa0','').replace('','**').replace("","**").replace(" ","# ").replace(" ","").replace(" ","## ").replace(" ","").replace('ufeff','\n').replace(' ','\n').replace(' ','\n') article=re.sub(imgre1,'![img](',article) article = re.sub(imgre2, ')',article) article=re.sub(passre,"",article) article=filter_emoji(article) timea=soup.select('.timestamp')[0].text.replace('时间\xa0','').replace('\n','').replace(' ','') author=soup.select('.cut')[0].text.replace('\n','').replace(' ','') author=filter_emoji(author) source=soup.select('.cut')[1].text nnid=ids[v].replace("/", "") title=soup.select('h1')[0].text title=filter_emoji(title) except: continue data=(title,author,article,timea,source,nnid) print(data) sql = "INSERT INTO article(title,author,content,create_time,link,nid) VALUES" + str(data) try: cursor.execute(sql) except: continue db.commit() # 提交数据 print("success") cursor.close() db.close() #if os.path.exists(".\\" + wordname + "\\" + wordname + ids[v].replace("/", "-") + ".txt") == 0 and article != "": # f = open(".\\" + wordname + "\\" + wordname + ids[v].replace("/", "-") + ".txt", 'a', # encoding='utf-8') # f.write(article) # f.close # print(".\\" + wordname + "\\" + wordname + ids[v].replace("/", "-") + ".txt 采集成功..." + link) #else: # print("已经存在...跳过") # continue def filter_emoji(desstr, restr=''): # 过滤表情 try: co = re.compile(u'[\U00010000-\U0010ffff]') except re.error: co = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]') return co.sub(restr, desstr) def SaveMyql(data): global config db = pymysql.connect(**config) cursor = db.cursor() sql = "INSERT INTO article(title,author,content,create_time,link,nid) VALUES"+str(data) cursor.execute(sql) db.commit() # 提交数据 print("success") cursor.close() db.close() # 按间距中的绿色按钮以运行脚本。 if __name__ == '__main__': main()上面很长的一个列表是获取词条单页时需要用到的，为此专门写了个小脚本，只不过没有将其整合。 import requests import re import json def main(): id=[] link=[] header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36", "Connection": "close", "cookie": "UM_distinctid=17c275c006ece3-083b66b719969d-a7d173c-384000-17c275c006fe78; __gads=ID=96df49f668e51a53-22c50fc1eecb00b5:T=1632748471:RT=1632748471:S=ALNI_MZ6tw2ZepbAUa-I3s2IIpLh2yOvCA; CNZZDATA5541078=cnzz_eid%3D620993454-1632739373-https%253A%252F%252Fwww.baidu.com%252F%26ntime%3D1632756015; _tuicool_session=[binary]%3D--da792ede16542253ae36372e2225d41a90ea6760" } for page in range(2,10): raw = requests.get("https://www.tuicool.com/topics/my_hot?id="+str(page),headers=header).text jsondata=json.loads(raw)['data'] for i in jsondata: id.append(i['id']) for x in id: print("wordlinks.append('https://www.tuicool.com/topics/"+str(x)+"?st=1&lang=1&pn=')") if __name__ == '__main__': main()4.心得与总结团队协作的感觉还不错（也可能是我负责的部分太简单），只需要专心做自己的事情就可以了，多多学习吧，掌握更多的技术。
[post cid="65" cover=""/]刚学c语言时大一上学期有了这种思考有天睡觉前突然想起是否可以用这种解法枚举一个逐渐递增0.5的数用总金额除以这个数如果除不尽就说明一定会淘汰人，因为这样就无法凑成完整的一组#include<stdio.h> int main(void) { int man,woman; int total; printf("男生代表一元 女生代表五角\n"); printf("请输入男生和女生的人数：\n"); scanf("%d %d",&man,&woman); total=man*10+woman*5; //小数没有%符号，转换一下 int i=10; float x; while(i<total) { if(total % i != 0){ x=(float)i/10; printf("%g ",x) ; } else{ if((i/5)%2!=0 && (total/i)>woman){ x=(float)i/10; printf("%g ",x) ; } } i+=5; } return 0; } 以后想起来更好的解法再来补充