我目前正在编写一个网络爬虫机器人。它生成一个 URL 列表,我需要它来删除重复项,并按字母顺序对行进行排序。我的代码如下所示:
#! /bin/bash
URL="google.com"
while [ 1 ]; do
wget --output-document=dl.html $URL
links=($(grep -Po '(?<=href=")[^"]*' dl.html))
printf "%s\n" ${links[@]} >> results.db
sort results.db | uniq -u
URL=$(shuf -n 1 results.db)
echo $URL
done
特别是该行:
sort results.db | uniq -u
答案1
POSIX说uniq -u
:
禁止写入输入中重复的行。
这意味着任何重复的行(甚至是原始行)都将被过滤掉。你的意思可能是(完成了POSIX还):
sort -u results.db
对于sort -u
,POSIX 说
独特:抑制除一在每组具有相同键的行中。如果与 -c 选项一起使用,除了检查输入文件是否已排序之外,还检查是否没有包含重复键的行。
无论哪种情况,下面的行
URL=$(shuf -n 1 results.db)
可能假设 sort/uniq 的目的是更新 results.db
(它不会)。为此,您必须对脚本进行更多修改:
sort -u results.db >results.db2 && mv results.db2 results.db
或者(按照@drewbenn的建议),将其与上一行结合起来。然而,自那以后追加到文件(组合他的答案中所示的命令不会消除最新 printf 和文件内容之间的重复项),单独的命令 sort/mv 看起来更接近原始脚本。
如果你想确保它$URL
不为空,那就是(实际上是另一个问题),并通过测试完成[
,例如,
[ -n "$URL" ] && wget --output-document=dl.html $URL
尽管简单地退出循环会更简单:
[ -z "$URL" ] && break
答案2
这是脚本的改进版本。
它仍然很糟糕,因为(除了最初的谷歌搜索的最低限度的努力之外),它没有尝试处理任何真正可怕的事情,不幸的是大部分网站对A HREF
URL 所做的事情 - 要么是因为它们无能或者因为他们试图追踪您或两者。
#! /bin/sh
# exit on any error
set -e
dbfile="results.db"
# if "$dbfile" doesn't exist (or is empty), or if a URL has been
# provided as a command-line argument, fetch the initial URLs
# from "$1" (or a google search), and strip off the google-junk:
if [ ! -s "$dbfile" ] || [ -n "$1" ] ; then
URL="{$1:-https://www.google.com/search?q=interesting+stuff}"
lynx -accept_all_cookies -dump -listonly -nonumbers "$URL" |
sed -e '/^http.*url?/!d; s/^.*\/url?q=//; s/\&.*//' > "$dbfile"
fi
URL=$(shuf -n 1 "$dbfile")
while [ 1 ]; do
lynx -accept_all_cookies -dump -listonly -nonumbers "$URL" |
grep http >> "$dbfile"
tmpfile=$(mktemp) &&
sort -u "$dbfile" > "$tmpfile" &&
mv -f "$tmpfile" "$dbfile" &&
rm -f "$tmpfile"
URL=$(shuf -n 1 "$dbfile")
echo "$URL"
done
网页抓取很困难,主要是因为 HTML 是一个极其宽松的标准,但也因为网页设计者通常要么是无能的弱者,要么是试图故意混淆他们的页面,或者两者兼而有之。它需要一种比bash
.
perl
就我个人而言,我用libwww-perl
aka编写网络机器人LWP
。我特别喜欢HTML::TokeParser
perl 模块,它是一个相当简单的 HTML 解析器,与LWP
.