- A+
使用ruby提取《潮州音》网站上的mp3文件
潮州音网站地址http://www.chaozhouyin.com/hua
找地址规则
- 登陆到潮州音网站后,我们可以发现分成了内容分布在“日常用语”,“名胜古迹”,“动物植物”,“方言俗语”这几个模块上。而“日常用语”又分布到了12个分页,“动物植物”分布到3个分页其它两类只有1个单独页面。
- 我们尝试点击不同的模块以及分页,可以发现:
“日常用语”模块地址http://www.chaozhouyin.com/hua/aWlnlGVkaGM
第一页地址http://www.chaozhouyin.com/hua/aWlnlGVkaGM
第二页地址http://www.chaozhouyin.com/hua/aWlnlGVkaGM-p-2
- 猜测页码地址规则如下:
主模块地址 (页码数等于1)
主模块地址 + "-p-" + 页码 (页码数大于1)
- 利用上面的规则。我们先定义一个散列表来保存主模块地址以及页码数等信息,代码如下:
pages = {
"http://www.chaozhouyin.com/hua/aWlnlGVkaGM" => [:日常用语, 12], #日常用语12页
"http://www.chaozhouyin.com/hua/aWlnlGVkaGQ" => [:名胜古迹, 1], #名胜古迹1页
"http://www.chaozhouyin.com/hua/aWlnlGVkaGU" => [:动物植物 ,3], #动物植物3页
"http://www.chaozhouyin.com/hua/aWlnlGVkaWY" => [:方言俗语, 1] #方言俗语1页
}
尝试下载单独的页面
利用地址规则再使用ruby可以很方便的下载所有页面到本地。这里我把页面下载到当前路径的html目录下。代码如下:
# 如果当前没有html目录,则创建html目录
Dir.mkdir("./html") if !File::directory?("./html")
# 将所有子页面下载到当前路径的html目录下
pages.each do |website, val|
pagenum = val[1]
pagenum.times do |i|
# 按地址规则生成页面的地址realwebsite
realwebsite = website + (i>0 ? "-p-#{i+1}" : "")
# 提取页面的名字,即最后一个/后面的字符串
pagename = realwebsite[realwebsite.rindex('/')+1, realwebsite.length-1]
filename = "./html/#{pagename}.html"
if !File::exists? filename
# 将页面数据保存到本地filename
File.open(filename, "wb") do |f|
f.write open(realwebsite).read
end
end
end
end
观察html文件
使用notepad++等文本编辑工具,查看下载下来的任意几个html文件。发现如下内容:
<a href="javascript:void(null);" onclick="javascript:play('00000138_00000116.mp3', 2);">
<h4>拧,扭,绞</h4>
<span>捘,例如:捘到我过痛(拧得我很疼)|行了捘下捘(走起路来一拧一扭的)|件衫捘一下(衣服绞一下)。</span> </a>
以及以下内容:
<a href="javascript:void(null);" onclick="javascript:play('00000272_00000305.mp3', 2);">
<h4>我</h4>
</a>
可以看出相关mp3数据在<a></a>
标签中,所以我们可以根据上面两种内容格式来进行提取。代码如下:
mp3List = {} #用来保存所有的MP3信息
# 找出所有页面的MP3文件名,以及h4标题内容,并且存放到mp3List中
pages.each do |website, val|
categoryname = val[0]
pagenum = val[1]
mp3List[categoryname] = {} #按不同模块归类
count = 0
pagenum.times do |i|
realwebsite = website + (i>0 ? "-p-#{i+1}" : "")
pagename = realwebsite[realwebsite.rindex('/')+1, realwebsite.length-1]
filename = "./html/#{pagename}.html"
if File::exists? filename
html = File.read filename
html.each_line do |line|
line.encode!('UTF-8', 'UTF-8', :invalid => :replace)
if /<a.*?javascript:play\('(.*?)'/ =~ line
mp3List[categoryname][count] = {:mp3 => $1}
elsif %r|<h4>(.*?)</h4>| =~ line
if !mp3List[categoryname][count].nil?
mp3List[categoryname][count][:h4] = $1.gsub(/\//, '_') if mp3List[categoryname][count][:h4].nil?
end
elsif %r|<span>(.*?)</span>.*</a>| =~ line
if !mp3List[categoryname][count].nil?
mp3List[categoryname][count][:span] = $1 if mp3List[categoryname][count][:span].nil?
count = count + 1
end
elsif %r|</a>| =~ line
count = count + 1 if !mp3List[categoryname][count].nil?
end
end
end
end
p [categoryname, pagenum, count]
end
下载mp3文件
通过上面的操作,我们把所有的MP3信息存放到了mp3List中,虽然有文件名,但是缺少了文件在网络上的具体地址。所以我们可以尝试在潮州音网站上尝试播放任意一个mp3。然后通过F12快捷键打开浏览器的开发者工具。点击到Network选项卡上,查看正在播放的mp3文件网络地址,并且拷贝出来。
地址大致如下:http://www.chaozhouyin.com/common/upload/sentencesound/00006335_00007145.mp3
地址规则如下:http://www.chaozhouyin.com/common/upload/sentencesound/ + MP3文件名
使用如下代码进行下载:
# 如果当前没有mp3目录,则创建mp3目录
Dir.mkdir("./mp3") if !File::directory?("./mp3")
# 下载所有的mp3文件到MP3目录的对应分类下
mp3List.each do |categoryname, val|
# 按模块划分路径
filepath = "./mp3/#{categoryname}"
# 如果模块路径还不存在,则进行创建
Dir.mkdir(filepath) if !File::directory?(filepath)
cnt = 0
val.each do |k, mp3info|
open("http://www.chaozhouyin.com/common/upload/sentencesound/#{mp3info[:mp3]}") do |fin|
puts "Downloading name: #{mp3info[:mp3]}"
open("#{filepath}/#{cnt+=1}_#{mp3info[:h4]}.mp3","wb") do |fout|
fout.write fin.read
end
end
end
end
完整代码
require "open-uri"
pages = {
"http://www.chaozhouyin.com/hua/aWlnlGVkaGM" => [:日常用语, 12], #日常用语12页
"http://www.chaozhouyin.com/hua/aWlnlGVkaGQ" => [:名胜古迹, 1], #名胜古迹1页
"http://www.chaozhouyin.com/hua/aWlnlGVkaGU" => [:动物植物 ,3], #动物植物3页
"http://www.chaozhouyin.com/hua/aWlnlGVkaWY" => [:方言俗语, 1] #方言俗语1页
}
# 如果当前没有html目录,则创建html目录
Dir.mkdir("./html") if !File::directory?("./html")
# 将所有子页面下载到当前路径的html目录下
pages.each do |website, val|
pagenum = val[1]
pagenum.times do |i|
# 按地址规则生成页面的地址realwebsite
realwebsite = website + (i>0 ? "-p-#{i+1}" : "")
# 提取页面的名字,即最后一个/后面的字符串
pagename = realwebsite[realwebsite.rindex('/')+1, realwebsite.length-1]
filename = "./html/#{pagename}.html"
if !File::exists? filename
# 将页面数据保存到本地filename
File.open(filename, "wb") do |f|
f.write open(realwebsite).read
end
end
end
end
mp3List = {} #用来保存所有的MP3信息
# 找出所有页面的MP3文件名,以及h4标题内容,并且存放到mp3List中
pages.each do |website, val|
categoryname = val[0]
pagenum = val[1]
mp3List[categoryname] = {} #按不同模块归类
count = 0
pagenum.times do |i|
realwebsite = website + (i>0 ? "-p-#{i+1}" : "")
pagename = realwebsite[realwebsite.rindex('/')+1, realwebsite.length-1]
filename = "./html/#{pagename}.html"
if File::exists? filename
html = File.read filename
html.each_line do |line|
line.encode!('UTF-8', 'UTF-8', :invalid => :replace)
if /<a.*?javascript:play\('(.*?)'/ =~ line
mp3List[categoryname][count] = {:mp3 => $1}
elsif %r|<h4>(.*?)</h4>| =~ line
if !mp3List[categoryname][count].nil?
mp3List[categoryname][count][:h4] = $1.gsub(/\//, '_') if mp3List[categoryname][count][:h4].nil?
end
elsif %r|<span>(.*?)</span>.*</a>| =~ line
if !mp3List[categoryname][count].nil?
mp3List[categoryname][count][:span] = $1 if mp3List[categoryname][count][:span].nil?
count = count + 1
end
elsif %r|</a>| =~ line
count = count + 1 if !mp3List[categoryname][count].nil?
end
end
end
end
p [categoryname, pagenum, count]
end
# 如果当前没有mp3目录,则创建mp3目录
Dir.mkdir("./mp3") if !File::directory?("./mp3")
# 下载所有的mp3文件到MP3目录的对应分类下
mp3List.each do |categoryname, val|
filepath = "./mp3/#{categoryname}"
Dir.mkdir(filepath) if !File::directory?(filepath)
cnt = 0
val.each do |k, mp3info|
open("http://www.chaozhouyin.com/common/upload/sentencesound/#{mp3info[:mp3]}") do |fin|
puts "Downloading name: #{mp3info[:mp3]}"
open("#{filepath}/#{cnt+=1}_#{mp3info[:h4]}.mp3","wb") do |fout|
fout.write fin.read
end
end
end
end
p "finished!!!!!!!!!"