我想从成员列表页面收集用户名,如下所示:http://www.marksdailyapple.com/forum/memberslist/
我想从所有页面中获取每个用户名,
我想在 linux 中做到这一点,使用 bash
我应该从哪里开始,任何人都可以给我一些提示吗?
这就是我的 Xidel 的用途:
xidel http://www.marksdailyapple.com/forum/memberslist/ -e 'a.username' -f '(//a[@rel="Next"])[1]'
通过这个简单的行,它将使用适当的html解析器解析页面,使用css选择器查找所有带有名称的链接,使用xpath查找下一页并重复它,直到所有页面都被处理
您也可以仅使用 css 选择器编写它:
xidel http://www.marksdailyapple.com/forum/memberslist/ -e 'a.username' -f 'div#pagination_top span.prev_next a'
或模式匹配。在那里,您基本上只需从页面源代码中复制要查找的html元素,并将文本内容替换为{.}
:
xidel http://www.marksdailyapple.com/forum/memberslist/ -e '<a class="username">{.}</a>*' -f '<a rel="next">{.}</a>'
首先,您应该使用 wget
来获取所有用户名页面。您必须使用一些选项(检查手册页中的wget
)以使其遵循正确的链接,理想情况下不要遵循任何不感兴趣的链接(否则,您可以忽略之后的无趣链接)。
然后,尽管 Stackoverflow 告诉你不要使用正则表达式来解析 HTML,但你应该使用正则表达式来解析 HTML,因为这只是一个家庭作业,对吧?
如果这不是家庭作业,那么您没有为这项工作选择最佳工具。
正如Robin所建议的那样,你真的应该在包含体面的html解析器的编程语言中做这种事情。你总是可以使用命令行工具执行各种任务,但是在这种情况下,我可能会选择perl。
如果你真的想尝试使用命令行工具做到这一点,我建议,curl,grep,sort和sed。
当我有东西可以玩时,我总是觉得更容易,所以这里有一些东西可以帮助你开始。
不过,我不会使用这种代码来生成有用的东西,但只是为了让您获得一些想法。
-
成员页面似乎很 xxx://xxx.xxx/index1.html,其中 1 表示页码。因此,我要做的第一件事是提取最后一个成员页面的编号。当我拥有它时,我知道我想用哪些网址喂卷曲。
-
每个用户名都在"用户名"类的成员中,有了这些信息,我们可以使用 grep 来获取相关数据。
#!/bin/bash number_of_pages=2 curl http://www.marksdailyapple.com/forum/memberslist/index[1-${number_of_pages}].html --silent | egrep 'class="username">.*</a>' -o | sed 's/.*>(.*)</a>/1/' | sort
这里的想法是给 curl 格式索引 [1-XXXX].html 中的地址,这将使 curl 遍历所有页面。然后,我们 grep 获取用户名类,将其传递给 sed 以提取相关数据(用户名)。然后,我们将生成的"用户名列表"传递到排序以使用户名排序。我总是喜欢排序的东西;)
虽然大笔记,
- 你真的应该以另一种方式做到这一点。同样,我推荐perl来完成这类任务。
- 没有错误检查,用户名验证等。如果你应该在某种生产中使用它,没有捷径,那就做对了。尝试阅读如何解析不同编程语言的网页。
- 我特意宣布number_of_pages比二。你必须自己想办法获取最后一个成员页面的编号。不过,它有很多页面,我想遍历它们需要一些时间。
希望有帮助!
我使用这个bash脚本浏览了所有页面:
#!/bin/bash
IFS=$'n'
url="http://www.marksdailyapple.com/forum/memberslist/"
content=$(curl --silent -L ${url} 2>/dev/null | col -b)
pages=$(echo ${content} | sed -n '/Last Page/s/^.*index([0-9]+).*/1/p' | head -1)
for page in $(seq ${pages}); do
IFS=
content=$(curl --silent -L ${url}index${page}.html 2>/dev/null | col -b)
patterns=$(echo ${content} | sed -n 's/^.*class="username">([^<]*)<.*$/1/gp')
IFS=$'n' users=(${patterns})
for user in ${users[@]}; do
echo "user=${user}."
done
done