استراتيجية بيثون لاستخراج النص من صفحات HTML المشوهة
-
06-07-2019 - |
سؤال
أحاول استخراج النص من صفحات HTML التعسفية. بعض الصفحات (التي ليس لدي سيطرة عليها) لديها HTML أو البرامج النصية التي تجعل هذا صعبًا. أنا أيضًا في بيئة استضافة مشتركة ، لذلك يمكنني تثبيت أي بيثون lib ، لكن لا يمكنني فقط تثبيت أي شيء أريده على الخادم.
لا يبدو أن pyparsing و html2text.py يعملان في صفحات HTML المشوهة.
مثال URL هو http://apnews.myway.com/article/20091015/d9bb7cgg1.html
عملي الحالي هو ما يلي تقريبًا:
# Try using BeautifulSoup 3.0.7a
soup = BeautifulSoup.BeautifulSoup(s)
comments = soup.findAll(text=lambda text:isinstance(text,Comment))
[comment.extract() for comment in comments]
c=soup.findAll('script')
for i in c:
i.extract()
body = bsoup.body(text=True)
text = ''.join(body)
# if BeautifulSoup can't handle it,
# alter html by trying to find 1st instance of "<body" and replace everything prior to that, with "<html><head></head>"
# try beautifulsoup again with new html
إذا كانت جميلة لا تزال لا تعمل ، فأنا ألجأ إلى استخدام مجريات في النظر إلى الشار الأول ، آخر شار (لمعرفة ما إذا كان يبدو أنه خط رمز # <؛ وأخذ عينة من الخط ثم تحقق مما إذا كانت الرموز الرموز هي كلمات أو أرقام إنجليزية. إذا كانت هناك عدد قليل من الرموز هي الكلمات أو الأرقام ، فأعتقد أن السطر هو رمز.
يمكنني استخدام التعلم الآلي لتفقد كل سطر ، لكن هذا يبدو مكلفًا بعض الشيء وربما يتعين علي تدريبه (لأنني لا أعرف الكثير عن آلات التعلم غير الخاضعة للإشراف) ، وبالطبع أكتبه أيضًا.
أي نصيحة ، أدوات ، استراتيجيات ستكون موضع ترحيب كبير. أدرك أيضًا أن الجزء الأخير من ذلك هو فوضوي إلى حد ما ، حيث إذا حصلت على سطر يحدد احتواء رمز ، فأنا حاليًا رمي الخط بأكمله حاليًا ، حتى لو كان هناك كمية صغيرة من النص الإنجليزي الفعلي في السطر.
المحلول
حاول ألا تضحك ، ولكن:
class TextFormatter:
def __init__(self,lynx='/usr/bin/lynx'):
self.lynx = lynx
def html2text(self, unicode_html_source):
"Expects unicode; returns unicode"
return Popen([self.lynx,
'-assume-charset=UTF-8',
'-display-charset=UTF-8',
'-dump',
'-stdin'],
stdin=PIPE,
stdout=PIPE).communicate(input=unicode_html_source.encode('utf-8'))[0].decode('utf-8')
أتمنى أن تكون قد حصلت على الوشق!
نصائح أخرى
حسنًا ، يعتمد ذلك على مدى جودة الحل. واجهت مشكلة مماثلة ، حيث استورد مئات صفحات HTML القديمة في موقع ويب جديد. لقد فعلت بشكل أساسي
# remove all that crap around the body and let BS fix the tags
newhtml = "<html><body>%s</body></html>" % (
u''.join( unicode( tag ) for tag in BeautifulSoup( oldhtml ).body.contents ))
# use html2text to turn it into text
text = html2text( newhtml )
وقد نجح الأمر ، ولكن بالطبع قد تكون الوثائق سيئة للغاية لدرجة أن BS لا يمكن أن تنقذ كثيرًا.
سوف تقوم BeautifulSoup سيئة مع HTML المشوهة. ماذا عن بعض regex-fu؟
>>> import re
>>>
>>> html = """<p>This is paragraph with a bunch of lines
... from a news story.</p>"""
>>>
>>> pattern = re.compile('(?<=p>).+(?=</p)', re.DOTALL)
>>> pattern.search(html).group()
'This is paragraph with a bunch of lines\nfrom a news story.'
يمكنك بعد ذلك تجميع قائمة بالعلامات الصالحة التي تريد استخراج المعلومات منها.