关于 URL 去重的想法

2015-03-01 16:23:02 +08:00
 chuhades

最近遇到了这个问题。目前的方案是,提取 url 的 请求方法|协议|域名|一级目录|目录深度|尾部特征|QUERY|DATA 作为特征,md5(特征) 作为返回值。
可以判断如下这种:
http://www.yigeshop.cn/index.php/home/shop_list/9
http://www.yigeshop.cn/index.php/home/shop_list/16
但对于 http://www.yigeshop.cn/index.php/home/shop_details/24,算法认为它与上面两个相同。
各位有什么好的解决方案么?

贴上渣渣算法:
```
def hash(self):
"""
URL 去重
:return: hash
:rtype: int
"""
# 请求方法|协议|域名|一级目录|目录深度|尾部特征|QUERY|DATA
# http://a.com/p1/p2/p3/f.php?a=1&b=2&c
# GET|http|a.com|p1|4|php|abc|

first_dir = self.__parsed.path.split("/")[1] \
        if len(self.__parsed.path.split("/")) > 1 else ""
    depth = str(self.__parsed.path.count("/")) \
        if self.__parsed.path.count("/") else "1"
    suffix = self.__parsed.path.split("/")[-1].split(".")[-1] \
        if "." in self.__parsed.path.split("/")[-1] else ""
    query = "".join(sorted(self.query.keys()))
    data = "".join(sorted(self.__data.keys()))

    feather = "|".join((
        self.__method,
        self.__parsed.scheme,
        self.__parsed.netloc,
        first_dir,
        depth,
        suffix,
        query,
        data
    ))

    hash_ = int(md5(feather.encode()).hexdigest(), 16)

    return hash_
5388 次点击
所在节点    Python
21 条回复
ruoyu0088
2015-03-01 16:25:44 +08:00
把你的程序提取的特征贴出来看看。
ruoyu0088
2015-03-01 16:28:01 +08:00
难道不应该用urlparse模块吗?
binux
2015-03-01 16:28:10 +08:00
url 本身有什么问题吗?
chuhades
2015-03-01 16:30:06 +08:00
@ruoyu0088 http://www.yigeshop.cn/index.php/home/shop_list/9 => GET|http|www.yigeshop.cn|index.php|4|||

http://www.yigeshop.cn/index.php/home/shop_details/24 => GET|http|www.yigeshop.cn|index.php|4|||

因为算法不够好,两者的特征是一样的。有什么建议么?
chuhades
2015-03-01 16:31:58 +08:00
@ruoyu0088 urlparse 不够强啊,http://a.com/1.php?a=1&b=2 http://a.com/1.php?b=2&a=1 这两个其实是一样的,或者http://a.com/a/b/c/1,http://a.com/a/b/c/2 这两个也是一样的。目标正式去重这些
chuhades
2015-03-01 16:32:27 +08:00
@binux 如4L,url rewrite
sumhat
2015-03-01 16:37:31 +08:00
抽象化必然损失信息,不用原始URL做比较一定会有冲突,没什么解决方案
lk09364
2015-03-01 16:37:56 +08:00
- http://a.com/a/b/c/1
- http://a.com/a/b/c/2
一般网站上这两个URL不是一样的吧。
chuhades
2015-03-01 16:40:35 +08:00
@lk09364 就个人的项目而言,如果我爬虫爬到了http://a.com/a/b/c/1-10000 1w个链接,我希望只输出一个就好,因为他们后端调用的应该是一样的,不同的知识参数
chuhades
2015-03-01 16:40:44 +08:00
@chuhades 只是
binux
2015-03-01 16:41:31 +08:00
@chuhades 你这是和网站相关的

http://a.com/1.php?a=1&b=2
http://a.com/1.php?b=2&a=1

对于标准来说,它就是不一样的

如果你非说它是一样的,把这个『一样』的规则写出来,用机器能懂的语言。
如果不行,那就是你写错了。
ruoyu0088
2015-03-01 16:43:28 +08:00
这样看你的URL相同的定义,例如如果忽略路径中最后一个是数字和所有的参数的话,那么这样也许可以:

import urlparse
from os import path

url = "http://www.yigeshop.cn/index.php/home/shop_list/9?a=1&b=2&c"

r = urlparse.urlparse(url)
url_path = r.path
if path.basename(url_path).isdigit():
url_path = path.dirname(url_path)

url = urlparse.urlunparse([r.scheme, r.netloc, url_path, "", "", ""])
print url
lk09364
2015-03-01 16:51:06 +08:00
@chuhades 就你给出的例子而言, http://a.com/a/b/c/1 可以无视的部分是最后的数字,那就直接把最后的数字删除掉就可以做比对了啊?

而就第二个例子,即
- http://a.com/1.php?a=1&b=2
- http://a.com/1.php?b=2&a=1
这个而言,你认为他们是一样的,所以可以把参数部分提出来,
?b=2&a=1
按field name 排序一下就可以了吧。
chuhades
2015-03-01 16:52:41 +08:00
@ruoyu0088 感谢,但是和我的需求还是不大一致。其实转换个说法,相当于怎么从一个url(rewrite)中提取出参数名称?
例如 http://www.yigeshop.cn/index.php/home/shop_list/9,参数就应该是9这部分,不知道能不能理解我的意思。。
chuhades
2015-03-01 16:54:03 +08:00
@lk09364 是的 我的代码也是这么写的,但是需求如题目,按已有的规则:
http://www.yigeshop.cn/index.php/home/shop_list/16、 http://www.yigeshop.cn/index.php/home/shop_details/24 会被判断成相同的url
lk09364
2015-03-01 17:07:01 +08:00
@chuhades
> 请求方法|协议|域名|一级目录|目录深度|尾部特征|QUERY|DATA
不,根据这个解释,hash中二/三/四级目录的名称不见了。

我认为你可以先把url 分作2个部分……
- http://www.yigeshop.cn/index.php/home/shop_list/9
- ?a=1&b=2&c

之后再作处理。
chuhades
2015-03-01 17:15:21 +08:00
@lk09364 是的,我就是讲参数和path 分离的,但是很多url做了rewrite 或者pathinfo,如下:
http://a.com/p1/p2/a/1/b/2 ,这样的就很蛋疼,对于这种,只想出用一级目录,目录深度,尾部特征来做判断。但是可能会有漏报,比如题目中描述的 http://www.yigeshop.cn/index.php/home/shop_list/16、 http://www.yigeshop.cn/index.php/home/shop_details/24会被判断成相同的url
lk09364
2015-03-01 17:24:50 +08:00
@chuhades 不只是一个站台吗?『很多url』
电脑不知道什么url 在你的定义里是『一样』,也不知道什么才叫『不一样』。
我也不知道。对此,我提出如下几个办法:
- 人手写case,对应不同网站/页面的rewrite rules。
- 机器学习[?],按网页内容判断url 是否『一样』,再分析网站url 的异同。
- 黑进对方伺服器,直接把网站资料拖下来。
chuhades
2015-03-01 17:26:30 +08:00
@lk09364 目前的项目就是扫描器,所以不可能针对每个站点自己去制定规则 : (
akira
2015-03-02 15:01:27 +08:00
@chuhades 有个大概的思路,不保证一定可行,
针对你的需求,可以假设参数一定是数字.
先全部url地址抓下来,如果某url最后参数是数字且生成对应的正则可以匹配多个url,则可视为这些url是一样的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/173756

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX