Work the Shell - 分析您的搜索关键词
上个月,我们开始探索如何使用 shell 脚本从 Web 服务器日志中提取和分析 HTTP_REFERER 值,并识别人们用来找到您页面的最常用词语和短语。听起来很有用,不是吗?
问题是,这个脚本比最初看起来更微妙。上个月,我们以以下 shell 脚本结束
#!/bin/sh ACCESSLOG="/var/logs/httpd.logs/access_log" grep 'google.com/search' $ACCESSLOG | \ awk '{print $11}' | \ cut -d\? -f2 | cut -d\& -f1 | \ sed 's/+/ /g;s/%22/"/g;s/q=//' | \ sort | \ uniq -c | \ sort -rn | \ head -5
当我运行它时,我看到的是这样
$ sh google-searches.sh 94 hl=en 18 client=safari 6 client=firefox-a 4 sourceid=navclient 4 client=opera
这很奇怪,因为它不是搜索词,而是包含在来自 Google 等网站的搜索字符串中的其他变量(hl=en表示您已将搜索限制为仅限英语网站,client=safari将用户的 Web 浏览器标识为 Apple 的 Safari 等等)。
当我们查看前十个匹配项而不是仅查看前五个时,问题就显现出来了
$ sh google-searches.sh | head -10 94 hl=en 18 client=safari 6 client=firefox-a 4 sourceid=navclient 4 client=opera 3 wicked cool scripts 3 hl=zh-CN 2 num=100 2 hs=wNy 2 barbara nelson%2Bpurses
啊,所以我们可以看到这里有两个有效的搜索,一个用于“wicked cool scripts”,一个用于“Barbara nelson%2Bpurses”。不确定后者是什么,但看到它很有用也很重要。幸运的是,筛选掉虚假匹配项就像使用 grep 删除包含等号的字段一样简单grep -v '='.
但是,与其将它放在脚本中长管道的末尾,不如将其放在 sed 调用之后,以便在管道中尽快去除虚假结果,从而加快整个脚本的速度。现在它看起来像这样
grep 'google.com/search' $ACCESSLOG | \ awk '{print $11}' | \ cut -d\? -f2 | cut -d\& -f1 | \ sed 's/+/ /g;s/%22/"/g;s/q=//' | \ grep -v '=' | \ sort | \ uniq -c | \ sort -rn
请注意,sed 语句本身会去除搜索的 name= 部分(q=),这样它就不会在新 grep 语句中被错误地匹配。
现在我们得到了想要的结果
$ sh google-searches.sh | head -10 3 wicked cool scripts 2 barbara nelson%2Bpurses 1 wsj%20password 1 why did animal kingdom introduce expedition everest 1 what makes a great speaker%3F 1 university of phoenix center of writing excellence 1 ubuntu x problem 1 triboot osx ubuntu ydl 1 the best dvd players 1 symbol html heart
这个网站的流量不大,所以让我们针对我流量更大的 AskDaveTaylor.com 网站运行相同的脚本。结果更有趣
$ sh google-searches.sh | head -10 5 standalone player 4 psp help 4 create a myspace 4 Documents and Settings" 4 %24NtUninstall 3 view myspace accounts that are set to private 3 i cant hear music on runescape 2 transfer files to psp 2 sync v3 motorola mac 2 running unix in windows xp
有趣得多。哦,如果您想知道您正在探索多少次搜索,只需对脚本进行另一个简单的调整,调用 wc 即可
$ sh google-searches.sh | wc -l 501
因此,在 501 次搜索中,最常见的搜索是“standalone player”,仅占 500 次搜索中的 5 次,即我的搜索流量的 1%。
在本月结束这个脚本之前,还有最后一步:让我们摆脱从用户 Web 浏览器的原始 URL 编码中遗留下来的奇怪字符。我在说什么? %24,Documents and Settings 中的右双引号,以及之前搜索 purses 中的 %2B。
您可以找出所有映射并进行相应的转换,但我懒得在一天结束时这样做,而是简单地找到所有 %xx 序列并将它们替换为单个空格。
这听起来很困难,但对于 sed 来说这是一项完美的工作,因为它允许您进行模式匹配,然后用您想要的任何其他内容替换匹配的材料。这就是我将要做的
sed 's/%[0-9a-fA-F][0-9a-fA-F]/ /g'
让我们仔细看看这个,然后再惊慌失措。用方括号分隔的集合在正则表达式术语中是一个集合,因此 [0-9] 将匹配 0、1、2、3、4、5、6、7、8、9 或 0 中的任何一个。事实证明,URL 编码使用十六进制,因此这些值不仅可以是 0-9,还可以是 A、B、C、D、E 和 F,大写或小写字母 - 因此模式中包含 0-9 和 a-f 和 A-F。 总体模式形式是 %,后跟这些可能值中的任何一个,然后再次跟这些可能值中的任何一个。现在您可以看到完整的模式了。
最后,在我们彻底完成此操作之前,请注意 sed 语句中更大的结构是 s/old/new/g,它在整行中将 old 替换为 new,无论它出现一次还是 15 次。
但是,我们还没有完全完成,因为我们还需要去除多余的双引号。同样,这很容易添加到 sed 语句中
sed 's/%[0-9a-fA-F][0-9a-fA-F]/ /g;s/"//g'
这是最终脚本
grep 'google.com/search' $ACCESSLOG | \ awk '{print $11}' | \ cut -d\? -f2 | cut -d\& -f1 | \ sed 's/+/ /g;s/%22/"/g;s/q=//' | \ sed 's/%[0-9a-fA-F][0-9a-fA-F]/ /g;s/"//g' | \ grep -v '=' | sort | uniq -c | sort -rn
以及最终结果
$ sh google-searches.sh | head -15 6 NtUninstall 5 standalone player 4 psp music 4 psp help 4 creat a myspace 4 Documents and Settings 3 view myspace accounts that are set to private 3 i cant hear music on runescape 2 transfer files to psp 2 sync v3 motorola mac 2 running unix in windows xp 2 rss feed reader shell 2 reinstall windows xp hp 2 psp transfer music 2 psp internet
请注意,一旦我们删除了多余的材料,事情的组织方式会略有不同(例如,在这里您可以看到 psp music 是最热门的搜索之一,但之前我们有 psp music 的不同变体,并且它没有成为热门搜索值)。
好了,对 Apache 日志文件的折磨就到此为止。让我们总结一下,在下一专栏中我们将转向完全不同的内容!有什么建议吗?请通过电子邮件发送给我!
Dave Taylor 是 UNIX 领域的 26 年资深人士,The Elm Mail System 的创建者,最近还是畅销书 Wicked Cool Shell Scripts 和 Teach Yourself Unix in 24 Hours 的作者,这两本书只是他的 16 本技术书籍中的一部分。他的主要网站是 www.intuitive.com。