Phân tích cú pháp XML bằng Python

0
306

Bài viết này tập trung vào cách người ta có thể phân tích cú pháp một tệp XML nhất định và trích xuất một số dữ liệu hữu ích từ nó theo cách có cấu trúc.

XML: XML là viết tắt của eXtensible Markup Language. Nó được thiết kế để lưu trữ và vận chuyển dữ liệu. Nó được thiết kế để người và máy đều có thể đọc được. Đó là lý do tại sao, các mục tiêu thiết kế của XML nhấn mạnh vào tính đơn giản, tính tổng quát và khả năng sử dụng trên Internet.
Tệp XML được phân tích cú pháp trong hướng dẫn này thực sự là một nguồn cấp dữ liệu RSS.

RSS: RSS (Rich Site Summary, thường được gọi là Really Simple Syndication) sử dụng một nhóm các định dạng nguồn cấp dữ liệu web tiêu chuẩn để xuất bản các mục blog, tiêu đề tin tức, âm thanh, video được cập nhật thường xuyên. RSS là văn bản thuần túy được định dạng XML.

  • Bản thân định dạng RSS tương đối dễ đọc bởi các quy trình tự động và cả con người.
  • RSS được xử lý trong hướng dẫn này là nguồn RSS của các tin bài hàng đầu từ một trang web tin tức phổ biến. Bạn có thể kiểm tra nó ở đây . Mục tiêu của chúng tôi là xử lý nguồn cấp RSS này (hoặc tệp XML) và lưu nó ở một số định dạng khác để sử dụng trong tương lai.

Mô-đun Python được sử dụng: Bài viết này sẽ tập trung vào việc sử dụng mô-đun xml có sẵn trong python để phân tích cú pháp XML và trọng tâm chính sẽ là API ElementTree XML của mô-đun này.

Thực hiện:

                #Python code to illustrate parsing of XML files 


                # importing the required modules 


                import 
                csv 


                import 
                requests 


                import 
                xml.etree.ElementTree as ET 





                def 
                loadRSS(): 






                # url of rss feed 



                url 
                = 
                'http://www.hindustantimes.com/rss/topnews/rssfeed.xml'






                # creating HTTP response object from given url 



                resp 
                = 
                requests.get(url) 






                # saving the xml file 



                with 
                open
                (
                'topnewsfeed.xml'
                , 
                'wb'
                ) as f: 



                f.write(resp.content) 








                def 
                parseXML(xmlfile): 






                # create element tree object 



                tree 
                = 
                ET.parse(xmlfile) 






                # get root element 



                root 
                = 
                tree.getroot() 






                # create empty list for news items 



                newsitems 
                = 
                [] 






                # iterate news items 



                for 
                item 
                in 
                root.findall(
                './channel/item'
                ): 






                # empty news dictionary 



                news 
                = 
                {} 






                # iterate child elements of item 



                for 
                child 
                in 
                item: 






                # special checking for namespace object content:media 



                if 
                child.tag 
                =
                = 
                '{http://search.yahoo.com/mrss/}content'
                : 



                news[
                'media'
                ] 
                = 
                child.attrib[
                'url'
                ] 



                else
                : 



                news[child.tag] 
                = 
                child.text.encode(
                'utf8'
                ) 






                # append news dictionary to news items list 



                newsitems.append(news) 






                # return news items list 



                return 
                newsitems 








                def 
                savetoCSV(newsitems, filename): 






                # specifying the fields for csv file 



                fields 
                = 
                [
                'guid'
                , 
                'title'
                , 
                'pubDate'
                , 
                'description'
                , 
                'link'
                , 
                'media'
                ] 






                # writing to csv file 



                with 
                open
                (filename, 
                'w'
                ) as csvfile: 






                # creating a csv dict writer object 



                writer 
                = 
                csv.DictWriter(csvfile, fieldnames 
                = 
                fields) 






                # writing headers (field names) 



                writer.writeheader() 






                # writing data rows 



                writer.writerows(newsitems) 








                def 
                main(): 



                # load rss from web to update existing xml file 



                loadRSS() 






                # parse xml file 



                newsitems 
                = 
                parseXML(
                'topnewsfeed.xml'
                ) 






                # store news items in a csv file 



                savetoCSV(newsitems, 
                'topnews.csv'
                ) 








                if 
                __name__ 
                =
                = 
                "__main__"
                : 






                # calling main function 



                main() 

Đoạn mã trên sẽ:

  • Tải nguồn cấp dữ liệu RSS từ URL được chỉ định và lưu nó dưới dạng tệp XML.
  • Phân tích cú pháp tệp XML để lưu tin tức dưới dạng danh sách từ điển trong đó mỗi từ điển là một mục tin tức duy nhất.
  • Lưu các mục tin tức vào một tệp CSV.

Hãy để chúng tôi cố gắng hiểu mã theo từng phần:

  • Đang tải và lưu nguồn cấp dữ liệu RSS def loadRSS (): # url của nguồn cấp dữ liệu rss url = ‘http://www.hindustantimes.com/rss/topnews/rssfeed.xml’ # tạo đối tượng phản hồi HTTP từ url nhất định res = request.get (url) # lưu tệp xml với open (‘topnewsfeed.xml’, ‘wb’) là f: f.write (tương ứng) Ở đây, đầu tiên chúng tôi tạo một đối tượng phản hồi HTTP bằng cách gửi một yêu cầu HTTP đến URL của nguồn cấp RSS. Nội dung phản hồi hiện chứa dữ liệu tệp XML mà chúng tôi lưu dưới dạng topnewsfeed.xml trong thư mục cục bộ của chúng tôi.
  • Phân tích cú pháp XML
    Chúng tôi đã tạo hàm parseXML () để phân tích cú pháp tệp XML. Chúng ta biết rằng XML là một định dạng dữ liệu phân cấp vốn có và cách tự nhiên nhất để biểu diễn nó là bằng một cây. Hãy xem hình ảnh bên dưới chẳng hạn:
phân tích cú pháp XML

Ở đây, chúng tôi đang sử dụng mô-đun xml.etree.ElementTree (gọi tắt là ET). Cây phần tử có hai lớp cho mục đích này – ElementTree đại diện cho toàn bộ
tài liệu XML dưới dạng một cây và Phần tử đại diện cho một nút duy nhất trong cây này. Tương tác với toàn bộ tài liệu (đọc và ghi vào / từ tệp) thường được thực hiện ở cấp ElementTree . Tương tác với một phần tử XML duy nhất và các phần tử con của nó được thực hiện ở mức Phần tử .

Được rồi, bây giờ chúng ta hãy xem qua hàm parseXML () :

tree = ET.parse (xmlfile)

Ở đây, chúng tôi tạo một đối tượng ElementTree bằng cách phân tích cú pháp xmlfile đã truyền .

root = tree.getroot ()

Hàm getroot () trả về gốc của cây dưới dạng một đối tượng Phần tử .

cho mục trong root.findall ('./ channel / item'):

Bây giờ, khi bạn đã xem xét cấu trúc tệp XML của mình, bạn sẽ nhận thấy rằng chúng tôi chỉ quan tâm đến phần tử item .
./channel/item thực sự là cú pháp XPath (XPath là một ngôn ngữ để giải quyết các phần của tài liệu XML). Ở đây, chúng tôi muốn tìm tất cả các mục con của các kênh con của phần tử gốc (ký hiệu là ‘.’).

cho mục trong root.findall ('./ channel / item'):         
# từ điển tin tức trống
tin tức = {}
# lặp lại các phần tử con của mục
cho trẻ em trong mục:
# kiểm tra đặc biệt cho nội dung đối tượng không gian tên: media if child.tag == '{http://search.yahoo.com/mrss/}content': news ['media'] = child.attrib ['url']
khác:
news [child.tag] = child.text.encode ('utf8')
# nối từ điển tin tức vào danh sách tin tức
newsitems.append (tin tức)

Khóa học PYTHON (IPD2020) cho người mới bắt đầu