问题:有数百万个网址(格式为:http://example.com/some_page),我需要将这些网址转换为以后可用于文件名的内容(许多操作系统不允许您使用在文件名中有一个冒号或破折号。)
到目前为止,我已经尝试过这个,希望我不会因为base64简单的编码/解码而使用键值数据库:
require 'base64'
p Base64.encode64('insert some REALLY long URL here') # would produce some random name to use as a filename
# I'd do Base64.decode64 to later to get back to the URL
问题在于URL越长,base64字符串就越长。这很糟糕,因为操作系统限制了文件名的长度。
我也尝试过secure_random,但问题是,a)随机性不能得到保证b)我必须使用一些数据库才能将随机字符串映射到URL。
如果有一些方案允许您输入字符串并将其转换为FIXED长度的字母数字字符,这可以用作文件名然后很容易地解码为原始字符串,那将是理想的。如果这样的事情不存在,那么解决这个问题的下一个最佳方法是什么呢?
答案 0 :(得分:1)
URL已经是文件路径和文件名,只有它前面有一个协议。因此,使用专门用于处理URL的工具并将其拆分为您需要的部分:
require 'uri'
uri = URI.parse('http://example.com/some_page')
uri.path # => "/some_page"
从/some_page
开始,很难准确地说出正在查看的内容。它可能是两个目录,或者一个目录和一个文件,所以它需要一些网站的先进知识才能肯定地说,但无论哪种方式,都有一些工具可以让它更容易使用:
uri_path = uri.path
File.dirname(uri_path) # => "/"
File.basename(uri_path) # => "some_page"
File.split(uri_path) # => ["/", "some_page"]
给出的示例并未透露dirname
,basename
和split
的工作原理,但您可以在File
文档中详细了解它们。而且,您想要对这些组件做什么取决于您。
也可以提取主机信息:
uri.host # => "example.com"
由于.
在文件名或路径中有效,因此可以保持名称不变。但是,了解主机名不一定是ASCII,这一点很重要。互联网不断变化,IDN标准允许您的操作系统可能不喜欢的二进制字符,或者您的大脑和眼睛,或您的客户可能不喜欢的二进制字符。因此,这就提出了如何在磁盘上正确构建指向文件的路径的问题。
虽然使用Base64对名称进行编码可能会有效,但您仍然有可能永远只需返回文件列表及其来源。搜索会很痛苦,非常可怕。
相反,我强烈建议构建一个用于将URL映射到文件路径的数据库。数据库甚至可以用于包含文件,或者您可以简单地将文件重命名为相关记录的row_ID。数据库还可以包含有关文件的元数据,例如文件类型,大小,首次检索文件时的日期/时间戳,更新时间,上次检查时间等等。数据库成为关于文件和磁盘上文件的中心知识点只是该信息的一部分。
您必须决定如何实现这一点,因为有许多方法可以将资源映射到文件,但尝试在磁盘上创建大量的站点/路径/资源文件层次结构基于拆分URL不能很好地扩展或与磁盘一起使用。
哪种类型的数据库最适合存储HTML内容?拥有数百万个HTML页面,这个数据库将是巨大的......
一个体面的?我不能说,因为我不知道你在做什么,但是如果你要保存页面,MySQL或PostgreSQL可以很容易地处理这个问题。如果没有,那么如果您只需要元数据,则键/值存储将起作用。如今,一百万行并不是那么多。一个更好的问题是,您需要多少磁盘空间,RAM,多少CPU以及网络带宽?
如果您正在进行分析或抓取和更新页面,那么每天处理数百万个页面会使一些主机不断地对数据库运行并检索页面,并且将涉及移动大量文本。 (当我负责编写一些财富500强公司的网站分析和编写代码并编写了数百个蜘蛛的代码时,我知道我们公司网络利用率最高,所以我对所遇到的问题有所了解。)
为什么存储数百万页?
许多HTTPd服务器支持ETag和各种其他标头,让您知道它是否知道自上次看到页面后是否发生了更改。 HEAD请求也可以提供帮助。在最坏的情况下,使用MD5来查看缓存页面和最近检索的远程页面是否匹配应该是足够的,方法是比较存储的MD5值并为新的值计算它。