2012-01-20 27 views
5

Tôi đang làm việc trên một dự án nhỏ để phân tích nội dung trên một số trang web mà tôi thấy thú vị; đây là một dự án DIY thực sự mà tôi đang làm cho giải trí/giác ngộ của mình, vì vậy tôi muốn tự mình viết mã càng nhiều càng tốt. Rõ ràng, tôi sẽ cần dữ liệu để cấp dữ liệu cho ứng dụng của mình, và tôi đã nghĩ tôi sẽ viết một trình thu thập dữ liệu nhỏ có thể lấy 20k trang html và ghi chúng vào tệp văn bản trên ổ cứng của tôi. Quay lại đầu trang Tuy nhiên, khi tôi xem xét SO và các trang web khác, tôi không thể tìm thấy bất kỳ thông tin nào về cách thực hiện việc này. Nó là khả thi? Dường như có các tùy chọn mã nguồn mở sẵn có (webpshinx?), Nhưng tôi muốn tự viết nó nếu có thể.Làm cách nào để thiết kế bot thu thập thông tin?

Đề án là ngôn ngữ duy nhất tôi biết rõ, nhưng tôi nghĩ tôi sẽ sử dụng dự án này để tự học một số Java, vì vậy tôi sẽ quan tâm nếu có bất kỳ thư viện vợt hoặc java nào hữu ích cho việc này .

Vì vậy, tôi đoán tóm tắt câu hỏi của tôi, một số tài nguyên tốt để bắt đầu điều này là gì? Làm cách nào để trình thu thập thông tin của tôi yêu cầu thông tin từ các máy chủ khác? Tôi sẽ phải viết một phân tích cú pháp đơn giản cho điều này, hoặc là không cần thiết cho tôi muốn lấy toàn bộ tập tin html và lưu nó như txt?

+0

Đừng cần một cú pháp nếu bạn không đi để phân tích, nhưng phân tích cú pháp sẽ làm cho kéo ra liên kết dễ dàng hơn đáng kể. Không chắc chắn nơi bạn gặp sự cố; có rất nhiều ví dụ có sẵn - bạn đã có những gì cho đến nay? –

+0

Bạn có dự định làm tất cả các ổ cắm tự hoạt động và nói HTTP thô với máy chủ không? Hoặc bạn có nội dung sử dụng các công cụ cấp cao hơn để yêu cầu các URL cụ thể không? (Bạn có quan tâm nhiều hơn về phía mạng hoặc bên phân tích cú pháp HTML không?) – sarnold

+0

Dave, bạn có thể chỉ ra một ví dụ không? Điều đó sẽ rất hữu ích. Sarnold, tôi chưa bao giờ thực sự thực hiện bất kỳ chương trình web nào - chỉ cần một số nội dung với mô-đun web-server/insta trong vợt, yêu cầu và đưa ra phản hồi. Vì vậy, tôi thậm chí không chắc chắn làm thế nào để viết một chương trình gửi một phản ứng chính nó. –

Trả lời

0

Tôi khuyên bạn nên xem xét trình thu thập dữ liệu web nguồn mở cho java được gọi là crawler4j.

Nó rất đơn giản để sử dụng và nó cung cấp tài nguyên rất tốt và các tùy chọn cho thu thập thông tin của bạn.

5

Điều này hoàn toàn khả thi và bạn chắc chắn có thể làm điều đó với Racket. Bạn có thể muốn xem qua các thư viện PLaneT; Đặc biệt, Neil Van Dyke của HtmlPrag:

http://planet.racket-lang.org/display.ss?package=htmlprag.plt&owner=neil

.. có lẽ là nơi để bắt đầu. Bạn sẽ có thể kéo nội dung một trang web thành một định dạng được phân tích cú pháp trong một hoặc hai dòng mã.

Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi nào về vấn đề này.

+0

Và sau đó sử dụng sxpath (thực hiện XPath) để trích xuất các phần; xem gói SXML2 được duy trì bởi tác giả của câu trả lời này: http://planet.racket-lang.org/display.ss?package=sxml2.plt&owner=clements –

+0

Cảm ơn bạn đã chỉ cho tôi về những điều này, tôi chắc chắn sẽ kiểm tra chúng ra. –

0

Nếu bạn biết lược đồ và bạn muốn dễ dàng sử dụng Java, tại sao bạn không bắt đầu với Clojure?

Bạn có thể tận dụng kiến ​​thức lisp của mình và tận dụng lợi thế của các thư viện phân tích cú pháp html html * để làm việc gì đó. Sau đó, nếu bạn muốn bắt đầu chuyển các phần của nó sang Java để tìm hiểu một chút, bạn có thể viết các bit chức năng trong Java và dây dẫn vào mã Clojure.

Chúc may mắn!

* Tôi đã xem một số câu hỏi về vấn đề này.

+0

Mối quan tâm của tôi với ý tưởng này là cú pháp của clojure hoàn toàn khác với lược đồ mà tôi muốn thảo luận tài liệu về clojure nhiều như java và học hai ngôn ngữ cùng một lúc. Tôi có thổi những khác biệt ở đây không? –

+0

Một lisp của nó, có một vài hình thức mà có lẽ không có trong chương trình, và một khi bạn có ý chính của những người nó sẽ chỉ được tham chiếu mà chức năng làm những gì. http://clojuredocs.org (ref nhanh) thực sự tốt cho điều đó. Tôi nghĩ bạn sẽ nhặt nó rất nhanh. Tôi cũng nghĩ rằng nó có thể là một kỹ năng thị trường tốt để có. – Bill

0

Nếu tôi là bạn, tôi sẽ không viết trình thu thập thông tin - tôi sẽ sử dụng một trong nhiều công cụ miễn phí tải xuống trang web cục bộ để duyệt ngoại tuyến (ví dụ: http://www.httrack.com/). Bạn có thể cần phải tinh chỉnh các tùy chọn để vô hiệu hóa tải xuống hình ảnh, v.v., nhưng những công cụ đó sẽ trở nên mạnh mẽ hơn và có thể cấu hình hơn bất cứ thứ gì bạn tự viết.

Khi bạn làm điều đó, bạn sẽ có toàn bộ tấn tệp HTML cục bộ mà bạn có thể nạp vào ứng dụng của mình.

Tôi đã thực hiện rất nhiều phân tích văn bản các tệp HTML; như một anh chàng Java, thư viện của tôi lựa chọn để chưng cất HTML thành văn bản (một lần nữa, không phải cái gì bạn muốn cuộn mình) là trình phân tích cú pháp Jericho tuyệt vời: http://jericho.htmlparser.net/docs/index.html

EDIT: đọc lại câu hỏi của bạn, có vẻ như bạn đang đặt vào viết trình thu thập thông tin của riêng bạn; nếu vậy, tôi sẽ khuyên bạn nên Commons HttpClient để làm việc tải xuống, và vẫn còn Jericho để kéo ra các liên kết và xử lý chúng thành các yêu cầu mới.

1

Tự mình thực hiện việc này trong Racket, đây là những gì tôi sẽ đề xuất.

Bắt đầu với một cách tiếp cận "Unix công cụ":

  • Sử dụng curl để làm công việc của tải mỗi trang (bạn có thể thực hiện nó từ vợt sử dụng system) và lưu trữ kết quả trong một tập tin tạm thời.
  • Sử dụng vợt để trích xuất các URI từ các thẻ <a>.
    • Bạn có thể "lừa đảo" và thực hiện tìm kiếm chuỗi biểu thức chính quy.
    • Hoặc, làm điều đó "đúng cách" với trình phân tích cú pháp HTML đúng, như câu trả lời tuyệt vời của John Clements giải thích.
    • Cân nhắc có thể thực hiện lừa đảo trước, sau đó lặp lại sau để thực hiện đúng cách.

Tại thời điểm này bạn có thể dừng lại, hoặc, bạn có thể quay trở lại và thay thế curl với mã của riêng bạn để làm tải. Đối với điều này, bạn có thể sử dụng mô-đun net/url của Racket.

Tại sao tôi khuyên bạn nên cố gắng curl, trước hết, là nó sẽ giúp bạn làm điều gì đó phức tạp hơn nó có vẻ:

  • Bạn có muốn làm theo 30x chuyển hướng?
  • Bạn có muốn chấp nhận/lưu trữ/cung cấp cookie (trang web có thể hoạt động khác không)?
  • Bạn có muốn sử dụng HTTP tiếp tục không?
  • Và cứ tiếp tục.

Sử dụng curl ví dụ như thế này:

(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))) 

đại diện là một nhiều mã mà bạn nếu không sẽ cần phải viết từ đầu trong vợt. Để làm tất cả những điều mà các cờ dòng lệnh curl đang làm cho bạn.

Tóm lại: Bắt đầu với trường hợp đơn giản nhất khi sử dụng các công cụ hiện có. Sử dụng Racket gần như là một kịch bản shell. Nếu đó là đủ tốt cho bạn, dừng lại. Nếu không, hãy tiếp tục thay thế từng công cụ bằng mã bespoke của bạn.

0

Tôi đã làm điều đó trong Perl năm trước (dễ dàng hơn nhiều, ngay cả khi không có mô-đun webcrawler).

Tôi khuyên bạn nên đọc tài liệu wget và sử dụng công cụ để lấy cảm hứng. Wget là netcat của webcrawling; bộ tính năng của nó sẽ truyền cảm hứng cho bạn.

Chương trình của bạn phải chấp nhận danh sách URL để bắt đầu và thêm chúng vào danh sách URL cần thử. Sau đó, bạn phải quyết định xem bạn có muốn thu thập mọi url hay chỉ thêm những từ tên miền (và tên miền phụ?) Được cung cấp trong danh sách ban đầu hay không.

tôi làm cho bạn một điểm khởi đầu khá mạnh mẽ trong Đề án:

(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))))))))) 
Các vấn đề liên quan