# PlayWithPython
**Repository Path**: UnouprimeOder/PlayWithPython
## Basic Information
- **Project Name**: PlayWithPython
- **Description**: 2020 春节太无聊,初探Python。2020's Spring Festival is so boring that I started to play with Python
- **Primary Language**: Python
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-05-20
- **Last Updated**: 2021-05-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 高一寒假的研究性学习
当今,互联网已经将全世界十亿个人计算机用户联结在了一起。我们为了更加了解互联网的组成与功能,这个寒假,(也有疫情只能呆在家中的缘故),我们打算初步探究互联网前端网页的自动化操作的实现。为了研究的趣味性与实用性,我们选择从最近很火的“爬虫”入手,进行我们的研究。
# 严正声明
本次研究性学习的一切内容仅供用于学习交流,严禁用于商业用途。
文章以 CC BY-NA-SA 共享,代码以 MIT License 开源。
-------
# 正文开始了
# 研究目的
初步了解互联网爬虫,感受计算机带来的便捷操作。
# 研究方式、步骤
使用Python爬虫,依次对1. 静态网页2. 动态网页 进行“图片”爬取。
使用Swift程序,对爬取的图片进行处理。
1. 爬取一个“Bing必应壁纸大全”网页
2. 爬取一个“漫画网页”
3. 对爬取的图片进行简单的整理并提高画质
# Get Started
### 环境
电脑:
> MacBook Pro (13-inch, 2017, Four Thunderbolt 3 Ports)
>
> 3.1 GHz 双核Intel Core i5
>
> 8 GB 2133 MHz LPDDR3
>
> Intel Iris Plus Graphics 650 1536 MB
>
系统:
> macOS Catalina(10.15.3)
编译环境:
> Python 3.8.0 (v3.8.0:fa919fdf25, Oct 14 2019, 10:23:27)
>
> [Clang 6.0 (clang-600.0.57)] on darwin
### 下载Xcode
从 App Store 上下载Xcode即可。
### 安装Python
从官网上下载:
https://www.python.org/downloads/
> 下载最新版 `python3` 就好,⚠️注意 `python3` 和 `python2` 不一样,本文全部使用 `python3` 。(注:macOS自带`python2`,但也不是最新版)
### 安装库
使用`pip3`,不要用`pip`。`pip3`安装`Python3`才读得到。
> `python3` 自带了`pip3`,不用在另外下载。
```
# Proj-1
$ pip3 install lxml
$ pip3 install requests
$ pip3 install selenium
```
# Proj-1:Python 图片爬虫
## 开始准备
我们在网上找了一下这个网站上有许多Bing的图片,很集中,很适合自动化操作。
### 爬取的内容
[https://bing.ioliu.cn/](https://bing.ioliu.cn/) 网站上的必应壁纸
然后我们在网上又找了一下(网上寻找资料的过程太冗长了,最近一段时间“爬虫”、“Python”都是热门话题,搜出来好多是广告。所以,具体的过程就不细说了),找到了我们需要用到的“Python 库”(理解为一些开箱即用的“工具包“就行了)
### 使用的库
就是一些别人写好的工具包啦,”不重复造轮子“是基本素养。
1. etree from lxml(分析HTML)
2. requests(获取数据)
## 分析网页
点开网页的检查器,我们能够发现一大堆“HTML源码”,这些HTML描述了网页的骨架、即网页基本长什么样子(具体的一些东西得让CSS(Cascading Style Sheets 层叠样式表)去描述)。
HTML,全称呢Hypertext Markup Language,超文本标记语言。使用的语法结构和XML(Extensible Markup Language可扩展标记语言)很相像(毕竟它们互相学习、一起发展),即是由一个一个标签组成的。
为了让计算机知道我们要的标签在哪里,我们通过标签的父子关系来确定标签的位置,即使用“XPath”来确定位置。
具体的Xpath内容便不细说了,我们只需要知道我们要的元素的Xpath是什么就行了,然而浏览器为我们提供了便利的方法:**`右键 ⇒ 'Copy' ⇒ 'Copy XPath'`**
那么我们正式开始对网页进行分析。
首先是页面。
### 页面
第1页:[https://bing.ioliu.cn/?p=1](https://bing.ioliu.cn/?p=1)
第2页:[https://bing.ioliu.cn/?p=2](https://bing.ioliu.cn/?p=2)
第3页:[https://bing.ioliu.cn/?p=3](https://bing.ioliu.cn/?p=3)
我们可以看到,翻页的方式是通过 `?p=` 给的参数,一共120页。
```python
for i in range(1,121):
urls = 'https://bing.ioliu.cn/?p={}'.format(i)
```
### 图片链接、名称及版权、日期
##### 版权信息是很重要的,我们在下载后,将版权信息加在文件名之后
这个时候我们可以引用一句数学老师们最讨厌的话:
> 由图知:
```python
xpath_1 = '/html/body/div[3]/div[1]/div/img'
url_1 = '/html/body/div[3]/div[1]/div/img/@src'
xpath_2 = '/html/body/div[3]/div[2]/div/img'
url_2 = '/html/body/div[3]/div[2]/div/img/@src'
xpath_3 = '/html/body/div[3]/div[3]/div/img'
url_3 = '/html/body/div[3]/div[3]/div/img/@src'
```
可以看出,第二个`
这时我们再引用一句学生们们最喜欢的话:
> 同理可得:
```python
xpath_of_name = '/html/body/div[3]/div/div/div[1]/h3/text()'
xpath_of_date = '/html/body/div[3]/div/div/div[1]/p[1]/em/text()'
```
------
## 开始CODE
终于到上代码的时间了!🎉
### 首先,我们来一点import:
```python
import requests # 获取文件
from lxml import etree # 分析HTML
import time # 用于暂停一段时间
import os # 调用系统功能
```
### 获取当前工作路径,用于保存文件:
```python
root = os.getcwd() + '/' # 这里加上’/‘是为了后面方便
```
> 手动储存log,我喜欢这么做,方便日后查看失败的请求
>```python
>logPath = root + 'log.txt'
>log = open(logPath, 'a') # 我用续写模式,也可也用'w'
># 开头写一些分隔符
>log.write('#############################################\n')#
>log.write(time.strftime('%Y-%m-%d %a. %H:%M:%S',time.localtime(time.time()))) # 写入时间
>log.write('#############################################\n')
>
>def logprint(text):
>print(text)
>log.write(text + '\n')
>```
### 主体代码
```python
for i in range(1, 121):
# 创建当前页面URL
url = 'https://bing.ioliu.cn/?p={}'.format(i)
# 获取页面
page = getPageHTML(url)
# 判断是不是timeout//函数抛出'timeout'
if page == 'timeout':
logprint('>>>>!!!!!!!BROKEN!!!!!!!\n>>>>{}\n>>>>{}\n>>>>!!!!!!!BROKEN!!!!!!!'.format(url, time.strftime('%Y-%m-%d %a. %H:%M:%S',time.localtime(time.time()))))
else:
# 获取页面信息
dataUrl = getInfoUrl(page) # get a string
dataName = getInfoName(page) # get a list
dataDate = getInfoDate(page) # get a list
#依次获取12张图片
for s in range(0, 12):
# 读取图片信息
imgUrl = dataUrl[s]
imgName = dataDate[s] + '_[' + dataName[s] + '].jpeg'
# 保存图片
logprint('>>>>获取 #第 {} 页__第 {} 张'.format(i, s))
saveImage(imgUrl=imgUrl, path = root + 'IMG/', imgName = imgName)
# 休息 5 秒
logprint('>>>>休息 5 秒')
time.sleep(5)
```
### 一些函数
```python
# MARK: - Get Page HTML
def getPageHTML(url, triedNum=0, sleepTime=5, tryNum=20):
logprint('>>>>正在访问: {}'.format(url))
# 获取页面
data = requests.get(url)
# 处理状态
statusCode = data.status_code
if not statusCode == 200:
data = 'timeout'
# 不要放弃,再试几次,我设置的20次,可以在参数设置
if triedNum <= tryNum:
logprint('>>>>休息 {} 秒'.format(sleepTime))
time.sleep(sleepTime)
logprint('>>>>重新访问: '+url+' : '+str(triedNum))
triedNum = triedNum + 1
getPageHTML(url=url, triedNum=triedNum, tryNum=tryNum)
else:
logprint('>>>>尝试 {} 次无效'.format(tryNum))
return data
```
```python
# MARK: Get Picture URL
def getInfoUrl(page):
logprint('>>>>正在获取URL信息')
data = page
selector = etree.HTML(data.text)
returnData = selector.xpath('/html/body/div[3]/div/div/img/@src')
return returnData
# MARK: Get Picture Name
def getInfoName(page):
logprint('>>>>正在获取NAME信息')
data = page
selector = etree.HTML(data.text)
returnData = selector.xpath('/html/body/div[3]/div/div/div[1]/h3/text()')
return returnData
# MARK: Get Picture Date
def getInfoDate(page):
logprint('>>>>正在获取DATE信息')
data = page
selector = etree.HTML(data.text)
returnData = selector.xpath('/html/body/div[3]/div/div/div[1]/p[1]/em/text()')
return returnData
######################
# 注意XPath,把递归的部分删去,etree 会自己递归,然后返回一个list
# 后面两个分开写了,这样清楚一些
```
```python
# MARK: - Save Image
def saveImage(imgUrl, path, imgName):
if not os.path.exists(path): # 判断文件夹是否已经存在
os.makedirs(path)
imgPath = path + imgName
if not os.path.exists(imgPath): # 判断文件是否已经存在
img = requests.get(imgUrl).content # 获取文件的二进制编码
file = open(imgPath, "wb") # 用二进制模式打开
file.write(img) # 直接写入二进制文件
logprint('>>>>file #' + imgName + ' written')
else:
logprint('>>>>file #' + imgName + ' already exists')
```
理论上,这就应该能跑了。
可是现实是残酷的。
仔细观察发现,copyright 里面竟然有个`/`。去访达里看看,会发现一个神奇的事情,
,访达怎么会支持这种东东!?
在`Terminal`里面`ls`看一下,它原来长这样`./bing:wallpapers.py`,再去访达里把文件命名为`:`,你会神奇的发现这是非法操作。
为了方便,于是我们干脆把正斜杠`/`换成反斜杠`\`,顺便把`©`换成`(c)`:
```python
name = dataDate[s] + '_[' + dataName[s] + '].jpeg'
# 处理名字里的不合法字符
imgName = ''
for x in name:
if not x == '/' and not x == '©':
imgName = imgName + x
elif x == '/':
imgName = imgName + '\\'
elif x == '©':
imgName = imgName + '(c)'
```
# Proj-2:爬取动态网页
由于没有找到其他特别好的网站,只好使用一个动画网站。**我们支持正版,保护作者权利。以下代码仅用于学习目的**
### 爬取网页
“http://www.mangabz.com/287bz/” 的其中几话。
## 分析网页
第一页是目录,是一张静态网页。
然而到了漫画页面是动态加载的。
对于动态页面,一般来说有两种处理方式:
1. 爬取网页后,加载有关 JavaScript 文件;
2. 动态加载完所有内容后,再爬取网页。
后者明显是简单方法,虽然是慢了一点点。
### 使用的库
1. etree from lxml(分析HTML)
2. requests(获取数据)
3. webdriver from selenium(网页自动化操作工具,可以直接调用浏览器,以达到自动加载的目的)
### 目录页面
我们需要获取每一话的“链接”、“名称”、“页数”。
```python
xpath_url = '/html/body/div[5]/div[2]/a/@href')
xpath_names = '/html/body/div[5]/div[2]/a/text()')
xpath_pagenums = '/html/body/div[5]/div[2]/a/span/text()')
```
### 漫画页面
我们需要取得当前`page`的“页数”、“名称”、和当前图片的“URL”
```python
xpath_img = '//*[@id="cp_image"]/@src'
xpath_pageNum = '//*[@id="lbcurrentpage"]/text()'
xpath_pageName = '/html/body/div[1]/div/div/p/text()'
```
每一张的翻页的实现:
第1页:http://www.mangabz.com/m21739/#ipg1
第2页:http://www.mangabz.com/m21739/#ipg2
第3页:http://www.mangabz.com/m21739/#ipg3
我们可以看到,翻页的方式是通过 `#ipg?` 给的参数,一共`chapterTotalPages`页。
```python
for currentPageIndex in range(chapterTotalPages):
currentPageURL = 'http://www.mangabz.com/' + chapterURL + '/#ipg{}'.format(currentPageIndex)
```
------
## 开始CODE
终于到上代码的时间了!🎉
首先,我们来一点import:
```python
import requests # 获取文件
from lxml import etree # 分析HTML
import time # 用于暂停一段时间
import random # 随机数生成
import os # 调用系统功能
from selenium import webdriver # 自动操作工具webdriver
```
#### 获取当前工作路径,用于保存文件:
```python
root = os.getcwd() + '/' # 这里加上’/‘是为了后面方便
if not os.path.exists(root + 'bilibili/'):
os.mkdir(root + 'bilibili/')
if not os.path.exists(root + 'bilibili/content/'):
os.mkdir(root + 'bilibili/content/')
```
> 手动储存log,我喜欢这么做,方便日后查看失败的请求
> ```python
> logPath = root + 'log.txt'
> log = open(logPath, 'a') # 我用续写模式,也可也用'w'
> # 开头写一些分隔符
> log.write('#############################################\n')#
> log.write(time.strftime('%Y-%m-%d %a. %H:%M:%S',time.localtime(time.time()))) # 写入时间
> log.write('#############################################\n')
>
> def logprint(text):
> print(text)
> log.write(text + '\n')
>
> #储存错误
> brokenLogPath = root + 'bilibili/bilibiliBrokenLog.txt'
> brokenLog = open(brokenLogPath, "a")
> brokenLog.write('\n')
> brokenLog.write('@@@@@@START@@@@@@\n')
> def saveBrokenLog(url, chapterNum=-1, pageNum=-1, chapterName=''):
> logprint('>>>>存入 bilibiliBrokenLog.txt')
> logprint('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
> brokenLog.write('--------------------------------------------------------------------------------\n')
> brokenLog.write('--------------------------------------------------------------------------------\n')
> if not chapterNum == -1 and not chapterName == '':
> brokenLog.writelines(
> '>>>>>>>> #' + str(chapterNum) + ' #' + chapterName)
> if not pageNum == -1:
> brokenLog.writelines('>>>>>>>> #'+str(pageNum))
> brokenLog.writelines('>>>>>>>> #' + url)
> brokenLog.write('--------------------------------------------------------------------------------\n')
> brokenLog.write('--------------------------------------------------------------------------------\n')
> brokenLog.write('\n')
> brokenLog.write('\n')
>
> #储存获取的每一页的数据
> pageLogPath = root + 'bilibili/bilibiliPageLog.txt'
> pageLog = open(pageLogPath, "w")
> pageLog.write('\n')
> pageLog.write('@@@@@@START@@@@@@\n')
> ```
#### 主体代码,主要的逻辑部分
“话” 我用 “chapter(章节)”来代替
```python
# 打开webdriver,这里用的是FireFox(也推荐使用Safari)
driver = webdriver.Firefox(executable_path='path/to/your/geckodriver')
# 开始
logprint('@@@@@@START@@@@@@')
# 获取目录里的全部页面信息,返回的是一个list嵌套的list
allChapter = getAllPages(driver=driver)
# 准备基础的URL
URL_b = 'http://www.mangabz.com/'
# 判断是否有返回
if allChapter == ['timeout']:
saveBrokenLog(url='none is got')
else:
# 获取每一话(chapter)
for ss in range(0, 5): # 象征性的只获取 5 个
currentChapter = allChapter[ss]
# 处理这一话的URL
chapterURLhref = currentChapter[2]
chapterURL = ''
# 要把多余的'/'删去,没有在获取的时候删是为了函数里的代码更清晰一点
for i in chapterURLhref:
if not i == '/':
chapterURL += i
# 获取其他信息
chapterTotalPages = currentChapter[3] # 总页数
chapterName = currentChapter[1] # 话名称
chapterNum = currentChapter[0] # 话的编号
# 获取每一个单页
for currentPageIndex in range(chapterTotalPages):
currentPageIndex += 1 # list是从0开始的,所以这里要转换一下
# 当前“页”的URL
currentPageURL = URL_b + chapterURL + '/#ipg{}'.format(currentPageIndex)
logprint('######## '+str(currentPageIndex)+' '+currentPageURL)
# 获取当前“页”的信息
info = getInfo(currentPageURL, driver)
currentImgURL = info[1]
currentImgNum = info[0]
currentImgName = info[2]
# 打印每一页的数据
logprint('>>>>当前章名: #' + currentImgName)
logprint('>>>>当前页数: #' + str(currentImgNum))
logprint('>>>>当前URL: #' + str(currentImgURL))
if currentImgURL == 'timeout':
logprint('>>>>获取页面失败')
saveBrokenLog(currentImgURL, chapterNum, currentPageIndex, currentImgName)
else:
# 储存路径的创立
chapterRootPath = root + 'bilibili/content/' + str(chapterNum) + '-' + currentImgName+'/'
if not os.path.exists(chapterRootPath):
os.mkdir(chapterRootPath)
logprint('>>>>章节路径: #{} 创建好了'.format(chapterRootPath))
# 判断是编号是否一致,以免错误的出现
if currentPageIndex == currentImgNum:
logprint('>>>>序号是一致的')
else:
logprint('>>>>序号不一致')
# 文件路径
fileName = str(chapterNum) + '-' + str(currentImgName) + '_p_' + str(currentPageIndex)+'.jpeg'
imgPath = chapterRootPath + fileName
# 是否已经存在,不要重复获取
if os.path.exists(imgPath):
logprint('>>>>file #{} already existed'.format(fileName))
else:
# 获取图片
saveImage(currentImgURL, imgPath, fileName)
# 下一话
logprint('--------------------------------------------------------------------------------')
logprint('--------------------------------------------------------------------------------')
logprint('######NEXT######')
logprint('--------------------------------------------------------------------------------')
# 结束了,退出
driver.close()
brokenLog.write('@@@@@@OVER@@@@@@')
logprint('@@@@@@OVER@@@@@@')
```
#### 一些函数
##### 获取页面
```python
def getPage(url, driver, tryNum=0):
print('>>>>正在访问: {}'.format(url))
# 这里我们用到了webdriver
driver.get(url)
# 等待动态加载,网速不好的可以等的时间长一点
logprint(">>>>睡 5 秒")
time.sleep(5)
data = driver.page_source
dataInfo = etree.HTML(data)
# 这里是判断是否是404,由于用了webdriver,手动判断会方便一点
is404 = dataInfo.xpath('/html/body/div[3]/img/@class')
logprint(">>>>得到 #{}".format(url))
if is404 == ['img-404']:
data = 'timeout'
# 尝试 20 次
if tryNum <= 20:
logprint('>>>>休息10s')
time.sleep(10)
logprint('>>>>重新访问: '+url+' : '+str(tryNum))
tryNum = tryNum + 1
getPage(url=url, driver=driver, tryNum=tryNum) # 这里有个迭代
else:
logprint('>>>>尝试20次无效')
return data # driver.page_source,或'timeout'(我全部使用字符串'timeout'来进行错误处理,方便一点)
```
##### 获取全部页面信息
```python
def getAllPages(driver):
url = 'http://www.mangabz.com/287bz/' # 写死的
data = getPage(url=url, driver=driver)
# 进行错误判断
if not data == 'timeout':
把数据交给etree
selector = etree.HTML(data)
获取信息
urls = selector.xpath('/html/body/div[5]/div[2]/a/@href')
names = selector.xpath('/html/body/div[5]/div[2]/a/text()')
pagenums = selector.xpath('/html/body/div[5]/div[2]/a/span/text()')
nums = []
returnData = []
# 处理页面编号,得把它过滤出来并从 str 改到 int
count = 0
for s in pagenums:
a = ''
count += 1
# 简单方法,硬上
for i in s:
if i == '1' or i == '2' or i == '3' or i == '4' or i == '5' or i == '6' or i == '7' or i == '8' or i == '9' or i == '0':
a += i
a = int(a)
nums.append(a)
for i in range(count + 1):
i = i - 1
pageLog.write('>>>>>>>>>>>>>>>>>>>>\n')
pageLog.write('####' + str(i+1)+names[i]+urls[i]+str(nums[i])+'\n')
pageLog.write('\n')
returnData.append([i + 1, names[i], urls[i], nums[i]])
# name is a string, url is a string, nums is a int which refers to how many pages this chapter got, the first one is the chapter's id
else:
returnData = ['timeout']
return(returnData) # 返回一个list,或'timeout'
```
##### 获取每一“页”的信息
```python
def getInfo(url, driver, tryNum=0):
logprint('>>>>正在获取页面信息')
data = getPage(url=url, driver=driver)
# 进行错误处理
if data == 'timeout':
logprint('data of getinfo is timeout')
imgURL = 'timeout'
pageNum = 404
pageName = 'timeout'
else:
# 把数据交给etree
selector = etree.HTML(data)
imgURL = selector.xpath('//*[@id="cp_image"]/@src')
# 如果是加载出了问题,图片还没有加载出来,不要气馁,再试几次
if imgURL == []:
if tryNum <= 20:
logprint('>>>>重新获取页面: '+url+' : '+str(tryNum))
tryNum = tryNum + 1
imgURL = 'timeout'
getInfo(url=url, driver=driver, tryNum=tryNum) # 迭代自己
else:
logprint('>>>>尝试 20 次无效')
imgURL = 'timeout'
pageNum = 404
pageName = 'timeout'
saveBrokenLog(url)
else:
imgURL = imgURL[0] # 把URL从 list 转为 str(感谢弱类型)
# 获取当前的页码
pageNum = selector.xpath('//*[@id="lbcurrentpage"]/text()')[0] # list 转 str
pageNum = int(pageNum) # str 转 int
pageName = selector.xpath('/html/body/div[1]/div/div/p/text()')[0]
# 把空白字符处理掉
pageName.replace('\s', '')
abcd = ''
for i in pageName:
if not i == '\t':
if not i == ' ':
abcd += i
pageName = abcd
#
logprint('>>>> #' + str(pageNum))
logprint('>>>> #' + pageName)
logprint('>>>> #' + imgURL)
return [pageNum, imgURL, pageName]
```
##### 获取图片
```python
def saveImage(imgUrl, path, name):
img = requests.get(imgUrl, headers=header)
img = img.content
file = open(path, "wb") # 二进制输入
file.write(img)
logprint('>>>>file #'+name + 'written>>>>>>>')
```
# Proj-3:批量处理获取的图片
好了,我们要打开Xcode了。
我们对图片进行分类和提高画质的处理。
创建一个命令行工具就好了。
### Swift 运行“命令行工具”
这段代码是通用的,所以对于我们这个程序可能有冗余的部分。
```swift
import Foundation
// MARK: ErroRs
/// This is a customized error enum. It has type of (.allGood), (.notFound), (.httpError)
enum ERRoR: Error {
case allGood
case notFound(String)
case httpError(Int, String)
}
// MARK: runCommand
/// This function will return the command's output, the state code and throw an ERRoR state
func runCommand(_ bin: String, isPrint: Bool = false, arguments: [String], runtime: Int = 1) throws -> (String, Int) {
let pipe = Pipe()
let file = pipe.fileHandleForReading
var launchPath = bin
if launchPath.first != "/" || launchPath != "/usr/bin/which" {
launchPath = try! runCommand("/usr/bin/which", arguments: [launchPath], runtime: 2).0
}
if launchPath.isEmpty || launchPath.first != "/" {
throw ERRoR.notFound("command not found")
} else {
if launchPath.last == "\n" {
launchPath = String(launchPath.dropLast())
}
let task = Process()
task.launchPath = launchPath
task.arguments = arguments
task.standardOutput = pipe
try! task.run()
task.waitUntilExit()
let data = file.readDataToEndOfFile()
if runtime == 1, isPrint {
print(String(data: data, encoding: String.Encoding.utf8)!)
}
var returnString = String(data: data, encoding: String.Encoding.utf8)!
if returnString.last == "\n" {
returnString = String(returnString.dropLast())
}
return (returnString, Int(task.terminationStatus))
}
}
```
### 主体代码
```swift
import Foundation
print("@@@@@@START@@@@@@")
// Basic Settings
let FManager = FileManager.default
//目录 #1: ./bilibili/content/
let rootPath = "./bilibili/content/"
let rootURL = URL(fileURLWithPath: rootPath)
let pianPathSet = try! FManager.contentsOfDirectory(atPath: rootURL.path)
// 第一次循环, ./bilibili/content/, 获取“篇”
for pianSubPath in pianPathSet {
if pianSubPath != ".DS_Store" { //排除 #系统文件
//目录 #2: ./bilibili/content/
let pianPath = rootPath + pianSubPath
let pianURL = URL(fileURLWithPath: pianPath)
let volPathSet = try! FManager.contentsOfDirectory(atPath: pianURL.path)
// 第二次循环,./bilibili/content/篇*, 获取“话”
for volSubPath in volPathSet {
if volSubPath != ".DS_Store" {
let volPath = pianPath + "/" + volSubPath
let volURL = URL(fileURLWithPath: volPath)
let chapterPathSet = try! FManager.contentsOfDirectory(atPath: volURL.path)
// 第三次循环, ./bilibili/content/篇*/话*, 获取"页"
for chapterSubPath in chapterPathSet {
if chapterSubPath != ".DS_Store" {
let chapterPath = volPath + "/" + chapterSubPath
let chapterURL = URL(fileURLWithPath: chapterPath)
var chapterNameS: String = ""
var chapterNameT: String = ""
var isRecordHua: Bool = false
//记录“话”
for i in chapterSubPath {
if i == "第", !isRecordHua {
isRecordHua = true
}
if isRecordHua {
chapterNameS += String(i)
//转化为简体
if i == "话" {
chapterNameT += "話"
} else {
chapterNameT += String(i)
}
}
if isRecordHua, i == "话" || i == "話" {
isRecordHua = false
break
}
}
let inpagePathSet = try! FManager.contentsOfDirectory(atPath: chapterURL.path)
// 第四次循环,./bilibili/content/篇*/话*/"页", 获取每一张图片
for pageIndex in 0 ..< inpagePathSet.count {
let inputPath = chapterPath + "/" + inpagePathSet[pageIndex]
// 输出目录
//加上“篇“
var outRootPath = "./bilibili/already/" + pianSubPath + "/"
if !FManager.fileExists(atPath: outRootPath) {
_ = try! runCommand("mkdir", arguments: ["\(outRootPath)"])
}
//加上”卷“
outRootPath += "/" + volSubPath
if !FManager.fileExists(atPath: outRootPath) {
_ = try! runCommand("mkdir", arguments: ["\(outRootPath)"])
}
//加上”话“
outRootPath += "/" + chapterSubPath
if !FManager.fileExists(atPath: outRootPath) {
_ = try! runCommand("mkdir", arguments: ["\(outRootPath)"])
}
//加上“页”
let outPath = outRootPath + "/" + "\(chapterNameS)_p\(pageIndex + 1).png" //简体
// 开始处理
print("########################################")
// 不要重复处理
if FManager.fileExists(atPath: outPath) {
print("##########FILE ALREADY EXISTED##########")
print(outPath)
} else if FManager.fileExists(atPath: outPathT) {
print("##########FILE ALREADY EXISTED##########")
print(outPath)
let exeNameChange = try! runCommand("mv", arguments: [outPathT, outPath]).1
if exeNameChange == 0 {
print("##########FILE NAME is CHANGED##########")
} else {
print("!!!!!!!!!!NAME CHANGE FAILED!!!!!!!!!!")
}
} else {
print(inputPath)
// 这里调用了一个开源软件
let exe = try! runCommand("/Users/HUi/bin/waifu2x", arguments: ["--type", "a", "--scale", "2", "--noise", "4", "--input", inputPath, "--output", outPath])
print(exe)
}
}
}
}
}
}
}
}
print("@@@@@@OVER@@@@@@")
```
> 代码重用到了一个“waifu2x”的开源软件,是Metal做的macOS版本的,原作是win专用的。
>
> 本次用到的:https://github.com/safx/waifu2x-metal(只用到了编译好的程序,没用用到代码)
>
> 原作:https://github.com/nagadomi/waifu2x
# 总结
我们着重研究了互联网爬虫以及数据处理的相关应用,是合法的应用,因为爬虫的应用同样可以造成危害。
1. 了解了互联网网页的基本架构,对我们眼前的绚丽网页有了更本质的了解;
2. 对数据进行处理的过程中,我们意识到科技、自动化带来的便利,也认识到其中可能存在的危害(比如侵害他人版权、导致服务器变慢)。
3. 使我们更加意识到,科技的发展是一把双刃剑,我们应当更好的利用科技来为人们服务,科技的最终目的是造福人类。作为使用者,应该健全法律意识,合理使用技术。作为开发者,应该频繁检查修理可能存在的漏洞,确保软件架构的安全完整性。作为政策制定的人,应该明确需求,合理制定相关法规。