爬虫:爬取Github项目结构、任意文件下载存储

2023-11-04

场景描述

需求:发现 任意文件下载漏洞 后,可能需要下载源码进行代码审计。

问题:burpsuite 拦截 HTTP/HTTPS 流量,不能使用 Intrude 模块通过文件路径字典来下载文件。

启发:遇到这个问题后,当时是采取手工访问来下载文件。前两天看了 @L4ml3da师傅 的内部分享视频讲到了 selenium,19年曾经拿 selenium 写过千行代码,就想到可以通过 selenium 来实现 登录接口爆破任意文件下载 等功能的自动化。(至少让我想到了自动化,为以后的偷懒夯实基础)

实践:Python 能实现 登录接口爆破任意文件下载,其中任意文件下载只要保存返回的数据即可。Python真香,要啥 selenium 模块。

爬取 Github 项目的文件结构

爬取 Laravel 8.x 文件结构

在 Github 上面找了一个 Laravel 8.x 项目,怎么获得其文件结构呢?建议写个爬取脚本,解放双手,成就你的梦想!

编写脚本

参考:

使用 Python 爬虫访问 Github,经常出现连接超时、或读取超时的错误。

访问 Github 连接超时

管理员身份打开记事本,打开文件 C:\Windows\System32\drivers\etc\hosts,添加 DNS 解析记录:

192.30.255.112  github.com git 
185.31.16.184 github.global.ssl.fastly.net  
requests 读取时间超时
# 设置重连3次
s = requests.session()
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))

resp = s.get(url, timeout=(5, 20))	# 20秒是等待服务器响应内容的时间

Github 设置了反爬机制,根据实验推测是一定时间内响应一次,设置随机的 User-Agent 代理没有作用。

打算让 requests 走 proxies 本地代理,手动更换 IP,但没连上代理端口,而且这个只能是缓兵之计。

目前还是耐心等待,爬一次等一分钟。(备注:使用代理连接很通畅)

爬取脚本

Spider_Github_FileStructure.py

# -*- coding: utf-8 -*-

import requests
from requests.adapters import HTTPAdapter
from bs4 import BeautifulSoup

"""避免给注释斜体和加粗"""
"""
@ ToDo:   Crawl the file structure of the GitHub project
@ author: pump
@ date: 2021/11/05
@ 适配性
    问题1,爬取 laravel 5.7
        正常的项目根目录路径是: https://github.com/laravel/laravel/tree/5.7,https://github.com/laravel/laravel/tree/8.x(示例中的是默认页)
        更正:项目根目录地址——修改,前缀和后缀——适配无需修改          
@ 思路:
    访问页面得到的原始数据:一堆超链接。
    筛选原始数据:根据路径。
    处理数据:是目录就下一层。是文件就保存路径。

    第二层,继续调用该方法。需要增加前缀以免重复爬取同一页面,但不能直接增加前缀,否则无法回溯到根目录继续爬取。

@ Github 项目路径信息:
    目录路径:https://github.com/laravel/laravel/tree/8.x/,目录都在/tree目录下
    文件路径:https://github.com/laravel/laravel/blob/8.x/,文件都在/blob/目录下
    补充:目前未确定,是否所有Github项目都以 /tree/ 和 /blob/ 路径来存储文件

@ 算法步骤:
    访问项目根目录页面,把超链接划分成三种:无关类、目录类、文件类
    @@@ 第一层
    (1)无关类:筛选掉
    (2)文件类:写入文件。依据:具有前缀/blob/8.x/
    (3)目录类:多层迭代访问。依据:具有前缀/tree/8.x/

    目录迭代访问算法:
        @@@ 第二层
            例如超链接的相对路径是:/laravel/laravel/tree/8.x/app,此时前缀是/laravel/laravel/tree/8.x/,
    需要对 url 、两个前缀进行更新以下一次调用。此时 url = urlRoot + href
        (1)更新 url:为了求 url ,要从超链接中截取出 "app",取名后缀tail = href[len(directoryPre):] = "app"
        (2)更新目录前缀:directoryPre + tail
        (3)更新文件前缀:filePre + tail
        @@@ 错误更正1
            错误:不能直接修改前缀的值,这样会导致后续的前缀值无法还原,比如使用前缀/xx/app筛选项目根目录,结果将为空
            更正:传递参数时加上tail,不改变变量值

        @@@ 错误更正2
            错误:保存文件名时,没有添加目录前缀
            更正:定义一个初始前缀变量,把初始前缀变量删除即可

        @@@ 结果保存
            需求:每次启动脚本时,首先清空 .txt 文件内容。
            限制:不能把 write_path() 的文件打开方式改成 w ,因为每次递归都会打开一次
            解决:定义一个清空的函数,启动时写入""来清空

        @@@ 访问情况备注
            使用科学上网软件开启系统代理模式,访问Github几乎无失败记录,非常丝滑
"""

"""
函数说明
    class::__init__(urlRoot, url, dicFilename, directoryPre, filePre) 初始化变量/配置项

    class::write_path(filename, fileList) 把文件路径写入结果文件

    class::write_flush(filename) 清空存放文件路径的结果文件

    class::crawl_github_file_structure(urlRoot, url, dicFilename, directoryPre, filePre) 递归爬取目录、把文件路径写入结果文件

参数说明
    dicFilename = "projectStructure/laravel/laravel_8.x_fileStructure.txt"   变量:存放结果的文件
    urlRoot = "https://github.com"                  常量
    url = "https://github.com/laravel/laravel/"     变量:项目根目录地址
    directoryPre = "/tree/8.x/"                     变量:项目目录存储的路径
    filePre = "/blob/8.x/"                          变量:项目文件存储的路径

class使用说明
    crawl = CrawlGithub(urlRoot, url, dicFilename, directoryPre, filePre)
    
    crawl.write_flush(dicFilename)
    crawl.crawl_github_file_structure(urlRoot, url, dicFilename, directoryPre, filePre)

有效代码量:64 lines
实例结果:见文件末尾
"""


class CrawlGithub:

    def __init__(self, urlRoot, url, dicFilename, directoryPre, filePre):
        self.urlRoot = urlRoot
        self.url = url
        self.dicFilename = dicFilename
        self.directoryPre = directoryPre
        self.filePre = filePre
        self.initDirectoryPre = directoryPre
        self.initFilePre = filePre

    def write_path(self, filename, fileList):
        with open(filename, 'a+') as f:
            for file in fileList:
                f.write(file + "\n")
            f.close()

    def write_flush(self, filename):
        with open(filename, 'w') as f:
            f.write("")
            f.close()

    def crawl_github_file_structure(self, urlRoot, url, dicFilename, directoryPre, filePre):
        try:
            # 设置重连3次
            s = requests.session()
            s.mount('http://', HTTPAdapter(max_retries=3))
            s.mount('https://', HTTPAdapter(max_retries=3))
            resp = s.get(url, timeout=(5, 20))
            print("访问成功")

            fileList = []
            soup = BeautifulSoup(resp.text, "lxml")
            list_a = soup.find_all('a')
            for a in list_a:
                href = a.get('href')
                print(href)

                # 只做白名单即可:目录路径前缀 /tree/8.x/、文件路径前缀 /blob/8.x/
                if directoryPre in href:    # 目录
                    url = urlRoot + href   # 新的访问页面
                    tail = href[16 + len(directoryPre):]
                    print(url)
                    self.crawl_github_file_structure(urlRoot, url, dicFilename, directoryPre + tail, filePre + tail)

                if filePre in href:
                    href = href[href.find(self.initFilePre) + len(self.initFilePre):]
                    fileList.append(href)
            self.write_path(dicFilename, fileList)

        except requests.exceptions.ConnectTimeout:
             print("网络连接超时")
        except requests.exceptions.ReadTimeout:
            print("读取时间超时")

if __name__ == "__main__":
    dicFilename = "projectStructure/laravel/laravel_5.7_fileStructure.txt"
    urlRoot = "https://github.com"
    url = "https://github.com/laravel/laravel/tree/5.7"
    directoryPre = "/tree/5.7/"
    filePre = "/blob/5.7/"

    crawl = CrawlGithub(urlRoot, url, dicFilename, directoryPre, filePre)

    crawl.write_flush(dicFilename)
    crawl.crawl_github_file_structure(urlRoot, url, dicFilename, directoryPre, filePre)

'''
@@@ 结果示例
app/Console/Kernel.php
app/Exceptions/Handler.php
app/Http/Controllers/Controller.php
app/Http/Middleware/Authenticate.php
app/Http/Middleware/EncryptCookies.php
app/Http/Middleware/PreventRequestsDuringMaintenance.php
app/Http/Middleware/RedirectIfAuthenticated.php
app/Http/Middleware/TrimStrings.php
app/Http/Middleware/TrustHosts.php
app/Http/Middleware/TrustProxies.php
app/Http/Middleware/VerifyCsrfToken.php
app/Http/Kernel.php
app/Models/User.php
app/Providers/AppServiceProvider.php
app/Providers/AuthServiceProvider.php
app/Providers/BroadcastServiceProvider.php
app/Providers/EventServiceProvider.php
app/Providers/RouteServiceProvider.php
bootstrap/cache/.gitignore
bootstrap/app.php
config/app.php
config/auth.php
config/broadcasting.php
config/cache.php
config/cors.php
config/database.php
config/filesystems.php
config/hashing.php
config/logging.php
config/mail.php
config/queue.php
config/sanctum.php
config/services.php
config/session.php
config/view.php
database/factories/UserFactory.php
database/migrations/2014_10_12_000000_create_users_table.php
database/migrations/2014_10_12_100000_create_password_resets_table.php
database/migrations/2019_08_19_000000_create_failed_jobs_table.php
database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php
database/seeders/DatabaseSeeder.php
database/.gitignore
public/.htaccess
public/favicon.ico
public/index.php
public/robots.txt
public/web.config
resources/css/app.css
resources/js/app.js
resources/js/bootstrap.js
resources/lang/en/auth.php
resources/lang/en/pagination.php
resources/lang/en/passwords.php
resources/lang/en/validation.php
resources/views/welcome.blade.php
routes/api.php
routes/channels.php
routes/console.php
routes/web.php
storage/app/public/.gitignore
storage/app/.gitignore
storage/framework/cache/data/.gitignore
storage/framework/cache/.gitignore
storage/framework/sessions/.gitignore
storage/framework/testing/.gitignore
storage/framework/views/.gitignore
storage/framework/.gitignore
storage/logs/.gitignore
tests/Feature/ExampleTest.php
tests/Unit/ExampleTest.php
tests/CreatesApplication.php
tests/TestCase.php
.editorconfig
.env.example
.gitattributes
.gitignore
.styleci.yml
CHANGELOG.md
README.md
artisan
composer.json
package.json
phpunit.xml
server.php
webpack.mix.js
'''

任意文件下载脚本

File_Arbitraty_Download.py

# -*- coding: utf-8 -*-

import requests
from requests.adapters import HTTPAdapter
import os


"""
@ 脚本流程如下,对应三个函数:
        读取字典:逐行读取 projectStructureDicts 目录下的{路径字典文件},返回一个列表
        访问文件:根据 path 访问站点,根据状态码(200)选择保存文件
        保存文件:保存到 projectFiles 目录下

@ 判断文件是否存在:状态码,示例状态码是200


@调试
    错误: open("", 'w')通过多级目录创建文件失败,例如 [Errno 2] No such file or directory: 'projectFiles/xxx/app/Exceptions/Handler.php'
    原因: open() 无法创建目录
    解决: 使用 os 库 的 os.makedirs() 递归创建目录,其中使用 str.rfind()从末尾查找子串 / ,从而截取目录
    
    错误: 下载的文件内容不对
    解决: 发现是 传参方式,GET 传参才能200,POST 传参会 405 报错
    
@数据保存
    保存文件内容: resp.content
    文件内容格式: resp.content 的格式是 bytes,即 b'xxxxxx'。调用方法 str(b, encoding = "utf8"),直接解决排版问题

@备注: laravel 的 Web 根目录是 app/Http/Controllers/,示例页面 /Student/Title/BookController.php
"""


class FileArbitraryDownload:

    def __init__(self, url, dictName, projectName):

        self.url = url
        self.dictName = 'projectDicts/' + dictName
        self.projectPath = "projectFiles/" + projectName    # 保存文件的文件夹

    def read_dict(self):
        with open(self.dictName, 'r') as f:
            content = f.read()
            path_list = content.split("\n")
            f.close()
        return path_list

    def download(self):

        # 设置重连3次
        s = requests.session()
        s.mount('http://', HTTPAdapter(max_retries=3))
        s.mount('https://', HTTPAdapter(max_retries=3))

        # proxies = {
        #     "http": "http://127.0.0.1:8080",
        #     "https": "https://127.0.0.1:8080"
        # }
        # 读取字典
        path_list = self.read_dict()
        for path in path_list:
            try:
                print(self.url + path)
                resp = s.get(self.url + path, timeout=5)
                print(self.url + path)
                print(resp.status_code)
                if resp.status_code == 200:
                    self.store_file(path, resp.content)
            except Exception as e:
                print(e)

    def store_file(self, path, file_content):
        file_path = self.projectPath + path
        if not os.path.exists(file_path[:file_path.rfind("/")]):
            os.makedirs(file_path[:file_path.rfind("/")])
        with open(file_path, 'w') as f:
            f.writelines(str(file_content, encoding="utf-8"))
        f.close()


        # write() argument must be str, not bytes


if __name__ == '__main__':
    url = "http://xxx/download?path=/../"
    dictName = "laravel/laravel_5.7_fileStructure.txt"
    projectName = 'xx站点源码/'

    crawlDownload = FileArbitraryDownload(url, dictName, projectName)

    crawlDownload.download()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

爬虫:爬取Github项目结构、任意文件下载存储 的相关文章

  • Python中Decimal类型的澄清

    每个人都知道 或者至少 每个程序员都应该知道 http docs oracle com cd E19957 01 806 3568 ncg goldberg html 即使用float类型可能会导致精度错误 然而 在某些情况下 精确的解决方
  • Python - 将宽字符字符串从二进制文件转换为 Python unicode 字符串

    这是漫长的一天 我有点困惑 我正在读取一个包含大量宽字符字符串的二进制文件 我想将它们转储为 Python unicode 字符串 为了解压非字符串数据 我使用 struct 模块 但我不知道如何对字符串执行相同的操作 例如 阅读 系列 一
  • python future 和元组解包

    实现像使用 future 进行元组解包这样的事情的优雅 惯用的方法是什么 我有这样的代码 a b c f x y g a b z h y c 我想将其转换为使用期货 理想情况下我想写一些类似的东西 a b c ex submit f x y
  • 如何在序列化器创建方法中获取 URL Id?

    我有以下网址 url r member P
  • 在 Tensorflow tf.nn.nce_loss 中出现 TypeError:'Mul' Op 的输入 'y' 的类型为 float32,与参数 'x' 的 int32 类型不匹配

    我正在研究 Tensor Flow 中的 Bag of Words 实现 并得到了 类型错误 Mul Op 的输入 y 的类型为 float32 与参数 x 的 int32 类型不匹配 在 tf nn nce loss 中 我尝试查看 tf
  • python 模拟第三方模块

    我正在尝试测试一些处理推文的类 我使用 Sixohsix twitter 来处理 Twitter API 我有一个类充当 Twitter 类的外观 我的想法是模拟实际的 Sixohsix 类 通过随机生成新推文或从数据库检索它们来模拟推文的
  • Python逻辑运算符优先级[重复]

    这个问题在这里已经有答案了 哪个运算符优先4 gt 5 or 3 lt 4 and 9 gt 8 这会被评估为真还是假 我知道该声明3 gt 4 or 2 lt 3 and 9 gt 10 显然应该评估为 false 但我不太确定 pyth
  • Django 模型在模板中不可迭代

    我试图迭代模型以获取列表中的第一个图像 但它给了我错误 即模型不可迭代 以下是我的模型和模板的代码 我只需要获取与单个产品相关的列表中的第一个图像 模型 py class Product models Model title models
  • python suds SOAP 请求中的名称空间前缀错误

    我使用 python suds 来实现客户端 并且在发送的 SOAP 标头中得到了错误的命名空间前缀 用于定义由element ref 在 wsdl 中 wsdl 正在引用数据类型 xsd 文件 请参见下文 问题出在函数上GetRecord
  • 使用 OLS 回归预测未来值(Python、StatsModels、Pandas)

    我目前正在尝试在 Python 中实现 MLR 但不确定如何将我找到的系数应用于未来值 import pandas as pd import statsmodels formula api as sm import statsmodels
  • 如何设置 Celery 来调用自定义工作器初始化?

    我对 Celery 很陌生 我一直在尝试设置一个具有 2 个独立队列的项目 一个用于计算 另一个用于执行 到目前为止 一切都很好 我的问题是执行队列中的工作人员需要实例化一个具有唯一 object id 的类 每个工作人员一个 id 我想知
  • 如何使用列表作为pandas数据框中的值?

    我有一个数据框 需要列的子集包含具有多个值的条目 下面是一个带有 运行时 列的数据框 其中包含程序在各种条件下的运行时 df condition a runtimes 1 1 5 2 condition b runtimes 0 5 0 7
  • 如何在 python 中没有 csv.reader 迭代器的情况下解析单行 csv 字符串?

    我有一个 CSV 文件 需要重新排列和重新编码 我想跑 line line decode windows 1250 encode utf 8 在由 CSV 读取器解析和分割之前的每一行 或者我想自己迭代行 运行重新编码 并仅使用单行解析表单
  • Python 将日志滚动到变量

    我有一个使用多线程并在服务器后台运行的应用程序 为了无需登录服务器即可监控应用程序 我决定包括Bottle http bottlepy org为了响应一些HTTP端点并报告状态 执行远程关闭等 我还想添加一种查阅日志文件的方法 我可以使用以
  • 部分共享git仓库

    我是 git 新手 我想知道是否支持以下场景 如果支持的话如何支持 即用于设置和更新的 git 命令 可以从三个不同的地方获取存储库 本地 镜像 和 github mirror 完全镜像 local github 镜像 local 但 受版
  • 如何为每个屏幕添加自己的 .py 和 .kv 文件?

    我想为每个屏幕都有一个单独的 py 和 kv 文件 应通过 main py main kv 中的 ScreenManager 选择屏幕 设计应从文件 screen X kv 加载 类等应从文件 screen X py 加载 Screens
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • 如何读取Python字节码?

    我很难理解 Python 的字节码及其dis module import dis def func x 1 dis dis func 上述代码在解释器中输入时会产生以下输出 0 LOAD CONST 1 1 3 STORE FAST 0 x
  • 迭代 pandas 数据框的最快方法?

    如何运行数据框并仅返回满足特定条件的行 必须在之前的行和列上测试此条件 例如 1 2 3 4 1 1 1999 4 2 4 5 1 2 1999 5 2 3 3 1 3 1999 5 2 3 8 1 4 1999 6 4 2 6 1 5 1
  • Scrapy Spider不存储状态(持久状态)

    您好 有一个基本的蜘蛛 可以运行以获取给定域上的所有链接 我想确保它保持其状态 以便它可以从离开的位置恢复 我已按照给定的网址进行操作http doc scrapy org en latest topics jobs html http d

随机推荐

  • 轻松成为设计高手

    目录 2 Verilog语言基础 2 1 三种描述方法 2 Verilog语言基础 2 1 三种描述方法 1 数据流描述 assign连续赋值语句 2 行为描述 过程赋值语句 always和initial过程块 3 结构化描述 实例化已有的
  • 微服务(SpringCloud)

    1 什么是微服务 将一个大项目中各个业务代码进行拆分 拆分成多个互不相干小项目 每个项目完成自己特有的功能 而且可以通过调用别的项目完成整体功能 2 SpringCloud 是由Spring提供的一套能够快速搭建微服务框架程序的框架集 也被
  • WEB漏洞测试(二)——HTML注入 & XSS攻击

    上一篇介绍了我们安装BWAPP来完成我们的漏洞测试 在BWAPP中 将HTML Injection和XSS做了非常详细的分类 那么为什么要将两个一起讲呢 归根结底 我觉得这两个分明是一个玩意 充其量是攻击的方式不一样 我们先来介绍一下这两种
  • Electron入门应用打包exe(windows)

    最近在学习nodejs 得知Electron是通过将Chromium和Node js合并到同一个运行时环境中 用HTML CSS和JavaScript来构建跨平台桌面应用程序的一门技术 对于之前一直从事flash AIR桌面应用开发的我迫不
  • 【网络】交换机 VLAN 网关 路由器

    网关 含义 网间连接器 协议转换器 在传输层上实现网络互连 PS 二层交换机在链路层 路由 三层交换机在网络层 集线器 中继器在物理层 是最复杂的网络互联设备 仅用于两个高层协议不同的网络互连 网关有很多种 最常用的是TCP IP协议里的网
  • DDoS攻击原理及防御

    转自 微点阅读 https www weidianyuedu com 随着网络时代的到来 网络安全变得越来越重要 在互联网的安全领域 DDoS Distributed DenialofService 攻击技术因为它的隐蔽性 高效性一直是网络
  • matlab自回归模型AIC,时间序列笔记-自回归模型(二)

    笔记说明 在datacamp网站上学习 Time Series with R track Introduction to Time Series Analysis 课程 做的对应笔记 学识有限 错误难免 还请不吝赐教 如无特殊说明 笔记中所
  • gcc常见编译参数介绍

    1 常见编译参数介绍 gcc可以说是个伟大的编译器集合 支持c c object c java fortran pascal ada等一大堆语言 同时支持几乎所有32位以上的cpu和部分16位 8位cpu 因此几乎所有开源操作系统 商业un
  • uniapp微信小程序 ios端部分机型屏幕可左右滑动原因即处理

    1 原因 因为部分元素超过了屏幕尺寸大小 2 处理 在超出屏幕尺寸的元素上一级使用 width 100 overflow x hidden 如果是图片导致的 则需要把多余的裁剪掉
  • ubuntu虚拟机搭建hadoop完全分布式集群

    一 需要的工具 需要的工具我已经完成分享 需要的可以直接在网盘中下载 VMware15 Workstation Pro 提取码 pp12 ubuntu16 18 19 镜像 提取码 yfj0 Xshell Xftp 提取码 6ao9 jdk
  • 7月网络学习报告

    原始代码 import torch import torch nn as nn import torch nn functional as F import torchvision from torchvision import datas
  • C++ 基础知识

    C 基础知识 一 语法 1 指针常量 常量指针 2 内存模型 3 引用 4 C 中面向对象的三大特性 5 纯虚函数和抽象类 6 文件操作 7 模板与泛型 8 STL 一 语法 1 指针常量 常量指针 指针常量 顾名思义 指针是一个常量 所以
  • 开源C/C++网络库比较 ace &&bosst &&libEvent

    ACE是一个大型的中间件产品 代码20万行左右 过于宏大 一堆的设计模式 架构了一层又一层 使用的时候 要根据情况 看你从那一层来进行使用 在开源的C C 网络库中 常用的就那么几个 在业界知名度最高的 应该是ACE了 不过是个重量级的大家
  • 盘点:计算机专业含金量最高的证书!只需一种证书在手,从此不愁

    第一种证书 计算机技术与软件专业资格考试证书 计算机技术与软件专业资格考试证书 是由国家人力资源和社会保障部 工业和信息化部领导的国家级考试 该考试分为 5 个专业类别 并分设了高 中 初级专业资格考试 共 28 个资格的考核 也是用人单位
  • 微服务设计指导-hystrix参数介绍

    连接nacos的配置 nacos 服务地址 spring cloud nacos discovery server addr nacos server addr 注册到nacos上的命名空间 spring cloud nacos disco
  • MySQL数据库基础知识11,查询缓存

    目录 一 查询缓存是什么 二 MySQL如何判断缓存命中 三 使用查询缓存需谨慎 四 如何分析和配置查询缓存 五 InnoDB和查询缓存 MySQL进阶实战系列文章 哪吒精品系列文章 一 查询缓存是什么 MySQL查询缓存保存查询返回的完整
  • 【OpenCV图像处理】1.23 直方图(Histogram)均衡化

    文章目录 相关理论 代码 展示效果 相关理论 什么是直方图 图像直方图 是指对整个图像像在灰度范围内的像素值 0 255 统计出现频率次数 据此生成的直方图 称为图像直方图 直方图 直方图反映了图像灰度的分布情况 是图像的统计学特征 直方图
  • 逆水寒紫禁之巅服务器维护,逆水寒"紫禁之巅"服务器或将成历史?王思聪、PDD时代已渐行渐远...

    原标题 逆水寒 紫禁之巅 服务器或将成历史 王思聪 PDD时代已渐行渐远 从没有一款端游 能像 逆水寒 这样 能吸引如此多的社会名流入驻游戏 在游戏开测之初 打着 五年五亿巨制 网易最后一款端游 的口号 连王思聪 秦奋等名人都纷纷入坑 逆水
  • 龙书笔记(9)

    chap 9 字体 生成和输出文本的3种方式 ID3DXFont CD3DFont D3DXCreateText 1 ID3DXFont接口 能处理一些复杂的字体和格式 但是速度略慢 创建ID3DXFont对象 D3DXFONT DESC
  • 爬虫:爬取Github项目结构、任意文件下载存储

    文章目录 场景描述 爬取 Github 项目的文件结构 爬取 Laravel 8 x 文件结构 编写脚本 访问 Github 连接超时 requests 读取时间超时 爬取脚本 任意文件下载脚本 场景描述 需求 发现 任意文件下载漏洞 后