前言:

浏览某乎网站时发现了一个分享各种图片的博主,于是我顺手就保存了一些。但是一张一张的保存实在太麻烦了,于是我就想要某虫的手段来处理。这样保存的确是很快,但是他不识图片内容,最近又看了 mobileNet 的预训练模型,想着能让程序自己对图片分类,以下就通过例子从内容采集到分类的过程。

内容和资源的采集,反手就是某虫了。在网络上,经过近几年的营销渲染,可能首选是用 Python 做脚本。而这次是用 PHP 的 QueryList 来做采集,下面也就是采集的编码过程和踩坑解决方法,最后再对采集图片进行标注和训练。

环境:

PHP7.4

QueryList4.0

QueryList-CurlMulti

编码:

以下例子是基于 TP5.1,所以只需要安装上面两个依赖包。采集启动通过自定义命令实现,接下来分别以普通采集和多线程采集两种方式展示。

1. 普通采集

<?php
/**
* @Notes: 公众号:ZERO开发
* @Interface getCondition
* @Return mixed
* @Author: bqs
* @Time: 2021/4/19 15:28
*/ namespace app\common\command; use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\console\input\Argument;
use think\console\input\Option;
use think\Db;
use think\facade\Hook;
use think\facade\Log;
use QL\QueryList; class QueryListSpiderSingle extends Command
{ protected function configure()
{
$this->setName('querylist:single')
->setDescription('采集');
} protected function execute(Input $input, Output $output)
{
ini_set('memory_limit', '512M'); $output->writeln("=========date:" . date('Y-m-d H:i:s') . "==============="); // 北桥苏奥特曼
//$slImgsUrl = "https://zhuanlan.zhihu.com/p/377571373";
$slImgsUrl = "https://zhuanlan.zhihu.com/p/344680014"; // 原生query_list
$list = QueryList::get($slImgsUrl)->find('.RichText')->find('noscript')->find('img')->attrs('src'); $path = 'E:\2setsoft\1dev\phpstudy_pro\WWW\4test\tensorflowJs\js-ml-code\t7\动漫分类\train\奥特曼\\';
foreach($list as $key => $value) {
$index = $key + 1 + 42; $filename = $index < 10 ? str_pad($index, 2, "0", STR_PAD_LEFT) : $index;
$filend = pathinfo($value, PATHINFO_EXTENSION);
$file = file_get_contents($value);
file_put_contents($path . $filename . "." . $filend, $file); $output->writeln($index . "--" . $value . "已保存--");
} $output->writeln("============date:" .date("Y-m-d H:i:s") . "采集完成==============");
} }

2. 多线程采集

<?php
/**
* @Notes: 文件描述
* @Interface getCondition
* @Return mixed
* @Author: bqs
* @Time: 2021/4/19 15:28
*/ namespace app\common\command; use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\console\input\Argument;
use think\console\input\Option;
use think\Db;
use think\facade\Hook;
use think\facade\Log;
use QL\QueryList;
use QL\Ext\CurlMulti; class QueryListSpider extends Command
{ protected function configure()
{
$this->setName('query:list')
->setDescription('采集');
} protected function execute(Input $input, Output $output)
{
ini_set('memory_limit', '512M'); $output->writeln("=========date:" . date('Y-m-d H:i:s') . "==============="); // 地址与目录映射
$dirMap = [
"假面骑士" => "https://zhuanlan.zhihu.com/p/376119915",
"龙珠" => "https://zhuanlan.zhihu.com/p/340048917",
"火影忍者" => ["https://zhuanlan.zhihu.com/p/352717188", "https://zhuanlan.zhihu.com/p/393213201", "https://zhuanlan.zhihu.com/p/358228745"],
"海贼王" => ["https://zhuanlan.zhihu.com/p/357683518", "https://zhuanlan.zhihu.com/p/338160632"]
]; // 采集地址
$multiArr = [];
$multiArr = array_reduce(array_values($dirMap), function ($res, $value) {
$res = array_merge($res, (array)$value);
return $res;
}, []); // 采集映射
$multiMap = [];
foreach($dirMap as $key => $value) {
if (!is_array($value)) {
$multiMap[$value] = $key;
} else {
$temp = array_fill_keys($value, $key);
$multiMap = array_merge($multiMap, $temp);
}
} // 开始使用多线程采集
$ql = QueryList::use (CurlMulti::class);
$ql->curlMulti($multiArr)
->success(function (QueryList $ql, CurlMulti $curl, $r) use ($multiMap) { $path = 'E:\2setsoft\1dev\phpstudy_pro\WWW\4test\tensorflowJs\js-ml-code\t7\动漫分类\train\\';
$queryUrl = $r['info']['url'];
$className = $multiMap[$queryUrl] ?? "";
$targetDir = $path . $className;
$path = $targetDir . '\\'; $endFileIndex = 0;
$existFileList = $this->scanFile($targetDir);
if ($existFileList) {
// 取出所有数字文件名最大值
$endFileName = max($existFileList);
$endFileIndex = explode(".", $endFileName)[0];
} $data = $ql->find('.RichText')->find('noscript')->find('img')->attrs('src'); foreach($data as $key => $value) {
$index = $key + 1 + $endFileIndex; $filename = $index < 10 ? str_pad($index, 2, "0", STR_PAD_LEFT) : $index;
$filend = pathinfo($value, PATHINFO_EXTENSION);
$file = file_get_contents($value);
file_put_contents($path . $filename . "." . $filend, $file);
}
})
// 每个任务失败回调
->error(function ($errorInfo, CurlMulti $curl) {
echo "Current url:{$errorInfo['info']['url']} \r\n";
print_r($errorInfo['error']);
})
->start([
// 最大并发数
'maxThread' => 10,
// 错误重试次数
'maxTry' => 5,
]); $output->writeln("============date:" . date("Y-m-d H:i:s") . "采集完成==============");
} // 扫描目录下所有文件
protected function scanFile($path) {
$result = [];
$files = scandir($path);
foreach ($files as $file) {
if ($file != '.' && $file != '..') {
if (is_dir($path . '/' . $file)) {
$this->scanFile($path . '/' . $file);
} else {
$result[] = basename($file);
}
}
}
return $result;
} }

问题解决:

由于普通采集的请求使用 GuzzleHttp 客户端,而多线程采集是 CURL,所以运行时报 curl 状态码 60 错误。

1. 解决方法:

(1). 下载 cacert

下载地址:https://curl.haxx.se/ca/cacert.pem

(2). 修改 php.ini , 并重启

在 php.ini 中找到 curl.cainfo 改为文件的绝对路径如:curl.cainfo =E:\2setsoft\1dev\phpstudy_pro\Extensions\php\php7.4.3nts\cacert.pem

图片训练:

以上的图片已经采集的差不多了,因为博主的图片有限,我也没有再去其他地方找,整个文件夹下的图片在 200 张左右。按理说图片当然是越多越好,但是整个分类标注起来耗时(看文章的配图,应该已经知道有哪几类了吧),所以就这样了。最后就是读取图片转换 Tensor 进行训练,后一篇再具体介绍吧,提醒一下。下一篇需要提前安装 Node, Http-Server,Parcel 工具。

用 Tensorflow.js 做了一个动漫分类的功能(一)的更多相关文章

  1. TensorFlow.js之根据数据拟合曲线

    这篇文章中,我们将使用TensorFlow.js来根据数据拟合曲线.即使用多项式产生数据然后再改变其中某些数据(点),然后我们会训练模型来找到用于产生这些数据的多项式的系数.简单的说,就是给一些在二维 ...

  2. 关于最近在做的一个js全屏轮播插件

    最近去面试了,对方要求我在一个星期内用原生的js代码写一个全屏轮播的插件,第一想法就是跟照片轮播很相似,只是照片轮播是有定义一个宽高度大小已经确定了的容器用来存储所有照片,然后将照片全部左浮动,利用m ...

  3. 做了一个图片等比缩放的js

    做了一个图片等比缩放的js 芋头 发布在view:8447   今天改了一下博客的主题,发现博客主题在ie6下变样了,后来发现是因为某篇文章里的某个图片太大了撑开了容器,导致样式错位,前几天公司需求里 ...

  4. 4-13 Webpacker-React.js; 用React做一个下拉表格的功能: <详解>

    Rails5.1增加了Webpacker: Webpacker essentially is the decisions made by the Rails team and bundled up i ...

  5. 用 JS 做一个数独游戏(二)

    用 JS 做一个数独游戏(二) 在 上一篇博客 中,我们通过 Node 运行了我们的 JavaScript 代码,在控制台中打印出来生成好的数独终盘.为了让我们的数独游戏能有良好的体验,这篇博客将会为 ...

  6. 用 JS 做一个数独游戏(一)

    用 JS 做一个数独游戏(一) 数独的棋盘由 9x9 的方格组成,每一行的数字包含 1 ~ 9 九个数字,并且每一列包含 1 ~ 9 这 9 个不重复的数字,另外,整个棋盘分为 9 个 3x3 的块, ...

  7. 用js给闺女做了一个加减乘除的html

    下班回家用二十分钟给闺女做了一个加减乘除的页面,顺便记录下代码,时间仓促,后期再来修改吧 目录结构 -yq --menu.html --yq.html --yq50.html --yq70.html ...

  8. 用js,css3 做的一个球

    用css3属性很容易做一个立方体,但是要做一个球体,会相对复杂些 原理是:球可以看做是由无数个圆圈构成,然后就可以用圆圈来做球, 下面的例子是我做的一个小球,由72个圆圈组成.如果把每个圆圈的背景颜色 ...

  9. JS 做时钟

    今天,给大家分享一个用JS做的时钟. <!DOCTYPE html><html> <head> <meta charset="utf-8" ...

  10. JS一般般的网页重构可以使用Node.js做些什么(转)

    一.非计算机背景前端如何快速了解Node.js? 做前端的应该都听过Node.js,偏开发背景的童鞋应该都玩过. 对于一些没有计算机背景的,工作内容以静态页面呈现为主的前端,可能并未把玩过Node.j ...

随机推荐

  1. 2023-03-15:屏幕录制并且显示视频,不要用命令。代码用go语言编写。

    2023-03-15:屏幕录制并且显示视频,不要用命令.代码用go语言编写. 答案2023-03-15: 使用moonfdd/ffmpeg-go和moonfdd/sdl2-go库来实现屏幕录制并显示视 ...

  2. 2020-09-18:LRU手撸,说下时间复杂度和空间复杂度。

    福哥答案2020-09-18: 方法:哈希表 + 双向链表.时间复杂度:对于 put 和 get 都是 O(1).空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity+1 ...

  3. 2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格, 他可以从北边的任何一个格子出发,到达南边的任何一个格子, 但每一步只能走到东南、正南、西南方向的

    2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格, 他可以从北边的任何一个格子出发,到达南边的任何一个格子, 但每一步只能走到东南.正南.西南方向的 ...

  4. 2021-04-16:摆放着n堆石子。现要将石子有次序地合并成一堆,规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。求出将n堆石子合并成一堆的最小得分(或最大得分)合

    2021-04-16:摆放着n堆石子.现要将石子有次序地合并成一堆,规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.求出将n堆石子合并成一堆的最小得分(或最大得分)合 ...

  5. 2021-06-25:只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中,如果其中某两个字符串所含有的字符种类完全一样,就将两个字符串算作一类,比如:baacbba

    2021-06-25:只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中,如果其中某两个字符串所含有的字符种类完全一样,就将两个字符串算作一类,比如:baacbba ...

  6. LeetCode 周赛 347(2023/05/28)二维空间上的 LIS 最长递增子序列问题

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 往期回顾:LeetCode 单周赛第 346 场 · 仅 68 人 AK 的最短路问题 周赛 347 概览 ...

  7. Hugging News #0602: Transformers Agents 介绍、大语言模型排行榜发布!

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  8. Java的先行发生原则

    先行发生原则(Happens-Before)是Java内存模型定义的一个等效判断原则.依赖这个原则,我们可以通过几条简单规则判断数据是否存在竞争,线程是否安全,而不需要陷入Java内存模型苦涩难懂的定 ...

  9. 数据科学工具 Jupyter Notebook 教程(一)

    ipython notebook 是一个基于浏览器的 python 数据分析工具,使用起来非常方便,具有极强的交互方式和富文本的展示效果.jupyter 是它的升级版,它的安装也非常方便,一般 Ana ...

  10. unity添加Mysql的dll以及发布的问题

    最近在做一个unity项目中,要读取数据库,还是MySql的数据库.遇到了很多问题,写出来供大家参考一下. 关于unity引用第三方的Mysql.data.dll的问题: 这个地方有一个难点,正常的C ...