【问题标题】:How to extract data (user name)from webpage如何从网页中提取数据(用户名)
【发布时间】:2013-10-26 19:04:35
【问题描述】:

我想从成员列表页面收集用户名,如下所示: http://www.marksdailyapple.com/forum/memberslist/

我想从所有页面中获取每个用户名,

我想在 linux 中用 bash 来做这个

我应该从哪里开始,谁能给我一些提示?

【问题讨论】:

  • 你必须自己尝试一些东西。试试curl。但最好在 perl (WWW::Mechanize + HTML::TreeBuilder::Xpath)、python 或 ruby​​ 等语言中使用真正的 HTML 解析器。
  • 谢谢你的提示,但对我来说似乎很难……

标签: linux bash html-content-extraction


【解决方案1】:

这就是我的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>'

【讨论】:

  • 哦!我喜欢这个,干得好!
  • 不错的工具,你能解释一下“a.username”和“'(//a[@rel="Next"])[1]'”对我意味着什么吗?它似乎没有为我要从中提取数据的页面工作。
  • a.username 是一个 css 选择器,用于选择类为 username 的所有链接。 (//a[@rel="Next"])[1] 是一个 XPath 表达式,用于选择属性为 rel="Next" 的第一个链接。 -e 表示它应该提取选择(将其打印到标准输出),-f 表示它应该跟随一个链接。您可以对这两个选项使用 css 选择器或 xpath,它应该会自动检测您使用了哪种表达式
  • 其实,我对html和css不太了解,所以我自己很难弄清楚提取表达式,我想使用那个xidelscript。但是在我选择了第一个之后ID“#thernrem1950”,结果框中显示的css表达式与你的有点不同,即“TABLE#memberlist_table TR TD.username A.username”,请告诉我为什么?我不知道如何使用xidel获得“关注表情”……
  • 如果一个 css 选择器包含空格,这意味着它包含多个选择器,每个选择器只应用最后一个结果的后代。所以你的选择器首先选择TABLE#memberlist_table,然后是TR,然后是TD,最后是A.username,这和我的一样。下面的表达式选择next button。您也可以为此使用 css:-f "div#pagination_top span.prev_next a"。 (只是 -f "span.prev_next a" 不起作用,因为 Xidel 由于 _ 而无法将其检测为 css 选择器)
【解决方案2】:

首先您应该使用wget 来获取所有用户名页面。您将不得不使用一些选项(查看wget 的手册页)以使其跟随正确的链接,并且最好不要跟随任何无趣的链接(或者如果失败,您可以在之后忽略无趣的链接)。

那么,尽管Stackoverflow tells you not to use regular expressions to parse HTML,你应该使用正则表达式来解析HTML,因为它只是一个家庭作业,对吧?

如果这不是家庭作业,则说明您没有选择最适合这项工作的工具。

【讨论】:

  • 谢谢,这不是家庭作业,我只想用 bash 来做。
  • 但是你为什么要用 bash 来做呢?!
  • 我正在学习linux,所以……(但我不会拒绝学习更好的方法^^)在我使用wget下载网页后,我可以使用什么命令来获取所有用户ID那个页面?grep 可以吗?你能帮我在这部分限制我的想法吗?
  • grep 可能适用于这些特定页面,但我建议使用真正的编程语言和真正的 HTML 解析器将更能够应对不同类型的用户列表页。但是如果你真的想使用grep,你应该查看HTML页面的源代码并设计一个正则表达式来匹配包含用户名的a元素。提示:他们得到了 CSS 类 username 的帮助。
  • 什么语言?什么 HTML 解析器?你能推荐一个吗,拜托?你在这个提示中是什么意思?“他们有帮助地给出 CSS 类用户名”,你能拿这个页面或者其他例子?
【解决方案3】:

正如 Robin 所建议的,你真的应该在包含一个像样的 html 解析器的编程语言中做这种事情。您总是可以使用命令行工具执行各种任务,但是在这种情况下,我可能会选择 perl。

如果您真的想尝试使用命令行工具,我建议您使用 curl、grep、sort 和 sed。

当我有一些东西可以玩时,我总是觉得它更容易,所以这里有一些东西可以帮助你开始。
虽然我不会使用这种代码来产生有用的东西,但只是为了让你得到一些想法。

  • memberpages 似乎是 xxx://xxx.xxx/index1.html,其中 1 表示页码。因此,我要做的第一件事就是提取最后一个会员页面的编号。当我拥有它时,我知道我想用哪些 URL 来提供 curl。

  • 每个用户名都属于“用户名”类的成员,有了这些信息,我们可以使用 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 以 index[1-XXXX].html 格式的地址,这将使 curl 遍历所有页面。然后我们对用户名类进行 grep,将其传递给 sed 以提取相关数据(用户名)。然后,我们将生成的“用户名列表”传递给 sort 以对用户名进行排序。我总是喜欢排序的东西;)

大笔记,

  1. 你真的应该以另一种方式来做这件事。同样,我推荐 perl 来处理这些任务。
  2. 没有错误检查、用户名验证等。如果你应该在某种生产中使用它,没有捷径,那就做对。尝试阅读如何用不同的编程语言解析网页。
  3. 出于目的,我将 number_of_pages 声明为 2。您必须自己想办法获得最后一个会员页面的编号。虽然它有很多页面,我想它需要一些时间来遍历它们。

希望有帮助!

【讨论】:

  • 你的建议对你很有帮助,谢谢,但是我现在对perl知之甚少,也许我以后会尝试学习它
【解决方案4】:

我使用这个 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多