2012-02-11 82 views
5

Tôi có nhiều văn bản cần xử lý cho các URL hợp lệ.Trích xuất URL từ các tệp văn bản/HTML lớn

Đầu vào hơi mơ hồ HTML, trong đó phần lớn là html. Tuy nhiên, nó không thực sự là hợp lệ HTML.

Tôi đã cố gắng thực hiện với regex và gặp sự cố.

Trước khi bạn nói (hoặc có thể hét lên - Tôi đã đọc các câu hỏi HTML + regex khác) "sử dụng một phân tích cú pháp", có một điều bạn cần phải xem xét:
Các tập tin tôi đang làm việc với rất có kích thước khoảng 5 GB

Tôi không biết bất kỳ trình phân tích cú pháp nào có thể xử lý điều đó mà không bị lỗi hoặc mất vài ngày. Hơn nữa, thực tế là, trong khi nội dung văn bản là phần lớn là html, nhưng không nhất thiết phải hợp lệ html có nghĩa là nó sẽ yêu cầu một trình phân tích cú pháp rất khoan dung. Cuối cùng, không phải tất cả các liên kết đều nhất thiết trong các thẻ <a> (một số có thể chỉ là văn bản thuần túy).

Vì tôi không thực sự quan tâm đến cấu trúc tài liệu, có lựa chọn thay thế nào tốt hơn WRT giải nén liên kết?

Ngay bây giờ tôi đang sử dụng regex:
\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))) (trong grep -E)
nhưng ngay cả với điều đó, tôi đã từ bỏ sau khi để cho nó chạy trong khoảng 3 giờ.

Có sự khác biệt đáng kể về hiệu suất của động cơ Regex không? Tôi đang sử dụng dòng lệnh của MacOS grep. Nếu có các triển khai tương thích khác có hiệu suất tốt hơn, đó có thể là một tùy chọn.


Tôi không quan tâm quá nhiều về ngôn ngữ/nền tảng, mặc dù dòng lệnh/MacOS sẽ tốt đẹp.

+0

Nó có nên thu hút mọi thứ không có kế hoạch không? (ví dụ: không có 'http: //') – icktoofay

+0

@icktoofay - Điều đó thật tuyệt. –

Trả lời

2

Tôi vết thương lên chuỗi lệnh một vài grep với nhau:

pv -cN source allContent | grep -oP "(?:\"([^\"' ]*?)\")|(?:'([^\"' ]*?)')|(?:([^\"' ]*?))" | grep -E "(http)|(www)|(\.com)|(\.net)|(\.to)|(\.cc)|(\.info)|(\.org)" | pv -cN out > extrLinks1

tôi đã sử dụng pv để cho tôi một dấu hiệu tiến bộ.

grep -oP "(?:\"([^\"' ]*?)\")|(?:'([^\"' ]*?)')|(?:([^\"' ]*?))"
Kéo ra bất kỳ thứ gì trông giống như một từ hoặc văn bản được trích dẫn và không có dấu cách.

grep -E "(http)|(www)|(\.com)|(\.net)|(\.to)|(\.cc)|(\.info)|(\.org)"
Bộ lọc đầu ra cho bất cứ điều gì mà có vẻ như nó có thể là một địa chỉ URL.

Cuối cùng,
pv -cN out > extrLinks1
Đầu ra nó vào một tập tin, và cung cấp cho một mét hoạt động tốt đẹp.

Tôi có thể sẽ đẩy tệp được tạo thông qua sort -u để xóa các mục nhập trùng lặp, nhưng tôi không muốn chuỗi kết thúc vì nó sẽ thêm một lớp phức tạp khác và tôi chắc chắn rằng sắp xếp sẽ thử để đệm toàn bộ tệp, điều này có thể gây ra sự cố.


Dù sao, khi nó đang chạy ngay bây giờ, có vẻ như sẽ mất khoảng 40 phút. Tôi không biết về pv trước đây. Đó là một tiện ích thực sự thú vị!

0

Tôi nghĩ bạn đang đi đúng hướng và grep sẽ có thể xử lý tệp 5Gb. Hãy thử đơn giản hóa regex của bạn tránh toán tử | và quá nhiều dấu ngoặc đơn. Ngoài ra, sử dụng lệnh head để lấy 100Kb đầu tiên trước khi chạy đối với toàn bộ tệp và chuỗi các greps sử dụng đường ống để đạt được độ đặc hiệu hơn. Ví dụ:

head -c 100000 myFile | grep -E "((src)|(href))\b*=\b*[\"'][\w://\.]+[\"']" 

Điều đó phải siêu nhanh, phải không?

+0

Tôi đang tìm cách bắt các liên kết không có trong các thẻ ''. –

Các vấn đề liên quan