感受 AI 的力量——利用 Cursor 自动生成 powershell 脚本下载 TheOldNewThing 博文

缘起

今天查资料的时候,偶然发现了一位国外网友镜像了 TheOleNewThing2003 年到 2019 年的博文,竟然有 5000 多篇(真是高产)。值得注意的是,微软官方博客中许多链接都已经失效了。为了防止这位网友的镜像链接也失效,我决定赶紧将这些内容下载保存下来。手动保存显然不现实,毕竟有 5000 多篇文章呢!所以,我决定写脚本来自动下载,这才是明智之举!如果是几年前,我肯定要亲自动手写脚本,不过如今,AI 这么强大,我无需再费力。幸运的是,我利用 Cursor 自动生成下载脚本的全过程,并对其进行了简单的修改,成功地将全部 5000 多篇文章下载并压缩存档,并按年月分类打包好了!不得不赞叹一句,AI 真是太强大了。

下载地址

所有文章已经按年压缩,感兴趣的朋友可以自行下载。

百度云盘:https://pan.baidu.com/s/1gGx7mvLsumbtzoQbatPsfw?pwd=dbqt 提取码: dbqt

gitee:

https://gitee.com/bianchengnan/my-blog/tree/master/download-the-old-new-thing-archive-blog-using-powershell-with-the-help-of-Cursor

注: 所有文章版权归原作者所有,我只是为了防止失联,转存一份。侵删!

下载

Q:

download url and save to disk and then parse inner urls and then save these urls to disk

A:

To download a URL, save it to disk, parse inner URLs, and then save these URLs to disk in PowerShell, you can use the Invoke-WebRequest cmdlet to download the webpage, Out-File cmdlet to save it to disk, and then use a regular expression to parse the inner URLs. Here is a simple example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Define the URL
$url = "http://example.com"

# Define the output file for the webpage
$outfile = "output.html"

# Define the output file for the inner URLs
$urlfile = "urls.txt"

# Download the webpage and save to disk
Invoke-WebRequest -Uri $url -OutFile $outfile

# Read the saved file
$content = Get-Content -Path $outfile

# Parse the inner URLs
$innerUrls = $content | Where-Object { $_ -match "(http|https)://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?" }

# Save the inner URLs to disk
$innerUrls | Out-File -FilePath $urlfile

This script will download the webpage, save it to output.html, read the saved file, parse the inner URLs, and then save these URLs to urls.txt. You can adjust the regular expression in the Where-Object cmdlet to match the URLs you are interested in.

画外音: 我发现解析出来的内部 urls 不太对,于是查看了原始网页中的链接形式,又对 Cursor 提出了进一步的要求,这次是用中文提的。

Q:

解析匹配 href="xxx" 模式的字符串。

A:

要在 PowerShell 中下载 URL,将其保存到磁盘,然后解析内部 URL,并将这些 URL 保存到磁盘,您可以使用 Invoke-WebRequest cmdlet 下载网页,使用 Out-File cmdlet 将其保存到磁盘,然后使用正则表达式解析内部 URL。以下是一个简单的示例:

1
2
3
4
5
6
7
# 省略 N 行

# 解析内部 URL
$innerUrls = $content | Where-Object { $_ -match 'href="([^"]*)"' }

# 保存内部 URL 到磁盘
$innerUrls | Out-File -FilePath $urlfile

此脚本将下载网页,将其保存到 output.html,读取保存的文件,解析内部 URL,然后将这些 URL 保存到 urls.txt。您可以调整 Where-Object cmdlet 中的正则表达式以匹配您感兴趣的 URL

画外音: 非常不错,可以记住上下文。

Q:

解析内部 url 的语句有问题,没有只保存 href="" 内部的内容

A:

对不起,我之前的回答中的正则表达式确实有误。我们应该使用一个捕获组来只获取 href="" 内部的内容。以下是修正后的代码:

1
2
3
4
5
6
7
# 省略 N 行

# 解析内部 URL
$innerUrls = $content | Select-String -Pattern 'href="([^"]*)"' -AllMatches | % { $_.Matches } | % { $_.Groups[1].Value }

# 保存内部 URL 到磁盘
$innerUrls | Out-File -FilePath $urlfile

这段脚本将下载网页,将其保存到 output.html,读取保存的文件,解析内部 URL,然后将这些 URL 保存到 urls.txtSelect-String cmdlet 中的正则表达式已经被修改,现在它只会匹配 href="" 内部的内容。

画外音: 看了生成的内容,已经无限接近最终想要的结果了,但是没想到居然写了 5000 多篇文章,手动拼接网址还是需要操作一会的。于是继续优化脚本。

Q:

需要在解析出来的 url 前加上前缀 https://bytepointer.com/resources/old_new_thing/ 再保存

A:

在解析出来的 URL 前加上前缀并保存的 PowerShell 代码如下:

1
2
3
4
5
6
7
8
# 省略 N 行

# 添加前缀
$prefix = "https://bytepointer.com/resources/old_new_thing/"
$innerUrls = $innerUrls | ForEach-Object { $prefix + $_ }

# 保存内部 URL 到磁盘
$innerUrls | Out-File -FilePath $urlfile

这段脚本将下载网页,将其保存到 output.html,读取保存的文件,解析内部 URL,然后在每个 URL 前添加前缀,最后将这些 URL 保存到 urls.txt

至此,已经把需要下载的 url 保存到了 urls.txt。接下来就要写脚本下载这些 url 了。最终载脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 定义 URL
$url = "https://bytepointer.com/resources/old_new_thing/index.htm"

# 定义网页的输出文件
$outfile = "output.html"

# 定义内部 URL 的输出文件
$urlfile = "urls.txt"

# 下载网页并保存到磁盘
Invoke-WebRequest -Uri $url -OutFile $outfile

# 读取保存的文件
$content = Get-Content -Path $outfile

# 解析内部 URL
$innerUrls = $content | Select-String -Pattern 'href="([^"]*)"' -AllMatches | % { $_.Matches } | % { $_.Groups[1].Value }

# 添加前缀
$prefix = "https://bytepointer.com/resources/old_new_thing/"
$innerUrls = $innerUrls | ForEach-Object { $prefix + $_ }

# 保存内部 URL 到磁盘
$innerUrls | Out-File -FilePath $urlfile

解析 url 并下载

Q:

遍历 urls.txt 并下载里面的每个 url,如果下载失败需要有提示,并且记录下载的位置。

A:

PowerShell 中,你可以使用 Invoke-WebRequest cmdlet 来下载 URL,并使用 try/catch 语句来处理可能的错误。以下是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 定义 URL 文件
$urlfile = "urls.txt"

# 读取 URL 文件
$urls = Get-Content -Path $urlfile

# 遍历每个 URL
foreach ($url in $urls) {
# 定义输出文件
$outfile = "downloaded_" + [System.IO.Path]::GetFileName($url)

try {
# 下载 URL 并保存到磁盘
Invoke-WebRequest -Uri $url -OutFile $outfile

# 打印下载的位置
Write-Output "Downloaded $url to $outfile"
} catch {
# 如果下载失败,打印错误信息
Write-Output "Failed to download $url: $_"
}
}

这段脚本将读取 urls.txt 文件中的每个 URL,然后尝试下载每个 URL 并保存到磁盘。如果下载失败,它将打印一个错误信息。下载成功的文件将被保存为 "downloaded_" 加上原始文件名。

画外音:

  1. 最后面的 Write-Output "Failed to download $url: $_" 会报错,需要在 $url: 之间加空格。
  2. 保存的文件名我去掉了 downloaded_ 前缀,而是保存到了 d:/downloaded/ 目录下。

因为文件数量太多,全部放到一个目录下会比较乱,于是想着按年月进行分组整理。

按年月分组

Q:

遍历文件夹中的文件,文件名前 8 个字符是年月日,比如 20030722_001_why_do_you_have_to_click_the_start_button_to_shut_down.html。从中提取出年份,月份,并且根据年份创建文件夹,然后根据月份创建子文件夹,并把对应的文件放到新建的文件夹中。

A:

这是一个 PowerShell 脚本的示例,它可以遍历文件夹中的文件,提取文件名前 8 个字符作为年份和月份,然后根据年份创建文件夹,根据月份创建子文件夹,并将对应的文件移动到新建的文件夹中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$sourceDir = "C:\path\to\your\source\directory" # 源文件夹路径

$destDir = "C:\path\to\your\destination\directory" # 目标文件夹路径

Get-ChildItem $sourceDir -File | ForEach-Object {
$year = $_.Name.Substring(0, 4) # 提取年份
$month = $_.Name.Substring(4, 2) # 提取月份
$newDir = Join-Path -Path $destDir -ChildPath $year -AdditionalChildPath $month # 新文件夹路径

if (!(Test-Path $newDir)) { # 如果文件夹不存在,则创建
New-Item -ItemType Directory -Path $newDir | Out-Null
}
Move-Item -Path $_.FullName -Destination $newDir # 移动文件到新文件夹
}

请将 $sourceDir$destDir 替换为你的实际路径。这个脚本会遍历 $sourceDir 中的所有文件,提取文件名前 4 个字符作为年份,接着的 2 个字符作为月份,然后在 $destDir 中创建一个以年份命名的新文件夹,再在该文件夹下创建以月份命名的子文件夹,并将文件移动到新文件夹中。如果新文件夹已经存在,它将不会再次创建。

画外音: -AdditionalChildPath 好像不是一个合法的选项,是 AI 自己臆想出来的。于是手动修改代码如下:

$newDir = Join-Path -Path $destDir -ChildPath $year

$newDir = Join-Path -Path $newDir -ChildPath $month

压缩

Q:

遍历文件夹,并压缩

A:

你可以使用 PowerShellCompress-Archive 命令来遍历文件夹并压缩文件。以下是一个示例:

1
2
3
4
5
6
7
8
9
$sourceDir = "C:\path\to\your\source\directory" # 源文件夹路径
$destDir = "C:\path\to\your\destination\directory" # 目标文件夹路径

Get-ChildItem $sourceDir -Recurse | ForEach-Object {
if ($_.PSIsContainer) {
$zipFilePath = Join-Path -Path $destDir -ChildPath ($_.Name + ".zip") # 压缩文件路径
Compress-Archive -Path $_.FullName -DestinationPath $zipFilePath # 压缩文件夹
}
}

请将 $sourceDir$destDir 替换为你的实际路径。这个脚本会遍历 $sourceDir 中的所有文件和文件夹,如果是文件夹,就将其压缩为 .zip 文件,并保存到 $destDir 中。

画外音: 实际上我并不需要递归处理,去掉 -Recurse 选项即可。

总结

整个过程很舒服,基本上没写一行代码,只是做了一些改动及细节微调。就把整个功能实现了。整个过程不到 20 分钟。

关于 Cursor 的用法,也很简单,网上随便一搜就能搜到。ctrl+L 即可开启魔法!

BianChengNan wechat
扫描左侧二维码关注公众号,扫描右侧二维码加我个人微信:)
0%