我正在尝试使用
WWW::Mechanize
和
Mojo::DOM
从旧的vBulletin论坛中提取文本.
vBulletin不使用HTML和CSS进行语义标记,而且我在使用Mojo :: DOM->孩子来获取某些元素时遇到了麻烦.
这些vBulletin帖子的结构取决于其内容.
单个消息:
<div id="postid_12345">The quick brown fox jumps over the lazy dog.<div>
单个消息引用另一个用户:
<div id="postid_12345"> <div> <table> <tr> <td> <div>Quote originally posted by Bob</div> <div>Everyone knows the sky is blue.</div> </td> </tr> </table> </div> I disagree with you,Bob. It's obvIoUsly green. </div>
带有剧透的单个消息:
<div id="postid_12345"> <div class="spoiler">Yoda is Luke's father!</div> </div>
单个消息引用另一个用户,带有剧透:
<div id="postid_12345"> <div> <table> <tr> <td> <div>Quote originally posted by Fred</div> <div class="spoiler">Yoda is Luke's father!</div> </td> </tr> </table> </div> <div class="spoiler">No waaaaay!</div> </div>
假设上面的HTML和一个包含必要帖子ID的数组:
for (@post_ids) { $mech->get($full_url_of_specific_forum_post); my $dom = Mojo::DOM->new($mech->content); my $div_id = 'postid_' . $_; say $dom->at($div_id)->children('div')->first; say $dom->at($div_id)->text; }
使用$dom-> at($div_id) – > all_text可以在一条连续的行中提供所有内容,这使得很难分辨帖子中的引用内容和原始内容.
使用$dom-> at($div_id) – >文本会跳过所有子元素,因此不会选择带引号的文本和剧透.
我尝试了$dom-> at($div_id) – > children(‘div’) – >的变体,但这给了我一切,包括HTML.
理想情况下,我希望能够获取每个帖子中的所有文本,每个子元素都在自己的行中,例如
POSTID12345: + Quote originally posted by Bob + Everyone knows the sky is blue. I disagree with you,Bob. It's obvIoUsly green.
我是Mojo的新手,并且和Perl一起生气.我想自己解决这个问题,但在查看文档并摆弄它几个小时之后,我的脑子就变得糊里糊涂了,我很茫然.我只是没有得到Mojo :: DOM和Mojo :: Collections如何工作.
任何帮助将不胜感激.
解决方法
查看Mojo :: DOM的源代码,基本上
all_text
method递归遍历DOM并提取所有文本.使用该源编写自己的DOM函数.它的递归函数依赖于返回单个字符串,在你的函数中你可能会返回一个数组,其中包含你需要的任何上下文.
编辑:
在对IRC进行一些讨论之后,网页抓取示例已经更新,它可以帮助您指导您. http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#Web_scraping