2009-03-14 32 views
6

Tôi đã trả lời một số câu hỏi đố vui cho một cuộc phỏng vấn và câu hỏi đặt ra là tôi sẽ làm cách nào để cạo màn hình. Tức là, chọn nội dung ra khỏi trang web, giả sử bạn không có cách có cấu trúc tốt hơn để truy vấn trực tiếp thông tin (ví dụ: dịch vụ web).Cạo màn hình: biểu thức chính quy hoặc biểu thức XQuery?

Giải pháp của tôi là sử dụng biểu thức XQuery. Biểu thức khá dài vì nội dung tôi cần khá sâu trong cấu trúc phân cấp HTML. Tôi đã phải tìm kiếm thông qua tổ tiên một cách công bằng trước khi tôi tìm thấy một yếu tố với một thuộc tính id. Ví dụ: việc cạo một trang Amazon.com cho Thứ nguyên sản phẩm trông giống như sau:

//a[@id="productDetails"] 
/following-sibling::table 
//h2[contains(child::text(), "Product Details")] 
/following-sibling::div 
//li 
/b[contains(child::text(), "Product Dimensions:")] 
/following-sibling::text() 

Đó là một biểu hiện khá khó chịu, nhưng đó là lý do Amazon cung cấp API dịch vụ web. Dù sao, nó chỉ là một ví dụ. Câu hỏi không phải về Amazon, nó là về cạo màn hình.

Người phỏng vấn không thích giải pháp của tôi. Ông nghĩ rằng nó rất mong manh, bởi vì một sự thay đổi thiết kế trang của Amazon có thể yêu cầu viết lại biểu thức XQuery. Gỡ lỗi một biểu thức XQuery không khớp với bất kỳ thứ gì trong trang mà nó được áp dụng chống lại là khó.

Tôi không đồng ý với tuyên bố của ông, nhưng tôi không nghĩ giải pháp của ông là cải thiện: ông nghĩ tốt hơn là sử dụng biểu thức chính quy và tìm kiếm nội dung và đánh dấu gần trọng lượng giao hàng. Ví dụ: sử dụng Perl:

$html =~ m{<li>\s*<b>\s*Product Dimensions:\s*</b>\s*(.*?)</li>}s; 

Đối số phản đối của tôi là điều này cũng dễ bị Amazon thay đổi mã HTML của họ. Họ có thể đánh vần thẻ HTML ở thủ đô (<LI>) hoặc thêm thuộc tính CSS hoặc thay đổi <b> thành <span> hoặc thay đổi nhãn "Thứ nguyên sản phẩm:" thành "Thứ nguyên:" hoặc nhiều loại thay đổi khác. Quan điểm của tôi là các biểu thức chính quy không giải quyết được các điểm yếu mà anh ta đã gọi ra trong giải pháp XQuery của tôi.

Nhưng ngoài ra, cụm từ thông dụng có thể tìm thấy các mặt tích cực sai, trừ khi bạn thêm đủ ngữ cảnh vào biểu thức. Nó cũng có thể vô tình phù hợp với nội dung xảy ra bên trong một chú thích, hoặc một chuỗi thuộc tính hoặc một phần CDATA.

Câu hỏi của tôi là, bạn sử dụng công nghệ nào để thực hiện cạo màn hình? Tại sao bạn chọn giải pháp đó? Có một số lý do thuyết phục để sử dụng nó không? Hoặc không bao giờ sử dụng khác? Có lựa chọn thứ ba nào ngoài những lựa chọn tôi đã trình bày ở trên không?

PS: Giả sử vì lý do không có API dịch vụ web hoặc cách trực tiếp khác để có được nội dung mong muốn.

Trả lời

3

Tôi muốn sử dụng cụm từ thông dụng, vì những lý do mà người quản lý đưa ra, làm phiền một vài (dễ dàng hơn, dễ dàng hơn cho các lập trình viên bên ngoài theo dõi, v.v.).

Đối số phản đối của bạn bỏ lỡ điểm rằng giải pháp của ông rất mong manh đối với địa phương thay đổi trong khi thay đổi của bạn là mong manh đối với thay đổi toàn cầu. Bất cứ điều gì phá vỡ ý chí của anh ta có thể sẽ phá vỡ của bạn, nhưng không phải visa-versa.

Cuối cùng, việc xây dựng slop/flex vào giải pháp của anh ta dễ dàng hơn nhiều (nếu, ví dụ, bạn phải xử lý nhiều biến thể nhỏ trong đầu vào).

4

Tôi muốn sử dụng cụm từ thông dụng, nhưng chỉ vì hầu hết các trang HTML không phải là XML hợp lệ, vì vậy bạn sẽ không bao giờ nhận được XQUERY hoạt động.

Tôi không biết XQuery, nhưng trông giống như biểu thức XPATH với tôi. Nếu vậy, có vẻ hơi đắt tiền với rất nhiều "//" nhà khai thác trong đó.

+0

Đây là lý do chính để tránh tìm kiếm trên web dựa trên XML. Không có bộ xử lý XML nào được tha thứ như một trình duyệt. Trang chỉ cần phá vỡ một quy tắc hợp lệ để làm cho XQuery hoàn toàn vô dụng. – harpo

1

Tôi thực sự tìm thấy biểu thức tìm kiếm CSS dễ đọc hơn. Có thể tồn tại ít nhất một thư viện bằng ngôn ngữ bạn chọn sẽ phân tích một trang và cho phép bạn viết các chỉ thị CSS để định vị các phần tử cụ thể. Nếu có một lớp thích hợp hoặc ID móc gần đó thì biểu thức là khá tầm thường. Nếu không, hãy lấy các phần tử có vẻ thích hợp và lặp lại qua chúng để tìm những phần tử bạn cần.

Đối với mong manh, tốt, tất cả chúng đều mong manh. Sàng lọc màn hình theo định nghĩa phụ thuộc vào tác giả của trang đó không thay đổi bố cục của nó một cách quyết liệt. Đi với một giải pháp có thể đọc được và có thể dễ dàng thay đổi sau này.

1

Một giải pháp không dễ vỡ để sàng lọc màn hình? Chúc may mắn cho người phỏng vấn cho điều đó: chỉ vì biểu thức thông thường quăng đi rất nhiều bối cảnh không có nghĩa là chúng ít giòn hơn: chỉ là chúng giòn theo những cách khác. Nhược điểm có thể thậm chí không phải là một nhược điểm: nếu một cái gì đó thay đổi trong trang web nguồn, bạn thường tốt hơn nếu giải pháp của bạn tăng báo động, thay vì cố gắng bù đắp một cách thông minh (và không thể đoán trước). Như bạn đã lưu ý. Những điều này luôn phụ thuộc vào các giả định của bạn: trong trường hợp này, về những gì cấu thành một sự thay đổi có khả năng.

Tôi thà thích số HTML agility pack: bạn nhận được sự khoan dung của các trang web không tuân thủ XHTML được kết hợp với sức mạnh biểu cảm của XPath.

2

Hãy thử JTidy hoặc BeautifulSoup hoạt động tốt cho tôi. chắc chắn // XPATH experssion khá tốn kém để loại bỏ.

1

Cụm từ thông dụng thực sự nhanh và hoạt động với các tài liệu không phải XML. Đó thực sự là những điểm tốt đối với XQuery. Tuy nhiên, tôi nghĩ rằng việc sử dụng một số trình chuyển đổi cho XHTML giống như XQuery gọn gàng và có thể đơn giản hơn, giống như chỉ phần cuối cùng của bạn:

//b[contains(child::text(), "Product Dimensions:")]/following-sibling::text() 

là một lựa chọn rất tốt.

Kính trọng,

Rafal Rusin

1

Để làm việc trên các trang html, nó là tốt nhất để sử dụng HtmlAgilityPack (và với một số mã LINQ). Đó là một cách tuyệt vời để phân tích cú pháp thông qua tất cả các phần tử và/hoặc thực hiện tìm kiếm trực tiếp với XPath. Theo tôi, nó chính xác hơn RegEx và dễ lập trình hơn. Tôi đã có một chút miễn cưỡng để sử dụng nó trước đây, nhưng nó rất dễ dàng để thêm vào dự án của bạn và tôi nghĩ là tiêu chuẩn yếu tố de để làm việc với html. http://htmlagilitypack.codeplex.com/

Chúc may mắn!

+0

Cảm ơn, có, HTML Agility Pack đã được đề xuất trong một câu trả lời khác của Pontus Gagge. Tôi tự hỏi HTML Agility Pack nào sử dụng nội bộ - XPath, biểu thức chính quy hoặc một số phân tích cú pháp DOM tùy chỉnh khác hoặc một số thứ khác. –

+1

Với HtmlAgilityPack, bạn có thể duyệt qua toàn bộ DOM thông qua DocumentNode.ChildNodes. Ví dụ: Đối với mỗi voTag trong voMyHTML.DocumentNode.ChildNodes hoặc bạn có thể phóng to vào một nút duy nhất với voMyHTML.DocumentNode.SelectSingleNode (vsXPath) hoặc thậm chí bạn có thể sử dụng LINQ: voElements = (Từ voTag Trong voMyHTML.DocumentNode.ChildNodes đâu voTag.GetAttributeValue ("class") = "myClass" Chọn voTag) –

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