أفضل طريقة للعودة إلى استخدام قوة LXML بعد الاضطرار إلى استخدام Regex للعثور على شيء في مستند HTML

StackOverflow https://stackoverflow.com/questions/2421396

سؤال

أحاول مزق بعض النص من عدد كبير من وثائق HTML (الأرقام في مئات الآلاف). المستندات هي أشكالا حقا ولكنها تحضنها مجموعة كبيرة جدا من المنظمات المختلفة لذلك هناك اختلاف كبير في كيفية إنشاء المستند. على سبيل المثال، تنقسم المستندات إلى فصول. قد أرغب في استخراج محتويات الفصل 5 من كل وثيقة حتى أتمكن من تحليل محتوى الفصل. في البداية اعتقدت أن هذا سيكون من السهل ولكن اتضح أن المؤلفين قد يستخدمون مجموعة من الجداول غير المتداخلة في جميع أنحاء المستند لعقد المحتوى حتى يتم عرض الفصل n باستخدام علامات TD داخل جدول. أو قد يستخدمون عناصر أخرى مثل علامات P TAGS أو علامات DIV أو أي عنصر آخر على مستوى كتلة.

بعد المحاولة بشكل متكرر استخدام LXML لمساعدتي في تحديد بداية ونهاية كل فصل، قررت أنه منظفا كبيرا استخدام تعبير منتظم لأنه في كل حالة، بغض النظر عما هو عنصر HTML المحيط هو تسمية الفصل دائما في شكل

>Chapter #

إنه أكثر تعقيدا قليلا في أنه قد يكون هناك مساحة بيضاء أو مساحة غير مكسورة ممثلة بطرق مختلفة (أو أو مجرد مسافات). ومع ذلك، كان الأمر تافيا لكتابة تعبير منتظم لتحديد بداية كل قسم. (بداية قسم واحد هي نهاية القسم السابق.)

ولكن الآن أريد استخدام LXML للحصول على النص. فكرتي هي أنه ليس لدي خيار حقا سوى السير على طول السلسلة الخاصة بي للعثور على علامة وثيقة للعنصر الذي يحفز النص الذي أستخدمه لإيجاد القسم ذي الصلة.

هذا هو المثال التالي حيث العنصر الذي يحمل اسم الفصل هو DIV

<div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="left"><font style="DISPLAY: inline; FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman">Chapter 1.&#160;&#160;&#160;Our Beginnings.</font></div>

لذلك أنا أتخيل أنني سأبدأ في الموقع الذي وجدت فيه المباراة للفصل 1 وإعداد تعبيرات منتظمة للعثور على التالي

</div|</td|</p|</h1 . . .

لذلك في هذه المرحلة حددت نوع العنصر الذي يحمل عنوان خادمي

يمكنني استخدام نفس المنطق للعثور على جميع النص الموجود داخل هذا العنصر الذي تم إعداد تعبير منتظم لمساعدتي في العلامة

>Chapter 1.&#160;&#160;&#160;Our Beginnings.<

لذلك حددت حيث يبدأ الفصل الأول

يمكنني أن أفعل نفس الشيء بالنسبة للفصل 2 (وهو حيث ينتهي الفصل 1)

الآن أتصور أنني سأقوم بتقييم المستند الذي يبدأ عند فتح العنصر الذي حددته كعنصر يشير إلى المكان الذي يبدأ فيه الفصل 1 وينتهي قبل افتتاح العنصر الذي حددته كعنصر يشير إليه 2 تبدأ. سيتم بعد ذلك تغذية السلسلة التي حددتها إلى LXML لاستخدام قوتها للحصول على المحتوى.

أنا ذاهب إلى كل هذه المشكلة لأنني قرأت مرارا وتكرارا - لا تستخدم أبدا تعبيرا منتظما لاستخراج المحتوى من مستندات HTML ولم أضرب طريقة لتكون دقيقا مع LXML لتحديد مواقع البدء والنهاية ل نص أريد استخراجه. على سبيل المثال، لا أستطيع أن أكون متأكدا من أن العنوان الفرعي للفصل 1 هو بداياتنا يمكن أن يكون كناري أحمر لدينا. اسمحوا لي أن أقول إنني قضيت يومين قويين في محاولة مع LXML لتكون واثقة من أنني أصبت بالعناصر البداية والنهاية ويمكنني أن أكون دقيقا فقط <60٪ من الوقت ولكن تعبيرا منتظما قصيرا للغاية أعطاني أفضل من النجاح بنسبة 95٪.

لدي ميل لجعل الأمور أكثر تعقيدا من اللازم، لذلك أتساءل ما إذا كان أي شخص قد شاهد أو حل مشاكل مماثلة، وإذا كان لديهم نهج (لا تفاصيل العقل لك) أنهم يرغبون في تقديمها.

هل كانت مفيدة؟

المحلول 3

كما أخشى أن هناك طريقة منتظمة لاستخدام LXML لتحديد واستخراج ما أحتاج إليه. يا حسنا أنا أقدر الجميع chiming. ملاحظة - هذا ليس خطأ LXML، فهذا هو خطأ ترميز HTML غير المتناقص. على سبيل المثال. نظرا لأن الفصل هو تقسيم معقول في وثيقة، يجب لف جميع المحتوى في فصل واحد في نوع من العناصر. ربما تكون أكثر مرونة هي العلامة DIV مع DIV اللاحقة الفصل التالي. هذا من شأنه أن يجعل الفصل فرع من الشجرة. لسوء الحظ، في حين أن ما يقرب من 20٪ من الوثائق قد يكون منظم جيدا الآخرون ليسوا كذلك.

يمكنني اختبار لكل نوع من العناصر التي يجب أن أحمل المحتوى الخاص بي (Div، P) والاستيلاء على جميع أطفالها وجميع أشقائها حتى أصل إلى العنصر التالي من هذا النوع الذي يحتوي على معلومات تنبهني أننا في نهاية القسم (بداية القسم التالي). ولكن هذا يبدو وكأنه الكثير من العمل عندما أكون جيدا 95٪ من الوقت أو أكثر مع تعبير منتظم.

شكرا لجميع الإجابات والتعليقات كما هو الحال دائما معتميت منها.

نصائح أخرى

في بعض الأحيان لا يوجد طريق مستقيم للحصول على المحتوى عند التعامل مع HTML بشكل سيء أو غير متسق.

قد ترغب في إلقاء نظرة على استخدام Lynx أو أحد المتصفحات المستندة إلى النص إلى تفريغ محتوى الصفحة، إما في ملف، أو أن توجيهه إلى التعليمات البرمجية، ثم أعالجه. أو يمكنك استخدام LXML لتحميل وتحليل الصفحة، ثم استخراج النص باستخدام Text_Content () وأذهب بعد الفصول عبر Regex.

كما يقولون، جيجو - القمامة في، القمامة خارج، وهو عملنا كمطورين لدور القمامة في الذهب. القيام بذلك يمكن أن تحصل فوضوي جدا.

أبسط شيء يبدو أنه ربما يمكنك القيام به هو تكرر أكثر من Tree.getroot (). يحثن عن التسجيل () يبحثون عن عقدة مع node.text هذا يطابق التعبير المنتظم الذي تريده. من هذه النقطة، يمكنك تمرير العقدة إلى وظيفة تستخدم بعض الاستدلال المخصصة لتحديد مكان النص. (ربما إذا كان INERDSCENDANTUTS على الجذر بطيئة للغاية، يمكنك استخدام نهج Regex الخاص بك والغوص في إتاجي لمحاولة العثور على f(text_position) -> node وظيفة.)

على سبيل المثال، إذا وجدت أن الهدف كان //tr/td, ، يمكنك تمريرها إلى بعض الروتين الفرعي لإيجاد نصوص النصوص التي تبحث في TD Next في Node.varent () لمعرفة ما إذا كان لديه نص يجعل منطقي (طول الفصل تقريبا، الذي يحتوي على كلمات معينة، أيا كان). وبالمثل، يمكنك تشكيل بعض الاستدلال لإيجاد البيانات في علامات أخرى مثل div و p. وبعد إذا وجدت نفسك في علامة غير معروفة مثل font يمكنك أن تجرب فقاعة عدد محدود من المستويات للعثور على شيء تعرفه - عليك التعامل معه - يجب أن تكون حذرا على عدم وجود فقاعة حتى الآن، أو أتصور أنك قد استرجع نصا عن طريق الخطأ من فصل آخر.

يبدو أن جوهر المشكلة هو أنك تقوم بتصنيع البيانات التي لم يتم تقديمها برمجيا بطريقة برمجية - في هذه الحالات، عادة ما يكون التفاعل البشري ضروريا إلى حد ما.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top