Hướng dẫn can xml parsers parse html? - trình phân tích cú pháp xml có thể phân tích cú pháp html không?

LXML cung cấp API rất đơn giản và mạnh mẽ để phân tích XML và HTML. Nó hỗ trợ phân tích cú pháp một bước cũng như phân tích cú pháp từng bước bằng API điều khiển sự kiện (hiện chỉ dành cho XML).

Quy trình thiết lập thông thường:

>>> from lxml import etree

Các ví dụ sau cũng sử dụng Stringio hoặc byte để hiển thị cách phân tích từ các tệp và các đối tượng giống như tệp. Cả hai đều có sẵn trong mô -đun IO:

from io import StringIO, BytesIO

Trình phân tích cú pháp

Phân tích cú pháp được đại diện bởi các đối tượng phân tích cú pháp. Có sự hỗ trợ để phân tích cú pháp cả XML và (bị hỏng) HTML. Lưu ý rằng XHTML được phân tích cú pháp tốt nhất là XML, phân tích cú pháp với trình phân tích cú pháp HTML có thể dẫn đến kết quả không mong muốn. Dưới đây là một ví dụ đơn giản để phân tích cú pháp XML từ chuỗi trong bộ nhớ:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'

Để đọc từ một tệp hoặc đối tượng giống như tệp, bạn có thể sử dụng hàm parse (), trả về một đối tượng ElementTree:

>>> tree = etree.parse(StringIO(xml))
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b xmlns="test"/></a>'

Lưu ý cách hàm parse () đọc từ một đối tượng giống như tệp ở đây. Nếu phân tích cú pháp được thực hiện từ một tệp thực, thì phổ biến hơn (và cũng có phần hiệu quả hơn) để truyền tên tệp:

>>> tree = etree.parse("doc/test.xml")

LXML có thể phân tích từ tệp cục bộ, URL HTTP hoặc URL FTP. Nó cũng tự động phát hiện và đọc các tệp XML được áp dụng GZIP (.GZ).

Nếu bạn muốn phân tích từ bộ nhớ và vẫn cung cấp URL cơ sở cho tài liệu (ví dụ: để hỗ trợ các đường dẫn tương đối trong Xinclude), bạn có thể chuyển đối số từ khóa base_url::

>>> root = etree.fromstring(xml, base_url="http://where.it/is/from.xml")

Tùy chọn phân tích cú pháp

Các trình phân tích cú pháp chấp nhận một số tùy chọn thiết lập làm đối số từ khóa. Ví dụ trên dễ dàng được mở rộng để làm sạch các không gian tên trong quá trình phân tích cú pháp:

>>> parser = etree.XMLParser(ns_clean=True)
>>> tree   = etree.parse(StringIO(xml), parser)
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b/></a>'

Các đối số từ khóa trong hàm tạo chủ yếu dựa trên cấu hình trình phân tích cú pháp LibXML2. DTD cũng sẽ được tải nếu xác thực hoặc giá trị mặc định thuộc tính được yêu cầu.

Các đối số từ khóa Boolean có sẵn:

  • Thuộc tính_defaults - Đọc DTD (nếu được tham chiếu bởi tài liệu) và thêm các thuộc tính mặc định từ nó
  • DTD_VALIDMATION - Xác thực trong khi phân tích cú pháp (nếu DTD được tham chiếu)
  • load_dtd - tải và phân tích DTD trong khi phân tích cú pháp (không thực hiện xác thực)
  • NO_Network - Ngăn quyền truy cập mạng khi tìm kiếm các tài liệu bên ngoài (theo mặc định)
  • NS_CLEAN - Cố gắng làm sạch các khai báo không gian tên dự phòng
  • Phục hồi - Cố gắng hết sức để phân tích qua XML bị hỏng
  • remove_blank_text - loại bỏ các nút văn bản trống giữa các thẻ, còn được gọi là khoảng trắng không đáng tin. Điều này được sử dụng tốt nhất cùng với DTD hoặc lược đồ (cho biết dữ liệu và tiếng ồn), nếu không thì một heuristic sẽ được áp dụng.
  • remove_comments - loại bỏ nhận xét
  • Remove_Pis - HƯỚNG DẪN Xử lý loại bỏ
  • Strip_cdata - Thay thế các phần CDATA bằng nội dung văn bản bình thường (theo mặc định)
  • resolv
  • khổng lồ_tree - Vô hiệu hóa các hạn chế bảo mật và hỗ trợ cây rất sâu và nội dung văn bản rất dài (chỉ ảnh hưởng đến libxml2 2.7+)
  • Compact - Sử dụng lưu trữ nhỏ gọn cho nội dung văn bản ngắn (theo mặc định)
  • ColleM_IDS - Thu thập ID XML trong bảng băm trong khi phân tích cú pháp (theo mặc định). Vô hiệu hóa điều này có thể tăng tốc đáng kể việc tăng tốc độ phân tích các tài liệu với nhiều ID khác nhau nếu tra cứu băm không được sử dụng sau đó.

Các đối số từ khóa khác:

  • Mã hóa - ghi đè mã hóa tài liệu
  • Target - Đối tượng mục tiêu phân tích cú pháp sẽ nhận được các sự kiện Parse (xem Giao diện trình phân tích cú pháp đích)
  • Schema - XMLSchema để xác nhận (xem xác thực)

Nhật ký lỗi

Trình phân tích cú pháp có thuộc tính ERROR_LOG liệt kê các lỗi và cảnh báo của trình phân tích cú pháp cuối cùng:

>>> parser = etree.XMLParser()
>>> print(len(parser.error_log))
0

>>> tree = etree.XML("<root>\n</b>", parser)  # doctest: +ELLIPSIS
Traceback (most recent call last):
  ...
lxml.etree.XMLSyntaxError: Opening and ending tag mismatch: root line 1 and b, line 2, column 5...

>>> print(len(parser.error_log))
1

>>> error = parser.error_log[0]
>>> print(error.message)
Opening and ending tag mismatch: root line 1 and b
>>> print(error.line)
2
>>> print(error.column)
5

Mỗi mục trong nhật ký có các thuộc tính sau:

  • Tin nhắn: Văn bản tin nhắn
  • Tên miền: ID miền (xem lớp lxml.etree.errordomains)
  • Loại: ID loại tin nhắn (xem lớp lxml.etree.errortypes)
  • Cấp độ: ID cấp nhật ký (xem lớp lxml.etree.errorlevels)
  • Dòng: dòng mà thông báo bắt nguồn (nếu có)
  • Cột: Cột ký tự mà thông báo bắt nguồn (nếu có)
  • Tên tệp: Tên của tệp có nguồn gốc thông báo (nếu có)

Để thuận tiện, cũng có ba thuộc tính cung cấp tên có thể đọc được cho các giá trị ID:

  • domain_name
  • type_name
  • level_name

Để lọc cho một loại thông báo cụ thể, hãy sử dụng các phương thức bộ lọc _*() khác nhau trên nhật ký lỗi (xem lớp lxml.etree._listerrorlog).filter_*() methods on the error log (see the lxml.etree._ListErrorLog class).

Phân tích cú pháp HTML

Phân tích cú pháp HTML cũng đơn giản tương tự. Các trình phân tích cú pháp có một đối số từ khóa khôi phục mà HTMLPARSER đặt theo mặc định. Nó cho phép libxml2 cố gắng hết sức để trả về một cây HTML hợp lệ với tất cả nội dung mà nó có thể quản lý để phân tích. Nó sẽ không nêu ra một ngoại lệ đối với các lỗi phân tích cú pháp. Bạn nên sử dụng LibXML2 phiên bản 2.6.21 hoặc mới hơn để tận dụng tính năng này.

>>> broken_html = "<html><head><title>test<body><h2>page title</h3>"

>>> parser = etree.HTMLParser()
>>> tree   = etree.parse(StringIO(broken_html), parser)

>>> result = etree.tostring(tree.getroot(),
...                         pretty_print=True, method="html")
>>> print(result)
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <h2>page title</h2>
  </body>
</html>

LXML có chức năng HTML, tương tự như phím tắt XML được biết đến từ ElementTree:

>>> html = etree.HTML(broken_html)
>>> result = etree.tostring(html, pretty_print=True, method="html")
>>> print(result)
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <h2>page title</h2>
  </body>
</html>

Hỗ trợ phân tích HTML bị hỏng phụ thuộc hoàn toàn vào thuật toán phục hồi của LibXML2. Đó không phải là lỗi của LXML nếu bạn tìm thấy các tài liệu bị hỏng quá nhiều đến nỗi trình phân tích cú pháp không thể xử lý chúng. Cũng không có gì đảm bảo rằng cây kết quả sẽ chứa tất cả dữ liệu từ tài liệu gốc. Trình phân tích cú pháp có thể phải giảm các bộ phận bị hỏng nghiêm trọng khi đấu tranh để tiếp tục phân tích cú pháp. Đặc biệt các thẻ meta bị đặt sai vị trí có thể bị ảnh hưởng này, điều này có thể dẫn đến các vấn đề mã hóa.

Lưu ý rằng kết quả là một cây HTML hợp lệ, nhưng nó có thể không phải là cây XML được hình thành tốt. Ví dụ, XML cấm các dấu gạch ngang kép trong các bình luận, mà trình phân tích cú pháp HTML sẽ vui vẻ chấp nhận trong chế độ khôi phục. Do đó, nếu mục tiêu của bạn là nối tiếp một tài liệu HTML dưới dạng tài liệu XML/XHTML sau khi phân tích cú pháp, bạn có thể phải áp dụng một số tiền xử lý thủ công trước.

Cũng lưu ý rằng trình phân tích cú pháp HTML có nghĩa là phân tích các tài liệu HTML. Đối với các tài liệu XHTML, hãy sử dụng trình phân tích cú pháp XML, là không gian tên.

Thông tin doctype

Việc sử dụng các trình phân tích cú pháp LibXML2 cung cấp một số thông tin bổ sung có sẵn ở cấp API. Hiện tại, các đối tượng ElementTree có thể truy cập thông tin docType được cung cấp bởi một tài liệu được phân tích cú pháp, cũng như phiên bản XML và mã hóa gốc. Kể từ LXML 3.5, các tài liệu tham khảo doctype có thể thay đổi.

from io import StringIO, BytesIO
0

Giao diện trình phân tích cú pháp đích

Như trong ElementTree và tương tự như trình xử lý sự kiện sax, bạn có thể chuyển một đối tượng đích cho trình phân tích cú pháp:

from io import StringIO, BytesIO
1

Điều quan trọng đối với phương thức .Close () là đặt lại mục tiêu phân tích cú pháp về trạng thái có thể sử dụng, để bạn có thể sử dụng lại trình phân tích cú pháp thường xuyên như bạn muốn:

from io import StringIO, BytesIO
2

Bắt đầu với LXML 2.3, phương thức .Close () cũng sẽ được gọi trong trường hợp lỗi. Điều này khác với hành vi của ElementTree, nhưng cho phép các đối tượng mục tiêu làm sạch trạng thái của chúng trong mọi tình huống, để trình phân tích cú pháp có thể sử dụng lại chúng sau đó.

from io import StringIO, BytesIO
3

Lưu ý rằng trình phân tích cú pháp không xây dựng cây khi sử dụng mục tiêu phân tích cú pháp. Kết quả của trình phân tích cú pháp là bất kỳ đối tượng đích nào trả về từ phương thức .close () của nó. Nếu bạn muốn trả lại một cây XML ở đây, bạn phải tạo nó một cách lập trình trong đối tượng đích. Một ví dụ cho một mục tiêu phân tích cú pháp xây dựng cây là người tìm kiếm:

from io import StringIO, BytesIO
4

Giao diện phân tích cú pháp thức ăn

Kể từ LXML 2.0, các trình phân tích cú pháp có giao diện phân tích cú pháp thức ăn tương thích với trình phân tích cú pháp ElementTree. Bạn có thể sử dụng nó để cung cấp dữ liệu vào trình phân tích cú pháp theo từng bước được kiểm soát.

Trong lxml.etree, bạn có thể sử dụng cả hai giao diện cho trình phân tích cú pháp cùng một lúc: hàm parse () hoặc xml () và giao diện trình phân tích cú pháp. Cả hai đều độc lập và sẽ không xung đột (trừ khi được sử dụng cùng với đối tượng mục tiêu phân tích cú pháp như được mô tả ở trên).

Để bắt đầu phân tích cú pháp với trình phân tích cú pháp thức ăn, chỉ cần gọi phương thức Feed () để cung cấp cho nó một số dữ liệu.

from io import StringIO, BytesIO
5

Khi bạn hoàn thành phân tích cú pháp, bạn phải gọi phương thức Close () để truy xuất phần tử gốc của tài liệu kết quả phân tích cú pháp và để mở khóa trình phân tích cú pháp:must call the close() method to retrieve the root Element of the parse result document, and to unlock the parser:

from io import StringIO, BytesIO
6

Nếu bạn không gọi Close (), trình phân tích cú pháp sẽ bị khóa và các nguồn cấp dữ liệu tiếp theo sẽ tiếp tục nối thêm dữ liệu, thường dẫn đến một tài liệu không được hình thành và lỗi trình phân tích cú pháp không mong muốn. Vì vậy, hãy chắc chắn rằng bạn luôn đóng trình phân tích cú pháp sau khi sử dụng, cũng trong trường hợp ngoại lệ.

Một cách khác để đạt được phân tích từng bước tương tự là viết đối tượng giống như tệp của riêng bạn, trả về một đoạn dữ liệu trên mỗi cuộc gọi đọc (). Trong trường hợp giao diện phân tích cú pháp cấp cho phép bạn chủ động chuyển các khối dữ liệu vào trình phân tích cú pháp, một đối tượng giống như tệp trả lời một cách thụ động với các yêu cầu đọc () của chính trình phân tích cú pháp. Tùy thuộc vào nguồn dữ liệu, một trong hai cách có thể tự nhiên hơn.

Lưu ý rằng trình phân tích cú pháp nguồn cấp dữ liệu có nhật ký lỗi riêng được gọi là Feed_error_log. Lỗi trong trình phân tích cú pháp cấp không hiển thị trong ERROR_LOG bình thường và ngược lại.

Bạn cũng có thể kết hợp giao diện trình phân tích cú pháp Feed với trình phân tích cú pháp đích:

from io import StringIO, BytesIO
7

Một lần nữa, điều này ngăn chặn việc tạo tự động của cây XML và để lại tất cả các sự kiện xử lý đến đối tượng đích. Phương thức đóng () của trình phân tích cú pháp chuyển tiếp giá trị trả về của phương thức đóng () của mục tiêu.

Phân tích sự kiện gia tăng

Trong Python 3.4, gói xml.etree.elementtree đã đạt được một phần mở rộng cho giao diện phân tích cú pháp thức ăn được thực hiện bởi lớp XMLPullPARSER. Nó cũng cho phép xử lý các sự kiện phân tích cú pháp sau mỗi bước phân tích cú pháp gia tăng, bằng cách gọi phương thức .Read_events () và lặp lại kết quả. Điều này hữu ích nhất cho các môi trường thực thi không chặn trong đó các khối dữ liệu đến từng người khác và nên được xử lý càng xa càng tốt trong mỗi bước.

Tính năng tương tự có sẵn trong LXML 3.3. Việc sử dụng cơ bản như sau:

from io import StringIO, BytesIO
8

Giống như trình phân tích cú pháp nguồn cấp thông thường, XMLPullParser xây dựng một cây trong bộ nhớ (và bạn nên luôn gọi phương thức .Close () khi thực hiện với phân tích cú pháp):

from io import StringIO, BytesIO
9

Tuy nhiên, vì trình phân tích cú pháp cung cấp quyền truy cập gia tăng vào cây đó, bạn có thể xóa rõ ràng nội dung mà bạn không còn cần khi bạn đã xử lý nó. Đọc phần về sửa đổi cây bên dưới để xem bạn có thể làm gì ở đây và loại sửa đổi nào bạn nên tránh.

Trong LXML, nó đủ để gọi phương thức .Read_events () một lần vì trình lặp nó trả về có thể được sử dụng lại khi có sẵn các sự kiện mới.

Ngoài ra, như đã biết từ các trình lặp khác trong LXML, bạn có thể chuyển một đối số thẻ chọn các sự kiện phân tích được trả về bởi trình lặp .read_events ().

Loại sự kiện

Các sự kiện phân tích là bộ dữ liệu (kiểu sự kiện, đối tượng). Các loại sự kiện được hỗ trợ bởi ElementTree và LXML.etree là các chuỗi 'Bắt ​​đầu', 'End', 'Start-NS' và 'End-NS'. Các sự kiện 'bắt đầu' và 'kết thúc' đại diện cho các yếu tố mở và đóng. Chúng được đi kèm với thể hiện yếu tố tương ứng. Theo mặc định, chỉ các sự kiện 'kết thúc' được tạo ra, trong khi ví dụ trên yêu cầu tạo cả các sự kiện 'bắt đầu' và 'kết thúc'.(event-type, object). The event types supported by ElementTree and lxml.etree are the strings 'start', 'end', 'start-ns' and 'end-ns'. The 'start' and 'end' events represent opening and closing elements. They are accompanied by the respective Element instance. By default, only 'end' events are generated, whereas the example above requested the generation of both 'start' and 'end' events.

Các sự kiện 'Start-NS' và 'End-NS' thông báo về các tuyên bố không gian tên. Họ không đi kèm với các yếu tố. Thay vào đó, giá trị của sự kiện 'Start-NS' là một tuple (tiền tố, tên tên) chỉ định sự khởi đầu của ánh xạ không gian tên tiền tố. Sự kiện End-NS tương ứng không có giá trị (không có). Đó là thông lệ là sử dụng một danh sách như ngăn xếp không gian tên và bật mục cuối cùng trong sự kiện 'End-NS'.end-ns event does not have a value (None). It is common practice to use a list as namespace stack and pop the last entry on the 'end-ns' event.

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
0

Sửa đổi cây

Bạn có thể sửa đổi phần tử và con cháu của nó khi xử lý sự kiện 'kết thúc'. Ví dụ, để lưu bộ nhớ, bạn có thể xóa các cây con không còn cần thiết:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
1

CẢNH BÁO: Trong sự kiện 'bắt đầu', bất kỳ nội dung nào của yếu tố, chẳng hạn như con cháu, theo anh chị em hoặc văn bản, vẫn chưa có sẵn và không nên truy cập. Chỉ các thuộc tính được đảm bảo được đặt. Trong sự kiện 'kết thúc', phần tử và con cháu của nó có thể được sửa đổi tự do, nhưng không nên truy cập anh chị em sau đây. Trong một trong hai sự kiện, bạn không được sửa đổi hoặc di chuyển tổ tiên (cha mẹ) của yếu tố hiện tại. Bạn cũng nên tránh di chuyển hoặc loại bỏ chính yếu tố. Quy tắc vàng là: Không chạm vào bất cứ thứ gì sẽ phải được chạm vào một lần nữa bởi trình phân tích cú pháp sau này.: During the 'start' event, any content of the element, such as the descendants, following siblings or text, is not yet available and should not be accessed. Only attributes are guaranteed to be set. During the 'end' event, the element and its descendants can be freely modified, but its following siblings should not be accessed. During either of the two events, you must not modify or move the ancestors (parents) of the current element. You should also avoid moving or discarding the element itself. The golden rule is: do not touch anything that will have to be touched again by the parser later on.

Nếu bạn có các phần tử có danh sách dài trẻ em trong tệp XML của mình và muốn lưu thêm bộ nhớ trong quá trình phân tích cú pháp, bạn có thể dọn dẹp anh chị em trước của phần tử hiện tại:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
2

Vòng lặp trong khi xóa nhiều anh chị em liên tiếp. Điều này chỉ cần thiết nếu bạn bỏ qua một số trong số họ bằng đối số từ khóa thẻ. Nếu không, một đơn giản nếu nên làm. Thẻ của bạn càng chọn lọc, tuy nhiên, bạn sẽ phải nghĩ rằng bạn sẽ phải tìm ra cách đúng cách để làm sạch các yếu tố đã bị bỏ qua. Do đó, đôi khi dễ dàng đi qua tất cả các yếu tố và thực hiện lựa chọn thẻ bằng tay trong mã xử lý sự kiện.

Sự kiện thẻ chọn lọc

Là một phần mở rộng trên ElementTree, lxml.etree chấp nhận một đối số từ khóa thẻ giống như Element.iter (TAG). Điều này giới hạn các sự kiện ở một thẻ hoặc không gian tên cụ thể:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
3

Các sự kiện có mục tiêu tùy chỉnh

Bạn có thể kết hợp trình phân tích cú pháp kéo với mục tiêu phân tích cú pháp. Trong trường hợp đó, trách nhiệm của mục tiêu là tạo ra các giá trị sự kiện. Bất cứ điều gì nó trở lại từ các phương thức .start () và .end () của nó sẽ được trình phân tích cú pháp kéo trả lại dưới dạng mục thứ hai của các sự kiện Parse.

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
4

Như bạn có thể thấy, các giá trị sự kiện thậm chí không phải là đối tượng phần tử. Mục tiêu thường tự do quyết định cách nó muốn tạo một cây XML hoặc bất cứ thứ gì khác mà nó muốn thực hiện các cuộc gọi lại của trình phân tích cú pháp. Tuy nhiên, trong nhiều trường hợp, bạn sẽ muốn làm cho mục tiêu tùy chỉnh của mình kế thừa từ lớp TreeBuilder để xây dựng một cây mà bạn có thể xử lý bình thường. Các phương thức Start () và .end () của TreeBuilder trả về đối tượng phần tử đã được tạo, do đó bạn có thể ghi đè chúng và sửa đổi đầu vào hoặc đầu ra theo nhu cầu của bạn. Dưới đây là một ví dụ cho thấy các thuộc tính bộ lọc trước khi chúng được thêm vào cây:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
5

iterparse và iterwalk

Như đã biết từ ElementTree, hàm tiện ích iterparse () trả về một trình lặp tạo ra các sự kiện phân tích cú pháp cho tệp XML (hoặc đối tượng giống như tệp), trong khi xây dựng cây. Bạn có thể nghĩ về nó như một trình bao bọc chặn xung quanh XMLPullPARSER tự động đọc dữ liệu từ tệp đầu vào cho bạn và cung cấp một trình lặp lại cho họ:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
6

Sau khi phân tích cú pháp, cây kết quả có sẵn thông qua thuộc tính gốc của trình lặp:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
7

Các loại sự kiện khác có thể được kích hoạt với đối số từ khóa của sự kiện:

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
8

iterparse () cũng hỗ trợ đối số thẻ cho lần lặp sự kiện chọn lọc và một số tham số khác kiểm soát thiết lập trình phân tích cú pháp. Đối số thẻ có thể là một thẻ duy nhất hoặc một chuỗi các thẻ. Bạn cũng có thể sử dụng nó để phân tích đầu vào HTML bằng cách chuyển HTML = true.

ITERWALK

Để thuận tiện, LXML cũng cung cấp chức năng iterWalk (). Nó hoạt động chính xác giống như iterparse (), nhưng hoạt động trên các phần tử và phần tử. Dưới đây là một ví dụ cho một cây được phân tích cú pháp bởi iterparse ():

>>> xml = '<a xmlns="test"><b xmlns="test"/></a>'

>>> root = etree.fromstring(xml)
>>> etree.tostring(root)
b'<a xmlns="test"><b xmlns="test"/></a>'
9

Và bây giờ chúng ta có thể lấy cây trong bộ nhớ kết quả và lặp lại nó bằng IterWalk () để có được các sự kiện chính xác mà không cần phân tích lại đầu vào:

>>> tree = etree.parse(StringIO(xml))
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b xmlns="test"/></a>'
0

Để tránh lãng phí thời gian vào các bộ phận không quan tâm của cây, trình lặp iterwalk có thể được hướng dẫn bỏ qua toàn bộ cây con với phương thức .skip_subtree () của nó.

>>> tree = etree.parse(StringIO(xml))
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b xmlns="test"/></a>'
1

Lưu ý rằng .skip_subtree () chỉ có hiệu ứng khi xử lý các sự kiện bắt đầu hoặc bắt đầu.start-ns events.

Chuỗi Python Unicode

lxml.etree có hỗ trợ rộng hơn cho chuỗi unicode python so với thư viện ElementTree. Trước hết, nơi ElementTree sẽ tăng một ngoại lệ, các trình phân tích cú pháp trong LXML.ETREE có thể xử lý các chuỗi Unicode ngay lập tức. Điều này hữu ích nhất cho các đoạn trích XML được nhúng trong mã nguồn bằng hàm xml ():

>>> tree = etree.parse(StringIO(xml))
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b xmlns="test"/></a>'
2

Tuy nhiên, điều này đòi hỏi các chuỗi Unicode không chỉ định một bản mã hóa mâu thuẫn và do đó nói dối về mã hóa thực sự của chúng:

>>> tree = etree.parse(StringIO(xml))
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b xmlns="test"/></a>'
3

Tương tự, bạn sẽ nhận được lỗi khi bạn thử tương tự với dữ liệu HTML trong chuỗi unicode chỉ định một ký tự trong thẻ meta của tiêu đề. Nói chung, bạn nên tránh chuyển đổi dữ liệu XML/HTML thành Unicode trước khi chuyển nó vào trình phân tích cú pháp. Nó đều chậm hơn và dễ bị lỗi.

Tuần tự đến chuỗi unicode

Để tuần tự hóa kết quả, thông thường bạn sẽ sử dụng hàm mô -đun toString (), được tuần tự hóa thành ASCII đơn giản theo mặc định hoặc một số mã hóa byte khác nếu được yêu cầu:

>>> tree = etree.parse(StringIO(xml))
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b xmlns="test"/></a>'
4

Là một phần mở rộng, LXML.ETREE nhận ra tên 'Unicode' là một đối số cho tham số mã hóa để xây dựng biểu diễn unicode Python của một cây:

>>> tree = etree.parse(StringIO(xml))
>>> etree.tostring(tree.getroot())
b'<a xmlns="test"><b xmlns="test"/></a>'
5

Kết quả của toString (mã hóa = 'unicode') có thể được xử lý như bất kỳ chuỗi unicode python nào khác và sau đó được chuyển trở lại vào các trình phân tích cú pháp. Tuy nhiên, nếu bạn muốn lưu kết quả vào một tệp hoặc chuyển nó qua mạng, bạn nên sử dụng Write () hoặc toString () với mã hóa byte (thường là UTF-8) để tuần tự hóa XML. Lý do chính là các chuỗi unicode được trả về bởi toString (mã hóa = 'unicode') không phải là các luồng byte và chúng không bao giờ có khai báo XML để chỉ định mã hóa của chúng. Các chuỗi này rất có thể không thể phân tích được bởi các thư viện XML khác.tostring(encoding='unicode') can be treated like any other Python unicode string and then passed back into the parsers. However, if you want to save the result to a file or pass it over the network, you should use write() or tostring() with a byte encoding (typically UTF-8) to serialize the XML. The main reason is that unicode strings returned by tostring(encoding='unicode') are not byte streams and they never have an XML declaration to specify their encoding. These strings are most likely not parsable by other XML libraries.

Đối với mã hóa byte bình thường, hàm toString () tự động thêm một khai báo khi cần thiết phản ánh mã hóa của chuỗi được trả về. Điều này giúp các trình phân tích cú pháp khác có thể phân tích chính xác luồng byte XML. Lưu ý rằng sử dụng toString () với UTF-8 cũng nhanh hơn đáng kể trong hầu hết các trường hợp.

HTML có thể được phân tích cú pháp không?

Phân tích cú pháp HTML liên quan đến việc xây dựng mã thông báo và xây dựng cây. Mã thông báo HTML bao gồm các thẻ bắt đầu và kết thúc, cũng như tên và giá trị thuộc tính. Nếu tài liệu được hình thành tốt, phân tích cú pháp thì đơn giản và nhanh hơn. Trình phân tích cú pháp phân tích cú pháp đầu vào vào tài liệu, xây dựng cây tài liệu.. HTML tokens include start and end tags, as well as attribute names and values. If the document is well-formed, parsing it is straightforward and faster. The parser parses tokenized input into the document, building up the document tree.

HTML có thể được phân tích cú pháp bởi regex không?

HTML không phải là ngôn ngữ thông thường và do đó không thể phân tích được các biểu thức thông thường.Các truy vấn của Regex không được trang bị để chia HTML thành các phần có ý nghĩa của nó.cannot be parsed by regular expressions. Regex queries are not equipped to break down HTML into its meaningful parts.

Trình phân tích cú pháp XML được sử dụng để làm gì?

Một trình phân tích cú pháp XML được sử dụng cho tài liệu XML.Nó đọc tài liệu và phân tích cấu trúc tài liệu và các thuộc tính dữ liệu.Trình phân tích phân chia dữ liệu thành nhiều phần để sử dụng các thành phần khác.Có hai loại trình phân tích cú pháp XML: trình phân tích cú pháp không xác thực và trình phân tích cú pháp xác thực.XML document. It reads the document and analysis the document structure and the data properties. The parser splits the data into many parts for the use of other components. There are two kinds of XML parsers: non-validating parsers and validating parsers.

Trình phân tích cú pháp HTML tốt nhất là gì?

Trình phân tích cú pháp HTML nhanh nhất: Python vs Ruby vs Java vs C vs Golang vs Ruby vs Node ...
Những người biểu diễn tốt nhất là Golang và C với kết quả rất giống nhau ..
Python libxml2 hoạt động khá tốt ..
Ruby Speed tương tự như Python ..
Máy phân tích cú pháp Java được kiểm tra chậm hơn ..
Perl Parser khá lỗi thời như ngôn ngữ ..