यदि वे regexp का उपयोग नहीं कर रहे हैं तो HTML parses कैसे काम करते हैं?


96

मैं हर दिन कुछ प्रश्न देखता हूं कि कुछ HTML स्ट्रिंग से कुछ कैसे पार्स या निकाला जाता है और पहला उत्तर / टिप्पणी हमेशा होती है "HTML का उपयोग करने के लिए RegEx का उपयोग न करें, ऐसा न हो कि आपको क्रोध महसूस हो!" (वह अंतिम भाग कभी-कभी छोड़ा जाता है)।

यह मेरे लिए भ्रामक है, मैंने हमेशा सोचा था कि सामान्य तौर पर, किसी भी जटिल स्ट्रिंग को पार्स करने का सबसे अच्छा तरीका एक नियमित अभिव्यक्ति का उपयोग करना है। तो HTML पार्सर कैसे काम करता है? क्या यह पार्स करने के लिए नियमित अभिव्यक्तियों का उपयोग नहीं करता है।

एक नियमित अभिव्यक्ति का उपयोग करने के लिए एक विशेष तर्क यह है कि हमेशा एक पार्सिंग विकल्प नहीं होता है (जैसे जावास्क्रिप्ट, जहां DOMDocument एक सार्वभौमिक रूप से उपलब्ध विकल्प नहीं है)। उदाहरण के लिए jQuery, HTML स्ट्रिंग को DOM नोड्स में बदलने के लिए regex का उपयोग करके ठीक प्रबंधन करता है।

यह सुनिश्चित करने के लिए नहीं कि यह सीडब्ल्यू है या नहीं, यह एक वास्तविक सवाल है जिसका मैं उत्तर देना चाहता हूं और वास्तव में चर्चा का धागा नहीं बनना चाहता।


पार्सिंग और html- पार्सिंग को जोड़ने के लिए रेट किया गया - @Andy E, मुझे आशा है कि आपके साथ ठीक है - मुझे लगा कि यह मददगार होगा।
JXG

@ जेएक्सजी: यह मेरे साथ ठीक है, धन्यवाद :-)
एंडी ई

जवाबों:


65

आमतौर पर एक टोकन का उपयोग करके। HTML5 विनिर्देश के मसौदे में "वास्तविक दुनिया HTML" को संभालने के लिए एक व्यापक एल्गोरिथ्म है


1
अच्छा लगता है ... उद्धृत करने के लिए "इन मामलों को संभालने के लिए, पार्सरों में एक स्क्रिप्ट घोंसले का शिकार स्तर होता है, जिसे शुरू में शून्य पर सेट किया जाना चाहिए, और एक पार्सर ठहराव ध्वज, जिसे शुरू में झूठा होना चाहिए।" - दूसरे शब्दों में, आपको इसे खुद से पुनरावृत्त करना होगा और बहुत सारे कस्टम तर्क होने चाहिए: P
टिमोथी खौरी

1
वोट दें। कुछ प्रौद्योगिकी के बजाय एल्गोरिथम जटिलता पर जोर देना बेहतर है।
अर्निस लैप्सा

1
कस्टम तर्क के बहुत सारे के साथ अपने आप को इस तरह एक महान विचार नहीं है। यदि आप कर सकते हैं तो मानक एल्गोरिथ्म का समर्थन करने वाले पुस्तकालय का उपयोग करें। उदा। search.cpan.org/~tobyink/HTML-HTML5-Parser-0.03/lib/HTML/HTML5/… / code.google.com/p/html5lib
Quentin

8
HTML पार्सर के साथ प्राथमिक समस्या यह है कि किसी त्रुटि का सामना करने पर, आप "पार्स त्रुटि" को थूकना और उस पर छोड़ देना ठीक नहीं है। आप quirks मोड में प्रवेश करते हैं और आपके द्वारा सामना की गई गड़बड़ी से सबसे अच्छा बनाने की कोशिश करते हैं, जिसमें बेमेल टैग शामिल हैं, [{]} स्टाइल इंटरलेस, और सभी प्रकार की अजीबताएँ, परिणाम को जितना हो सके उतना अच्छा बनाने की कोशिश करें और अपरिहार्य कम से कम दर्दनाक विफलता ... यह ऐसी चीज नहीं है जिसे आप रेगेक्स के साथ कर सकते हैं।
एसएफ।

7
@ टिमोथी के: 'नोट: जिस तरह से इस एल्गोरिथ्म के कारण माता-पिता को बदलने के लिए तत्वों का कारण बनता है, उसे "गोद लेने वाली एजेंसी एल्गोरिथम" करार दिया गया है (गलत सामग्री से निपटने के लिए अन्य संभावित एल्गोरिदम के विपरीत, जिसमें "इंक एल्गोरिथम" शामिल था,) "गुप्त संबंध एल्गोरिथ्म", और "हाइजेनबर्ग एल्गोरिथ्म")। "
JXG

133

तो HTML पार्सर कैसे काम करता है? क्या यह पार्स करने के लिए नियमित अभिव्यक्ति का उपयोग नहीं करता है?

नहीं।

यदि आप अपने मस्तिष्क में गणना के पाठ्यक्रम के सिद्धांत तक वापस पहुंचते हैं, यदि आपने एक, या एक संकलक पाठ्यक्रम, या कुछ इसी तरह लिया है, तो आप याद कर सकते हैं कि विभिन्न प्रकार की भाषाएं और कम्प्यूटेशनल मॉडल हैं। मैं सभी विवरणों में जाने के लिए योग्य नहीं हूं, लेकिन मैं आपके साथ कुछ प्रमुख बिंदुओं की समीक्षा कर सकता हूं।

सबसे सरल प्रकार की भाषा और संगणना (इन उद्देश्यों के लिए) एक नियमित भाषा है। ये नियमित अभिव्यक्तियों के साथ उत्पन्न हो सकते हैं, और परिमित ऑटोमेटा के साथ पहचाने जा सकते हैं। मूल रूप से, इसका मतलब है कि इन भाषाओं में "पार्सिंग" तार राज्य का उपयोग करते हैं, लेकिन सहायक मेमोरी नहीं। HTML निश्चित रूप से एक नियमित भाषा नहीं है। यदि आप इसके बारे में सोचते हैं, तो टैग की सूची को मनमाने तरीके से गहराया जा सकता है। उदाहरण के लिए, टेबल में टेबल हो सकते हैं, और प्रत्येक टेबल में बहुत सारे नेस्टेड टैग हो सकते हैं। नियमित अभिव्यक्तियों के साथ, आप टैग की एक जोड़ी लेने में सक्षम हो सकते हैं, लेकिन निश्चित रूप से मनमाने ढंग से नेस्टेड कुछ भी नहीं।

एक क्लासिक सरल भाषा जो नियमित नहीं है, सही रूप से कोष्ठक से मेल खाती है। जितना हो सके प्रयास करें, आप कभी भी एक नियमित अभिव्यक्ति (या परिमित ऑटोमेटन) नहीं बना पाएंगे जो हमेशा काम करेगा। आपको घोंसले की गहराई का ट्रैक रखने के लिए मेमोरी की आवश्यकता होती है।

मेमोरी के लिए स्टैक के साथ एक राज्य मशीन कम्प्यूटेशनल मॉडल की अगली ताकत है। इसे पुश-डाउन ऑटोमेटन कहा जाता है, और यह संदर्भ-मुक्त व्याकरण द्वारा उत्पन्न भाषाओं को पहचानता है। यहां, हम सही ढंग से मिलान किए गए कोष्ठकों को पहचान सकते हैं - वास्तव में, एक स्टैक इसके लिए सही मेमोरी मॉडल है।

खैर, क्या यह HTML के लिए पर्याप्त है? दुख की बात है नहीं। शायद सुपर-डुपर के लिए एक्सएमएल को सावधानीपूर्वक मान्य किया गया था, वास्तव में, जिसमें सभी टैग हमेशा पूरी तरह से पंक्तिबद्ध होते हैं। वास्तविक दुनिया HTML में, आप आसानी से स्निपेट जैसे पा सकते हैं <b><i>wow!</b></i>। यह स्पष्ट रूप से घोंसला नहीं है, इसलिए इसे सही ढंग से पार्स करने के लिए, एक स्टैक बस पर्याप्त शक्तिशाली नहीं है।

गणना का अगला स्तर सामान्य व्याकरणों द्वारा उत्पन्न भाषाएं हैं, और ट्यूरिंग मशीनों द्वारा मान्यता प्राप्त है। यह आमतौर पर प्रभावी रूप से सबसे मजबूत कम्प्यूटेशनल मॉडल होने के लिए स्वीकार किया जाता है - एक राज्य मशीन, सहायक मेमोरी के साथ, जिसकी मेमोरी को कहीं भी संशोधित किया जा सकता है। यह वही है जो प्रोग्रामिंग भाषाएं कर सकती हैं। यह जटिलता का स्तर है जहां HTML रहता है।

एक वाक्य में यहां सब कुछ संक्षेप में प्रस्तुत करने के लिए: सामान्य HTML को पार्स करने के लिए, आपको एक वास्तविक प्रोग्रामिंग भाषा की आवश्यकता है, न कि एक नियमित अभिव्यक्ति।

HTML को उसी तरह पार्स किया जाता है जैसे अन्य भाषाओं को पार्स किया जाता है: लेक्सिंग और पार्सिंग। लेक्सिंग कदम अलग-अलग पात्रों की धारा को सार्थक टोकन में तोड़ देता है। पार्सिंग चरण टोकन को इकट्ठा करता है, राज्यों और मेमोरी का उपयोग करते हुए, एक तार्किक सुसंगत दस्तावेज़ में, जिस पर कार्रवाई की जा सकती है।


22

रेगुलर एक्सप्रेशन सिर्फ पार्सर का एक रूप है। पाठ को ठीक से व्याख्या करने के लिए पुनरावर्ती वंश , भविष्यवाणी और कई अन्य तकनीकों का उपयोग करके एक ईमानदार-से-अच्छाई HTML पार्सर काफी अधिक जटिल होगा, जो कि रेक्सक्स में व्यक्त किया जा सकता है । यदि आप वास्तव में इसे प्राप्त करना चाहते हैं, तो आप lex & yacc और इसी तरह के उपकरणों की जांच कर सकते हैं ।

HTML पार्सिंग के लिए रेगेक्स का उपयोग करने के खिलाफ निषेध को संभवतः अधिक सही रूप में लिखा जाना चाहिए: " HTML को पार्स करने के लिए भोले नियमित अभिव्यक्ति का उपयोग न करें ..." (ऐसा न हो कि आपको क्रोध महसूस हो) "... और सावधानी के साथ परिणामों का इलाज करें।" कुछ विशिष्ट लक्ष्यों के लिए, एक रेगीक्स पूरी तरह से पर्याप्त हो सकता है, लेकिन आपको अपने रेगेक्स की सीमाओं से अवगत होने के लिए बहुत सावधानी बरतने की आवश्यकता है और जैसा कि आपके द्वारा पाठ के स्रोत के लिए उपयुक्त है उपयोगकर्ता इनपुट, वास्तव में बहुत सावधान रहें)।


+1, एक अच्छा जवाब। मुझे स्वीकार करना चाहिए, मैंने HTML से पहले भी जब मैं नियंत्रण में नहीं था, तब भी रेगेक्स का उपयोग किया था, लेकिन सार्वजनिक रूप से जारी किए गए किसी भी प्रकार के आवेदन में नहीं। मैंने "क्रोध को महसूस किया" भी, क्योंकि यह अनुभवहीन था। लेकिन यह बहुत समय पहले था :-)
एंडी ई

6

Parsing HTML एक वृक्ष संरचना में एक रेखीय पाठ का परिवर्तन है। नियमित अभिव्यक्ति आम तौर पर पेड़ संरचनाओं को संभाल नहीं सकती है। अगले बिंदु पर हर समय होने वाले परिवर्तनों को प्राप्त करने के लिए आपको प्रत्येक बिंदु पर नियमित अभिव्यक्ति की आवश्यकता होती है। आप एक पार्सर में नियमित अभिव्यक्ति का उपयोग कर सकते हैं, लेकिन आपको पार्स करने की प्रत्येक संभावित स्थिति के लिए नियमित अभिव्यक्ति की एक पूरी सरणी की आवश्यकता होगी।


2

यदि आप 100% समाधान करना चाहते हैं: आपको अपना स्वयं का कस्टम कोड लिखना होगा जो HTML चरित्र-दर-वर्ण के माध्यम से पुनरावृत्त होता है और आपको यह निर्धारित करने के लिए कि आपके वर्तमान नोड को रोकना चाहिए और शुरू करने के लिए आपके पास तर्क की जबरदस्त मात्रा होनी चाहिए। आगे।

कारण यह है कि यह वैध HTML है:

<ul>
<li>One
<li>Two
<li>Three
</ul>

लेकिन ऐसा है:

<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>

यदि आप "90% समाधान" के साथ ठीक हैं: तो दस्तावेज़ को लोड करने के लिए XML पार्सर का उपयोग करना ठीक है। या फिर रेगेक्स का उपयोग करना (हालांकि xml आसान है यदि आप तब सामग्री के मास्टर हैं)।


4
एक XML पार्सर 1% समाधान की तरह अधिक है। XML को अच्छी तरह से बनाने वाले HTML दस्तावेजों की संख्या कम है।
क्वेंटिन

4
हां, वे करते हैं ... "चरित्र द्वारा चरित्र" को शाब्दिक रूप से नहीं लेते हैं, जैसा कि आप चीजों को स्ट्रीम करने का प्रयास कर सकते हैं। लेकिन मेरा कहना यह है कि आपको अपना पार्सर लिखना होगा। नए-पुराने प्रोग्रामर का उपयोग उस तरह के कोड को लिखने के लिए नहीं किया जाता है ... हम "HtmlDocumentUtility.Load" और उस जैसे सामान का उपयोग करते हैं :)
टिमोथी खौरी

4
@Andy E: Regexes कोई जादू नहीं है, वे चरित्र द्वारा भी काम करते हैं, जैसे किसी भी अन्य प्रकार के पार्सिंग, या हेक, किसी भी अन्य स्ट्रिंग फ़ंक्शन।
बार्ट वैन ह्युकेलोम

1
BTW: आपका पहला उदाहरण सिर्फ "अर्ध-वैध HTML" नहीं है। यह वास्तव में मान्य HTML 4.01 सख्त है। आप इसे सत्यापित करने के लिए उदाहरण के लिए W3C सत्यापनकर्ता का उपयोग कर सकते हैं। समापन टैग आधिकारिक तौर पर <li> (HTML 4 युक्ति देखें) के लिए वैकल्पिक है।
सालेके

2
@ बर्ट: अच्छा बिंदु, कभी-कभी मेरा मस्तिष्क सभी तर्क भूल जाता है और सोचता है कि चीजें जादू से काम करती हैं।
एंडी ई
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.