我正在开展一个小项目来分析我觉得有趣的网站上的内容;这是一个真正的DIY项目,我正在为我的娱乐/启蒙做,所以我想尽可能多地编写自己的代码。
显然,我将需要数据来提供我的应用程序,我想我会写一个小爬虫,可能需要20k页的html并将它们写入我的硬盘上的文本文件。但是,当我查看SO和其他网站时,我找不到有关如何执行此操作的任何信息。这可行吗?似乎有可用的开源选项(webpshinx?),但我想尽可能自己写这个。
Scheme是我唯一熟悉的语言,但我认为我会利用这个项目来学习一些Java,所以如果有任何racket或java库会对此有所帮助,我会感兴趣。
所以我想总结一下我的问题,有什么好的资源可以开始这个?如何让我的爬虫从其他服务器请求信息?我是否必须为此编写一个简单的解析器,或者这是不必要的,因为我想获取整个html文件并将其保存为txt?
答案 0 :(得分:5)
这完全可行,你绝对可以使用Racket。您可能想看一下PLaneT库;尤其是Neil Van Dyke的HtmlPrag:
http://planet.racket-lang.org/display.ss?package=htmlprag.plt&owner=neil
..可能是开始的地方。您应该能够将一个网页的内容拉成一行或两行代码中的解析格式。
如果您对此有任何疑问,请与我们联系。
答案 1 :(得分:1)
我自己在Racket中完成了这个,这就是我的建议。
从“Unix工具”方法开始:
curl
执行下载每个页面的工作(您可以使用system
从Racket执行它)并将输出存储在临时文件中。<a>
标记中提取URI。
此时您可以停止,或者,您可以返回并使用您自己的代码替换curl
来执行下载。为此,您可以使用Racket的net/url
模块。
为什么我建议尝试curl
,首先,它可以帮助您做一些比看上去更复杂的事情:
使用curl
例如:
(define curl-core-options
(string-append
"--silent "
"--show-error "
"--location "
"--connect-timeout 10 "
"--max-time 30 "
"--cookie-jar " (path->string (build-path 'same "tmp" "cookies")) " "
"--keepalive-time 60 "
"--user-agent 'my crawler' "
"--globoff " ))
(define (curl/head url out-file)
(system (format "curl ~a --head --output ~a --url \"~a\""
curl-core-options
(path->string out-file)
url)))
(define (curl/get url out-file)
(system (format "curl ~a --output ~a --url \"~a\""
curl-core-options
(path->string out-file)
url)))
表示代码是 lot ,否则您需要在Racket中从头开始编写代码。要做那些curl
命令行标志为你做的所有事情。
简而言之:从最简单的使用现有工具开始。使用Racket几乎作为shell脚本。如果这对你来说足够好,请停下来。否则,请继续使用您的定制代码逐个更换工具。
答案 2 :(得分:0)
我建议查看java的开源网络抓取工具crawler4j。
使用起来非常简单,它为您的抓取提供了非常好的资源和选项。
答案 3 :(得分:0)
如果您了解方案,并且想要轻松使用Java,为什么不从Clojure开始?
您可以利用您的lisp知识,并利用java html解析库*在那里获得一些有用的东西。然后,如果你想开始将它的一部分转换为Java来学习一点,你可以用Java编写一些功能并将其连接到Clojure代码中。
祝你好运!*我已经看到了几个SO问题。
答案 4 :(得分:0)
如果我是你,我不会写一个抓取工具 - 我会使用许多免费工具之一在本地下载网站进行离线浏览(例如http://www.httrack.com/)来进行抓取。您可能需要调整选项以禁用下载图像等,但这些工具将比您自己编写的任何内容更加健壮和可配置。
一旦你这样做,你就会在本地拥有大量的HTML文件,你可以将它们提供给你的应用程序。
我对HTML文件进行了大量的文本分析;作为一个Java人,我将HTML提炼成文本的选择库(再次,不是你想要自己推出的东西)是优秀的Jericho解析器:http://jericho.htmlparser.net/docs/index.html
编辑:重新阅读您的问题,看来您确实在编写自己的抓取工具;如果是这样,我会建议Commons HttpClient进行下载,并且仍然会让Jericho取出链接并将它们处理成新的请求。答案 5 :(得分:0)
我几年前在Perl中做过(更简单,即使没有webcrawler模块)。
我建议您阅读wget文档并使用该工具获取灵感。 Wget是webcrawling的netcat;它的功能集将激励你。
您的程序应接受一系列要开始使用的网址,并将其添加到要尝试的网址列表中。然后,您必须决定是要收集每个网址还是仅添加初始列表中提供的域(和子域?)中的网址。
我在Scheme中为你提供了一个相当强大的起点:
(define (crawl . urls)
;; I would use regular expressions for this unless you have a special module for this
;; Hint: URLs tend to hide in comments. referal tags, cookies... Not just links.
(define (parse url) ...)
;; For this I would convert URL strings to a standard form then string=
(define (url= x y) ...)
;; use whatever DNS lookup mecanism your implementation provides
(define (get-dom) ...)
;; the rest should work fine on its own unless you need to modify anything
(if (null? urls) (error "No URLs!")
(let ([doms (map get-dom urls)])
(let crawl ([done '()])
(receive (url urls) (car+cdr urls)
(if (or (member url done url=)
(not (member (get-dom url) doms url=)))
(crawl urls done)
(begin (parse url) (display url) (newline)
(crawl (cons url done)))))))))