使用ruby提取《潮州音》网站上的mp3文件

  • A+
所属分类:ruby 技巧

使用ruby提取《潮州音》网站上的mp3文件

潮州音网站地址http://www.chaozhouyin.com/hua

找地址规则

  1. 登陆到潮州音网站后,我们可以发现分成了内容分布在“日常用语”,“名胜古迹”,“动物植物”,“方言俗语”这几个模块上。而“日常用语”又分布到了12个分页,“动物植物”分布到3个分页其它两类只有1个单独页面。
  2. 我们尝试点击不同的模块以及分页,可以发现:
    “日常用语”模块地址http://www.chaozhouyin.com/hua/aWlnlGVkaGM
    第一页地址http://www.chaozhouyin.com/hua/aWlnlGVkaGM
    第二页地址http://www.chaozhouyin.com/hua/aWlnlGVkaGM-p-2
  3. 猜测页码地址规则如下:
    主模块地址 (页码数等于1)
    主模块地址 + "-p-" + 页码 (页码数大于1)
  4. 利用上面的规则。我们先定义一个散列表来保存主模块地址以及页码数等信息,代码如下:
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!!!!!!!!!"
百分购

发表评论

您必须才能发表评论!