পাইথনের স্ট্রিং থেকে এইচটিএমএল স্ট্রিপ করুন


268
from mechanize import Browser
br = Browser()
br.open('http://somewebpage')
html = br.response().readlines()
for line in html:
  print line

এইচটিএমএল ফাইলে একটি লাইন প্রিন্ট করার সময়, আমি কেবলমাত্র প্রতিটি HTML উপাদানগুলির বিষয়বস্তু প্রদর্শন করার জন্য উপায় অনুসন্ধান করার চেষ্টা করছি, বিন্যাসটি নিজেই নয়। যদি এটি সন্ধান করে তবে এটি '<a href="whatever.com">some text</a>'কেবল 'কিছু পাঠ্য', '<b>hello</b>''হ্যালো' প্রিন্ট করবে, ইত্যাদি কীভাবে এটি করা যায়?


16
এইচটিএমএল সত্তা (উদাহরণস্বরূপ &amp;) কীভাবে পরিচালনা করবেন তা একটি গুরুত্বপূর্ণ বিবেচনা । আপনি হয় 1) ট্যাগ সহ এগুলি মুছে ফেলতে পারেন (প্রায়শই অযাচিত এবং অপ্রয়োজনীয় যেহেতু তারা সরল পাঠ্যের সমতুল্য), ২) এটিকে অপরিবর্তিত রেখে দিন (যদি স্ট্রাইপযুক্ত পাঠ্যটি কোনও HTML প্রসঙ্গে ফিরে আসে তবে একটি উপযুক্ত সমাধান) বা 3 ) এগুলি সরল পাঠ্যে ডিকোড করুন (যদি স্ট্রিপড পাঠ্য কোনও ডেটাবেজে বা অন্য কোনও এইচটিএমএল প্রসঙ্গে চলে যায়, বা যদি আপনার ওয়েব ফ্রেমওয়ার্কটি স্বয়ংক্রিয়ভাবে আপনার জন্য পাঠ্যের HTML প্রেরণ সম্পাদন করে)।
সেরেন ল্যাভবার্গ

2
: @ SørenLøvborg বিন্দু 2) জন্য stackoverflow.com/questions/753052/...
রবার্ট

2
এখানে শীর্ষ উত্তর, যা মার্চ ২০১৪ অবধি জ্যাঙ্গো প্রকল্প দ্বারা ব্যবহৃত হয়েছিল, এটি ক্রস-সাইট স্ক্রিপ্টিংয়ের বিরুদ্ধে সুরক্ষিত হিসাবে পাওয়া গেছে - উদাহরণটির জন্য সেই লিঙ্কটি দেখুন যা এটি তৈরি করে। আমি ব্লিচ.ক্লিয়েন (), মার্কআপসফের স্ট্রিপ্যাগগুলি বা রিসেন্ট জ্যাঙ্গোর স্ট্রিপ_ট্যাগগুলি ব্যবহার করার পরামর্শ দিচ্ছি।
ds

উত্তর:


418

আমি এই ফাংশনটি সর্বদা এইচটিএমএল ট্যাগগুলি ফালা করতে ব্যবহার করি, কারণ এটিতে কেবল পাইথন স্টিডলিব প্রয়োজন:

পাইথন 3 এর জন্য:

from io import StringIO
from html.parser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        super().__init__()
        self.reset()
        self.strict = False
        self.convert_charrefs= True
        self.text = StringIO()
    def handle_data(self, d):
        self.text.write(d)
    def get_data(self):
        return self.text.getvalue()

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()

পাইথন 2 এর জন্য:

from HTMLParser import HTMLParser
from StringIO import StringIO

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.text = StringIO()
    def handle_data(self, d):
        self.text.write(d)
    def get_data(self):
        return self.text.getvalue()

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()

3
দু'বছর + পরে, একই সমস্যার মুখোমুখি হচ্ছেন এবং এটি একটি আরও মার্জিত সমাধান। কেবলমাত্র পরিবর্তিত পরিবর্তনটি হ'ল তালিকায় যোগদানের পরিবর্তে স্ব.ফিডকে তালিকা হিসাবে ফিরে আসা, যাতে আমি উপাদানগুলির বিষয়বস্তুগুলি নিয়ে যেতে পারি।
নির্দেশ

47
মনে রাখবেন যে এইচটিএমএল সত্তা (যেমন &amp;) পাশাপাশি ট্যাগগুলি স্ট্রিপ করে ।
সেরেন লভবর্গ

30
@surya আমি আপনি করে থাকেন করছি এই দেখা
tkone

8
দুর্দান্ত উত্তরের জন্য ধন্যবাদ। পাইথনের (৩.২++) নতুন সংস্করণ ব্যবহার করা আপনার জন্য একটি বিষয় লক্ষ্য করুন যে আপনাকে প্যারেন্ট ক্লাসের __init__ফাংশনটি কল করতে হবে । এখানে দেখুন: স্ট্যাকওভারফ্লো / প্রশ্ন / 111061058/…
সিউডোরাম্বল

10
এইচটিএমএল সত্তাকে (ইউনিকোডে রূপান্তরিত) রাখতে, আমি দুটি লাইন যুক্ত করেছি: parser = HTMLParser()এবং html = parser.unescape(html)স্ট্রিপ_ট্যাগগুলি ফাংশনের শুরুতে।
জেমস দোপ্প - পিনহেতাগ্যু

156

কেসগুলি মিস করবে সেগুলি সম্পর্কে আমি খুব বেশি ভাবি না, তবে আপনি একটি সাধারণ রেইজেক্স করতে পারেন:

re.sub('<[^<]+?>', '', text)

যারা রেজেক্স বোঝেন না তাদের জন্য এটি একটি স্ট্রিং অনুসন্ধান করে <...>, যেখানে অভ্যন্তরীণ সামগ্রীটি এক বা একাধিক ( +) অক্ষর দ্বারা তৈরি যা একটি নয় <। এর ?অর্থ এটি যে ক্ষুদ্রতম স্ট্রিংয়ের সাথে মিলবে এটি এটি খুঁজে পেতে পারে। উদাহরণস্বরূপ <p>Hello</p>, এটি মেলে <'p>এবং </p>পৃথকভাবে মিলবে ?। এটি ছাড়া এটি পুরো স্ট্রিংয়ের সাথে মিলবে <..Hello..>

যদি নন-ট্যাগ <এইচটিএমএলে উপস্থিত হয় (উদা। 2 < 3), এটি &...যেভাবেই হোক একটি পালানোর অনুক্রম হিসাবে লেখা উচিত যাতে এটি ^<অপ্রয়োজনীয় হতে পারে।


10
জঙ্গোর স্ট্রিপ_ট্যাগগুলি এটি প্রায় ঠিক এটি করে।
ব্লু

10
নোট করুন যে এটি এইচটিএমএল সত্তা (উদাঃ &amp;) আউটপুটে অপরিবর্তিত রাখে।
সেরেন লভবর্গ

35
এখনও কেউ এই পদ্ধতিটির সাথে এই জাতীয় কৌশলটি চালিয়ে যেতে পারে: <লিপি << স্ক্রিপ্ট>> সতর্কতা ("হাই!") </

19
এই উপায়টি করবেন না! @ জুলিও গার্সিয়া যেমন বলেছেন, এটি নিরাপদ নয়!
রিডিস্ক

18
লোকেরা, এইচটিএমএল স্ট্রিপিং এবং এইচটিএমএল স্যানিটাইজিংকে বিভ্রান্ত করবেন না। হ্যাঁ, ভাঙা বা দূষিত ইনপুটটির জন্য এই উত্তরটি এতে HTML ট্যাগ সহ আউটপুট তৈরি করতে পারে। এটি এখনও এইচটিএমএল ট্যাগ ফালা জন্য একটি সম্পূর্ণ বৈধ পদ্ধতির। তবে , এইচটিএমএল ট্যাগ কেটে ফেলা যথাযথ এইচটিএমএল স্যানিটাইজেশনের বৈধ প্রতিস্থাপন নয়। নিয়মটি কঠোর নয়: আপনি যখনই কোনও এইচটিএমএল আউটপুটে কোনও সরল-পাঠ্য স্ট্রিং sertোকান তখন আপনার HTML সর্বদা এটি (ব্যবহার করে cgi.escape(s, True)) এড়িয়ে চলতে হবে, এমনকি যদি আপনি এটি "HTML" জানেন না যে এটি HTML ব্যবহার করে না (যেমন আপনি HTML বিষয়বস্তু ছিনিয়ে নিয়েছেন) । তবে এটি ওপি সম্পর্কে জিজ্ঞাসা করেছিল না।
সেরেন ল্যাভবার্গ

76

আপনি বিউটিউলসুপ get_text()বৈশিষ্ট্যটি ব্যবহার করতে পারেন ।

from bs4 import BeautifulSoup

html_str = '''
<td><a href="http://www.fakewebsite.com">Please can you strip me?</a>
<br/><a href="http://www.fakewebsite.com">I am waiting....</a>
</td>
'''
soup = BeautifulSoup(html_str)

print(soup.get_text()) 
#or via attribute of Soup Object: print(soup.text)

স্পষ্ট করে পার্সার নির্দিষ্ট করার পরামর্শ দেওয়া হয় , উদাহরণস্বরূপ BeautifulSoup(html_str, features="html.parser"), আউটপুট পুনরায় উত্পাদনযোগ্য হতে পারে।


32

সংক্ষিপ্ত সংস্করণ!

import re, cgi
tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)')

# Remove well-formed tags, fixing mistakes by legitimate users
no_tags = tag_re.sub('', user_input)

# Clean up anything else by escaping
ready_for_web = cgi.escape(no_tags)

রেজেক্স উত্স: মার্কআপসেফ । তাদের সংস্করণটি এইচটিএমএল সত্তাকেও পরিচালনা করে, যদিও এই দ্রুতটি তা করে না।

আমি কেন কেবল ট্যাগগুলি ফাঁক করে ছেড়ে দিতে পারি না?

মানুষকে চারপাশে ভাসমান <i>italicizing</i>না রেখে জিনিস থেকে দূরে রাখা এক জিনিস i। তবে স্বেচ্ছাচারিত ইনপুট নেওয়া এবং এটিকে সম্পূর্ণ নিরীহ করে তোলা অন্য। এই পৃষ্ঠার বেশিরভাগ কৌশল অবরুদ্ধ মন্তব্য ( <!--) এবং কোণ-বন্ধনীগুলির মতো জিনিসগুলি ছেড়ে দেবে যা ট্যাগগুলির অংশ ( blah <<<><blah) অক্ষত নেই। এইচটিএমএল পার্সার সংস্করণটি এমনকি কোনও বিবৃত মন্তব্যের মধ্যে থাকলে সম্পূর্ণ ট্যাগগুলি এখানে রেখে দিতে পারে।

যদি আপনার টেম্পলেট হয় {{ firstname }} {{ lastname }}? firstname = '<a'এবং lastname = 'href="http://evil.com/">'এই পৃষ্ঠায় প্রতিটি ট্যাগ স্ট্রিপারের মাধ্যমে দেওয়া হবে (@ মেদিরোস ব্যতীত!), কারণ তারা নিজেরাই পুরোপুরি ট্যাগ নেই। সাধারণ এইচটিএমএল ট্যাগগুলি ছড়িয়ে দেওয়া যথেষ্ট নয়।

strip_tagsএই প্রশ্নের শীর্ষ উত্তরের একটি উন্নত (পরবর্তী শিরোনামটি দেখুন) সংস্করণ জ্যাঙ্গো নিম্নলিখিত সতর্কতা দেয়:

ফলস্বরূপ কোনও এইচটিএমএল সুরক্ষিত স্ট্রিং সম্পর্কে কোনও গ্যারান্টি সরবরাহ করা হয়নি। সুতরাং কোনও strip_tagsকলকে প্রথমে এড়িয়ে চলা ছাড়া নিরাপদ হিসাবে চিহ্নিত করুন না , উদাহরণস্বরূপ escape()

তাদের পরামর্শ অনুসরণ করুন!

এইচটিএমএল পার্সারের সাহায্যে ট্যাগগুলি ছাঁটাতে আপনাকে এটি একাধিকবার চালাতে হবে।

এই প্রশ্নের শীর্ষের উত্তরটি বাতিল করা সহজ।

এই স্ট্রিংটি দেখুন ( উত্স এবং আলোচনা ):

<img<!-- --> src=x onerror=alert(1);//><!-- -->

এইচটিএমএল পার্সার এটি প্রথমবার দেখলে এটি বলতে পারে না যে এটি <img...>একটি ট্যাগ। এটি ভাঙা দেখায়, তাই এইচটিএমএল পার্সার এ থেকে মুক্তি পায় না। এটি কেবল আপনাকেই <!-- comments -->ছাড়িয়ে যায়

<img src=x onerror=alert(1);//>

এই সমস্যাটি জাঙ্গো প্রকল্পে 2014 সালের মার্চ মাসে প্রকাশ করা হয়েছিল। তাদের পুরানো strip_tagsমূলত এই প্রশ্নের শীর্ষ জবাব হিসাবে একই ছিল। তাদের নতুন সংস্করণটি মূলত এটিকে একটি লুপে চালায় যতক্ষণ না আবার এটি চালানো স্ট্রিং পরিবর্তন করে না:

# _strip_once runs HTMLParser once, pulling out just the text of all the nodes.

def strip_tags(value):
    """Returns the given HTML with all tags stripped."""
    # Note: in typical case this loop executes _strip_once once. Loop condition
    # is redundant, but helps to reduce number of executions of _strip_once.
    while '<' in value and '>' in value:
        new_value = _strip_once(value)
        if len(new_value) >= len(value):
            # _strip_once was not able to detect more tags
            break
        value = new_value
    return value

অবশ্যই আপনি যদি সর্বদা এর ফলাফল থেকে বাঁচেন তবে এগুলির কোনওই সমস্যা নয় strip_tags()

আপডেট 19 মার্চ, 2015 : জঙ্গো সংস্করণে 1.4.20, 1.6.11, 1.7.7 এবং 1.8c1 এর আগে একটি বাগ ছিল। এই সংস্করণগুলি স্ট্রিপ_ট্যাগগুলি () ফাংশনে একটি অসীম লুপ প্রবেশ করতে পারে। স্থির সংস্করণ উপরে পুনরুত্পাদন করা হয়। আরও বিশদ এখানে

অনুলিপি বা ব্যবহার ভাল জিনিস

আমার উদাহরণ কোডটি এইচটিএমএল সত্তাগুলি পরিচালনা করে না - জাজানো এবং মার্কআপসেফ প্যাকেজযুক্ত সংস্করণগুলি।

আমার উদাহরণ কোডটি ক্রস-সাইট স্ক্রিপ্টিং প্রতিরোধের জন্য দুর্দান্ত মার্কআপসে লাইব্রেরি থেকে টানা হয়েছে is এটি সুবিধাজনক এবং দ্রুত (সিটি স্পিডআপ সহ এর মূল পাইথন সংস্করণে)। এটা তোলে মধ্যে অন্তর্ভুক্ত Google App ইঞ্জিন , এবং দ্বারা ব্যবহৃত Jinja2 (2.7 এবং তার পরবর্তী) , Makó, pylons, ড। এটি জ্যাঙ্গো ১.7 থেকে জাজানো টেম্পলেটগুলির সাথে সহজেই কাজ করে।

সাম্প্রতিক সংস্করণ থেকে জ্যাঙ্গোর স্ট্রিপ_ট্যাগ এবং অন্যান্য এইচটিএমএল ইউটিলিটিগুলি ভাল, তবে আমি সেগুলি মার্কআপসেফের চেয়ে কম সুবিধাজনক বলে মনে করি। তারা বেশ স্ব-অন্তর্নিহিত, আপনি এই ফাইলটি থেকে যা প্রয়োজন তা অনুলিপি করতে পারেন ।

আপনার যদি প্রায় সব ট্যাগ ফেলা প্রয়োজন তবে ব্লিচ লাইব্রেরিটি ভাল। আপনার কাছে এটি "আমার ব্যবহারকারীরা জিনিসগুলিকে ইটালাইজ করতে পারে তবে তারা আইফ্রেমেস তৈরি করতে পারে না" এর মতো বিধি প্রয়োগ করতে পারে।

আপনার ট্যাগ স্ট্রিপারের বৈশিষ্ট্যগুলি বুঝুন! এটির উপর ফজ পরীক্ষা চালান! এই উত্তরের জন্য আমি গবেষণাটি করতে কোডটি এখানে ব্যবহার করি।

ভেড়া নোট - প্রশ্নটি নিজেই কনসোলে মুদ্রণের বিষয়ে, তবে এটি "স্ট্রিং থেকে পাইথন স্ট্রিপ এইচটিএমএল" এর জন্য শীর্ষ গুগলের ফলাফল, তাই এই উত্তরটি ওয়েব সম্পর্কে 99%।


আমার "বিকল্প শেষ লাইন" উদাহরণ কোডটি এইচটিএমএল সত্তাগুলি পরিচালনা করে না - এটি কতটা খারাপ?
রবিবার্ক

আমি কেবল কোনও বিশেষ ট্যাগ ছাড়াই এইচটিএমএলের একটি ছোট অংশকে পার্স করছি, এবং আপনার সংক্ষিপ্ত সংস্করণটি কাজটি খুব ভালভাবে করে। ভাগ করে নেওয়ার জন্য ধন্যবাদ!
tbolender

31

আমার ট্যাগগুলি স্ট্রিপ করার এবং এইচটিএমএল সত্তাটিকে সরল পাঠ্যে ডিকোড করার একটি উপায় প্রয়োজন । নীচের সমাধানটি এলফের উত্তরের উপর ভিত্তি করে (যা আমি ব্যবহার করতে পারিনি কারণ এটি সত্তা সরিয়ে দেয়)।

from HTMLParser import HTMLParser
import htmlentitydefs

class HTMLTextExtractor(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.result = [ ]

    def handle_data(self, d):
        self.result.append(d)

    def handle_charref(self, number):
        codepoint = int(number[1:], 16) if number[0] in (u'x', u'X') else int(number)
        self.result.append(unichr(codepoint))

    def handle_entityref(self, name):
        codepoint = htmlentitydefs.name2codepoint[name]
        self.result.append(unichr(codepoint))

    def get_text(self):
        return u''.join(self.result)

def html_to_text(html):
    s = HTMLTextExtractor()
    s.feed(html)
    return s.get_text()

একটি দ্রুত পরীক্ষা:

html = u'<a href="#">Demo <em>(&not; \u0394&#x03b7;&#956;&#x03CE;)</em></a>'
print repr(html_to_text(html))

ফলাফল:

u'Demo (\xac \u0394\u03b7\u03bc\u03ce)'

ত্রুটি পরিচালনা:

  • অবৈধ এইচটিএমএল কাঠামো একটি এইচটিএমএল পার্সিররর কারণ হতে পারে ।
  • অবৈধ নামযুক্ত এইচটিএমএল সত্তা (যেমন &#apos;, যা এক্সএমএল এবং এক্সএইচটিএমএলে বৈধ, তবে সাধারণ এইচটিএমএল নয়) ValueErrorব্যতিক্রম ঘটায় ।
  • পাইথনের দ্বারা গ্রহণযোগ্য ইউনিকোড ব্যাপ্তির বাইরে কোড পয়েন্ট নির্দিষ্ট করে এমন সংখ্যার এইচটিএমএল সত্তা (যেমন, কয়েকটি সিস্টেমে বেসিক বহুভাষিক সমতলের অক্ষর ) ValueErrorব্যতিক্রম ঘটায় ।

সুরক্ষা দ্রষ্টব্য: এইচটিএমএল স্ট্রিপিং (এইচটিএমএলকে প্লেইন পাঠ্যে রূপান্তর করা) এইচটিএমএল স্যানিটাইজাইজিং (প্লেইন পাঠ্যকে এইচটিএমএল রূপান্তরকরণ) দিয়ে বিভ্রান্ত করবেন না। এই উত্তরটি এইচটিএমএল এবং সরল পাঠ্যে সত্তা সত্তা সরিয়ে দেবে - যা এইচটিএমএল প্রসঙ্গে ব্যবহারের ফলাফলকে নিরাপদ করে না।

উদাহরণ: &lt;script&gt;alert("Hello");&lt;/script&gt;রূপান্তরিত হবে <script>alert("Hello");</script>যা 100% সঠিক আচরণ, তবে ফলস্বরূপ প্লেইন পাঠ্যটি কোনও HTML পৃষ্ঠায় asোকানো হলে তা অবশ্যই যথেষ্ট নয়।

নিয়মটি কঠোর নয়: আপনি যখনই কোনও এইচটিএমএল আউটপুটে কোনও সরল-পাঠ্য স্ট্রিং sertোকান তখন আপনার HTML সর্বদা এটি (ব্যবহার করে cgi.escape(s, True)) এড়িয়ে চলতে হবে, এমনকি যদি আপনি এটি "HTML" জানেন না যে এটি HTML ব্যবহার করে না (যেমন আপনি HTML বিষয়বস্তু ছিনিয়ে নিয়েছেন) ।

(তবে, ওপি কনসোলে ফলাফল মুদ্রণের বিষয়ে জিজ্ঞাসা করেছিল, এই ক্ষেত্রে কোনও এইচটিএমএল পালানোর প্রয়োজন নেই))

পাইথন ৩.৪++ সংস্করণ: (ডক্টেস্ট সহ!)

import html.parser

class HTMLTextExtractor(html.parser.HTMLParser):
    def __init__(self):
        super(HTMLTextExtractor, self).__init__()
        self.result = [ ]

    def handle_data(self, d):
        self.result.append(d)

    def get_text(self):
        return ''.join(self.result)

def html_to_text(html):
    """Converts HTML to plain text (stripping tags and converting entities).
    >>> html_to_text('<a href="#">Demo<!--...--> <em>(&not; \u0394&#x03b7;&#956;&#x03CE;)</em></a>')
    'Demo (\xac \u0394\u03b7\u03bc\u03ce)'

    "Plain text" doesn't mean result can safely be used as-is in HTML.
    >>> html_to_text('&lt;script&gt;alert("Hello");&lt;/script&gt;')
    '<script>alert("Hello");</script>'

    Always use html.escape to sanitize text before using in an HTML context!

    HTMLParser will do its best to make sense of invalid HTML.
    >>> html_to_text('x < y &lt z <!--b')
    'x < y < z '

    Unrecognized named entities are included as-is. '&apos;' is recognized,
    despite being XML only.
    >>> html_to_text('&nosuchentity; &apos; ')
    "&nosuchentity; ' "
    """
    s = HTMLTextExtractor()
    s.feed(html)
    return s.get_text()

নোট করুন যে পাইথন 3 এ এইচটিএমএল পার্সারের উন্নতি হয়েছে (যার অর্থ কম কোড এবং আরও ভাল ত্রুটি পরিচালনা)।


18

এটির একটি সহজ উপায় আছে:

def remove_html_markup(s):
    tag = False
    quote = False
    out = ""

    for c in s:
            if c == '<' and not quote:
                tag = True
            elif c == '>' and not quote:
                tag = False
            elif (c == '"' or c == "'") and tag:
                quote = not quote
            elif not tag:
                out = out + c

    return out

ধারণাটি এখানে ব্যাখ্যা করা হয়েছে: http://youtu.be/2tu9LTDujbw

আপনি এটি এখানে কাজ করে দেখতে পারেন: http://youtu.be/HPkNPcYed9M?t=35s

: - দ্রষ্টব্য আপনি (পাইথন সঙ্গে স্মার্ট ডিবাগিং সম্বন্ধে) ক্লাসে আগ্রহী হন, তাহলে আমি তোমাকে একটা লিঙ্ক দিতে http://www.udacity.com/overview/Course/cs259/CourseRev/1 । এটা বিনামূল্যে!

আপনাকে স্বাগতম! :)


2
আমি অবাক হলাম কেন এই উত্তরটি সবেচেয়ে কম গেল। কোনও শোধ ছাড়াই সমস্যা সমাধানের এটি সহজ উপায়। কেবল খাঁটি অজগর এবং এটি লিঙ্কগুলি দেখানো হিসাবে কাজ করে।
মেডিইরোস

2
সম্ভবত লোকেরা তাদের নিরাপত্তা দেওয়ার জন্য লিবকে পছন্দ করে। আমি আপনার কোডটি পরীক্ষা করে পাস করেছি এবং আমি সবসময় একটি ছোট্ট কোড পছন্দ করি যা আমি বুঝতে পারি যে কোনও বাগটি ব্যবহার করা এবং বাগ পপ আপ না হওয়া পর্যন্ত এটি ঠিক আছে than আমার জন্য এটি আমি যা খুঁজছিলাম এবং আবার ধন্যবাদ। ডাউনভোটগুলি সম্পর্কে, সেই মানসিকতায় উঠবেন না। এখানকার লোকদের ভোটের বিষয়ে নয়, গুণমান সম্পর্কে যত্ন নেওয়া উচিত। ইদানীং এসও এমন একটি জায়গায় পরিণত হয়েছে যেখানে জ্ঞানের নয়, প্রত্যেকেই তার পয়েন্ট চায়।
জিমি কেন

2
এই সমাধানটির সাথে সমস্যা হ'ল ত্রুটি পরিচালনা করা। উদাহরণস্বরূপ যদি আপনি <b class="o'>x</b>ইনপুট ফাংশন আউটপুট হিসাবে দেন x। তবে আসলে এই ইনপুটটি অবৈধ। আমি মনে করি সে কারণেই লোকেরা লাইব পছন্দ করে।
লল্টিন

1
এটি সেই ইনপুটটির সাথেও কাজ করে। সবেমাত্র পরীক্ষিত। কেবল উপলব্ধি করুন যে এই লাইব্রেরির ভিতরে আপনি একই কোড পাবেন। এটি খুব অজগর নয়, আমি জানি। সি বা জাভা কোডের মতো দেখাচ্ছে। আমি মনে করি এটি দক্ষ এবং সহজেই অন্য ভাষায় পোর্ট করা যায়।
মেডেইরোস

1
সরল, পাইথোনিক এবং আলোচিত অন্যান্য পদ্ধতির চেয়ে ভাল বা ভাল হিসাবে কাজ করে বলে মনে হচ্ছে। এটি সম্ভবত কিছু অসুস্থ গঠনের এইচটিএমএল এর জন্য কাজ করবে না তবে এটির অতিক্রম করার কোনও সুযোগ নেই।
ডেনসন

16

যদি আপনার এইচটিএমএল সত্তা (যেমন &amp;) সংরক্ষণের প্রয়োজন হয় তবে আমি এলফের উত্তরে "হ্যান্ডেল_এন্টিটিফ" পদ্ধতি যুক্ত করেছি ।

from HTMLParser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.fed = []
    def handle_data(self, d):
        self.fed.append(d)
    def handle_entityref(self, name):
        self.fed.append('&%s;' % name)
    def get_data(self):
        return ''.join(self.fed)

def html_to_text(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()

13

আপনি যদি সব এইচটিএমএল ট্যাগগুলি সন্ধান করতে চান তবে আমার কাছে পাওয়া সবচেয়ে সহজ উপায় হ'ল বিউটিফুলসপ ব্যবহার করুন:

from bs4 import BeautifulSoup  # Or from BeautifulSoup import BeautifulSoup

def stripHtmlTags(htmlTxt):
    if htmlTxt is None:
            return None
        else:
            return ''.join(BeautifulSoup(htmlTxt).findAll(text=True)) 

আমি স্বীকৃত উত্তরের কোডটি চেষ্টা করেছি তবে আমি "রানটাইম’রর: সর্বাধিক পুনরাবৃত্তির গভীরতা অতিক্রম করেছি" যা উপরের কোডটির ব্লকের সাথে ঘটেছিল না happen


1
আমি কেবল আপনার পদ্ধতিটি চেষ্টা করেছি কারণ এটি ক্লিনার বলে মনে হচ্ছে, এটি কাজ করেছে, ভাল ধরণের ... এটি ইনপুট ট্যাগগুলি স্ট্রিপ করেনি!
kustomrtr

আমি দেখি যে BeautifulSoup সহজ আবেদন অনুসরণকারী শূণ্যস্থান সঙ্গে একটি সমস্যা রয়েছে: ''.join(BeautifulSoup('<em>he</em>llo<br>world').find_all(text=True))। এখানে আউটপুটটি "হেলিওর্ল্ড" রয়েছে, আপনি সম্ভবত এটি "হ্যালো ওয়ার্ল্ড" হতে চান। ' '.join(BeautifulSoup('<em>he</em>llo<br>world').find_all(text=True))এটি "তিনি বিশ্বজুড়ে" হয়ে ওঠে না।
ফিন অরূপ

@ কাস্টমআর্টর, দুঃখিত আমার অজ্ঞতা, আমি নিজের মধ্যে কী যুক্তি দেব? নামের ত্রুটি: নাম 'স্ব' সংজ্ঞায়িত করা হয়নি
Ian_De_Oliveira

@ আইয়ান_ডে_ অলিভেরা আপনি এটি সরিয়ে ফেলতে পারেন, আমি ধরে নিয়েছি এটি কোনও শ্রেণীর ভিতরে রয়েছে তবে এটির দরকার নেই। আমি এটিকে সরানোর জন্য উত্তরটি সম্পাদনা করেছি
ভ্যাসিলিস

@ আইয়ান_ডে_ অলিভেরা আপনি এটি সরিয়ে ফেলতে পারেন, আমি ধরে নিয়েছি এটি কোনও শ্রেণীর ভিতরে রয়েছে তবে এটির দরকার নেই। আমি এটিকে সরানোর জন্য উত্তরটি সম্পাদনা করেছি
ভ্যাসিলিস

9

একটি lxML.html ভিত্তিক সমাধান (lxML একটি স্থানীয় গ্রন্থাগার এবং তাই কোনও খাঁটি অজগর সমাধানের তুলনায় অনেক দ্রুত)।

from lxml import html
from lxml.html.clean import clean_html

tree = html.fromstring("""<span class="item-summary">
                            Detailed answers to any questions you might have
                        </span>""")

print(clean_html(tree).strip())

# >>> Detailed answers to any questions you might have

LxML.cleaner ঠিক কী করে তার জন্য http://lxML.de/lxmlhtml.html#cleaning-up-html দেখুন ।

আপনি যদি পাঠ্যে রূপান্তর করার আগে ঠিক কী পরিমাণে স্যানিটাইজ করা হয় তার উপর যদি আপনার আরও নিয়ন্ত্রণের প্রয়োজন হয় তবে আপনি কনস্ট্রাক্টরের যে বিকল্পগুলি চান সেটি স্পষ্ট করে lxML ক্লিনারটি ব্যবহার করতে পারেন , যেমন:

cleaner = Cleaner(page_structure=True,
                  meta=True,
                  embedded=True,
                  links=True,
                  style=True,
                  processing_instructions=True,
                  inline_style=True,
                  scripts=True,
                  javascript=True,
                  comments=True,
                  frames=True,
                  forms=True,
                  annoying_tags=True,
                  remove_unknown_tags=True,
                  safe_attrs_only=True,
                  safe_attrs=frozenset(['src','color', 'href', 'title', 'class', 'name', 'id']),
                  remove_tags=('span', 'font', 'div')
                  )
sanitized_html = cleaner.clean_html(unsafe_html)

1
আমি AttributeError পেয়েছিলাম: 'HtmlElement' অবজেক্ট কোন অ্যাট্রিবিউট 'ফালা' হয়েছে
এআরআইএস

9

এখানে একটি সহজ সমাধান যা এইচটিএমএল ট্যাগগুলি স্ট্রিপ করে এবং আশ্চর্যজনকভাবে দ্রুত lxmlগ্রন্থাগারের উপর ভিত্তি করে এইচটিএমএল সত্তাকে ডিকোড করে :

from lxml import html

def strip_html(s):
    return str(html.fromstring(s).text_content())

strip_html('Ein <a href="">sch&ouml;ner</a> Text.')  # Output: Ein schöner Text.

3
2020 সালের হিসাবে, এটি এইচটিএমএল এর বিষয়বস্তু ছড়িয়ে দেওয়ার জন্য দ্রুত এবং সর্বোত্তম উপায় ছিল। প্লাস ডিকোডিং পরিচালনা করার বোনাস। ভাষা সনাক্তকরণের জন্য দুর্দান্ত!
dfabiano

text_content()ফেরত দেয় lxml.etree._ElementUnicodeResultযাতে আপনার এটি প্রথমে স্ট্রিংয়ে ফেলে দিতে হয়
সুজানা

1
@ সুজানা ভাল পয়েন্ট strস্ট্রিং অপারেশনের মতো +এবং সূচকের জন্য এটি স্বয়ংক্রিয়ভাবে কাস্টেড হয়ে গেছে বলে মনে হচ্ছে []। যাইহোক ভাল পরিমাপের জন্য একটি কাস্ট যোগ করা হয়েছে।
রবিন ডিনসে

7

সুন্দর স্যুপ প্যাকেজটি আপনার জন্য তাৎক্ষণিকভাবে এটি করে।

from bs4 import BeautifulSoup

soup = BeautifulSoup(html)
text = soup.get_text()
print(text)

3
পর্যালোচনা সারি থেকে: আমি আপনাকে অনুরোধ করতে দয়া করে আপনার উত্তর কাছাকাছি আরও কিছু প্রসঙ্গ যুক্ত করুন। কোড-কেবল উত্তরগুলি বোঝা মুশকিল। আপনি যদি আপনার পোস্টে আরও তথ্য যুক্ত করতে পারেন তবে এটি প্রশ্নকারী এবং ভবিষ্যতের পাঠকদের উভয়কেই সহায়তা করবে।
help-info.de

2

অজগর 3 এর জন্য আমার সমাধান এখানে।

import html
import re

def html_to_txt(html_text):
    ## unescape html
    txt = html.unescape(html_text)
    tags = re.findall("<[^>]+>",txt)
    print("found tags: ")
    print(tags)
    for tag in tags:
        txt=txt.replace(tag,'')
    return txt

এটি নিখুঁত কিনা তা নিশ্চিত নন তবে আমার ব্যবহারের ক্ষেত্রে সমাধান হয়েছে এবং সহজ বলে মনে হচ্ছে।


2

আপনি হয় আলাদা এইচটিএমএল পার্সার ( যেমন lxML বা বিউটিফুল স্যুপ ) ব্যবহার করতে পারেন - এমনটি যা কেবলমাত্র পাঠ্য বের করার জন্য ফাংশন সরবরাহ করে। অথবা, আপনি আপনার লাইনের স্ট্রিংয়ে একটি রেজেেক্স চালাতে পারেন যা ট্যাগগুলি বের করে দেয়। আরও জন্য পাইথন ডক্স দেখুন।


1
আমাক লিঙ্কটি মারা গেছে। বিকল্প পেয়েছেন?

2
পাইথন ওয়েবসাইটটিতে এখন কীভাবে টাস্ক রয়েছে
জেসন কুন

5
Lxml ইন:lxml.html.fromstring(s).text_content()
Bluu

1
LxML সহ ব্লু উদাহরণটি HTML সত্ত্বাকে ডিকোড করে (যেমন &amp;) পাঠ্য করতে।
সেরেন লভবর্গ

1

আমি পাইফনের ৩.১-এর জন্য এলফের উত্তর সফলভাবে ব্যবহার করেছি [অনেক ধন্যবাদ!]।

আমি পাইথন ৩.২.৩ এ আপগ্রেড করেছি এবং ত্রুটি হয়েছি।

এখানে প্রদত্ত সমাধানটি প্রতিক্রিয়াশীল থমাস কেকে ধন্যবাদ জানিয়ে super().__init__()নিম্নলিখিত কোডটিতে প্রবেশ করানো হল :

def __init__(self):
    self.reset()
    self.fed = []

... এটি দেখতে দেখতে:

def __init__(self):
    super().__init__()
    self.reset()
    self.fed = []

... এবং এটি পাইথন ৩.২.৩ এর জন্য কাজ করবে।

আবার, ঠিক করার জন্য এবং উপরে প্রদত্ত এলফের মূল কোডটির জন্য থমাস কে ধন্যবাদ!


1

আপনি নিজের ফাংশন লিখতে পারেন:

def StripTags(text):
     finished = 0
     while not finished:
         finished = 1
         start = text.find("<")
         if start >= 0:
             stop = text[start:].find(">")
             if stop >= 0:
                 text = text[:start] + text[start+stop+1:]
                 finished = 0
     return text

1
স্ট্রিংগুলিতে সংযোজন স্ট্রিংয়ের একটি নতুন অনুলিপি তৈরি করে?
জেরেমি এল

1
@ নারডলিং - হ্যাঁ এটি হ'ল যা ঘন ঘন ব্যবহৃত ফাংশনগুলিতে কিছু বা চিত্তাকর্ষক অদক্ষতার দিকে পরিচালিত করতে পারে (বা, এই বিষয়টির জন্য, খুব বেশি ব্যবহৃত টেক্সট যা বড় আকারের পাঠ্যের উপরে কাজ করে)) বিশদ জন্য এই পৃষ্ঠাটি দেখুন । : ডি
জেরেমি স্যান্ডেল

এটি কি উদ্ধৃত স্ট্রিংগুলির বিরুদ্ধে পরীক্ষা করে? নং
জিমি কানে

1

এইচটিএমএল-পার্সার সহ সমাধানগুলি সমস্ত ব্রেকড হয়, যদি তারা কেবল একবার চালায়:

html_to_text('<<b>script>alert("hacked")<</b>/script>

ফলাফল স্বরূপ:

<script>alert("hacked")</script>

আপনি কি প্রতিরোধ করতে চান। আপনি যদি এইচটিএমএল-পার্সার ব্যবহার করেন তবে শূন্য প্রতিস্থাপন না হওয়া পর্যন্ত ট্যাগগুলি গণনা করুন:

from HTMLParser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.fed = []
        self.containstags = False

    def handle_starttag(self, tag, attrs):
       self.containstags = True

    def handle_data(self, d):
        self.fed.append(d)

    def has_tags(self):
        return self.containstags

    def get_data(self):
        return ''.join(self.fed)

def strip_tags(html):
    must_filtered = True
    while ( must_filtered ):
        s = MLStripper()
        s.feed(html)
        html = s.get_data()
        must_filtered = s.has_tags()
    return html

1
যদি আপনি কলিত কোনও ফাংশন কল করেন html_to_textএবং আপনি এই পাঠ্যটি এইচটিএমএলের অভ্যন্তরে আউটপুট হিসাবে টেক্সটটি এম্বেট করে থাকেন তবে এটি পলায়নের অভাব যা কোনও সুরক্ষা দুর্বলতা, html_to_textফাংশন নয়। html_to_textফাংশন আপনি কখনই প্রতিশ্রুত আউটপুট টেক্সট করা হবে। এবং এড়িয়ে যাওয়া ছাড়াই এইচটিএমএল এ পাঠ্য সন্নিবেশ করানো আপনার সম্ভাব্য সুরক্ষার দুর্বলতা, আপনি যে পাঠ্যটি html_to_text অন্য কোনও উত্স থেকে পেয়েছেন তা নির্বিশেষে ।
কাস্পারড

আপনি ঠিকঠাক ক্ষেত্রে, পালাতে না পারা, তবে প্রশ্নগুলি একটি নির্দিষ্ট স্ট্রিং থেকে এইচটিএমএল ফেলা হবে যাতে প্রদত্ত স্ট্রিংটি এড়ানোর জন্য নয়। পূর্ববর্তী উত্তরগুলি যদি কিছু এইচটিএমএল অপসারণের ফলে তাদের সমাধানগুলি সহ নতুন এইচটিএমএল তৈরি করে, তবে এই সমাধানগুলির ব্যবহার বিপজ্জনক।
ফালক নিসিয়াস

1

এটি একটি দ্রুত স্থির এবং আরও অনুকূলিত করা যেতে পারে তবে এটি দুর্দান্ত কাজ করবে। এই কোডটি "" সহ সমস্ত অ খালি ট্যাগগুলিকে প্রতিস্থাপন করবে এবং সমস্ত এইচটিএমএল ট্যাগ একটি প্রদত্ত ইনপুট পাঠ্য গঠন করবে। আপনি এটি ব্যবহার করতে পারেন। / ফাইল.পি ইনপুট আউটপুট

    #!/usr/bin/python
import sys

def replace(strng,replaceText):
    rpl = 0
    while rpl > -1:
        rpl = strng.find(replaceText)
        if rpl != -1:
            strng = strng[0:rpl] + strng[rpl + len(replaceText):]
    return strng


lessThanPos = -1
count = 0
listOf = []

try:
    #write File
    writeto = open(sys.argv[2],'w')

    #read file and store it in list
    f = open(sys.argv[1],'r')
    for readLine in f.readlines():
        listOf.append(readLine)         
    f.close()

    #remove all tags  
    for line in listOf:
        count = 0;  
        lessThanPos = -1  
        lineTemp =  line

            for char in lineTemp:

            if char == "<":
                lessThanPos = count
            if char == ">":
                if lessThanPos > -1:
                    if line[lessThanPos:count + 1] != '<>':
                        lineTemp = replace(lineTemp,line[lessThanPos:count + 1])
                        lessThanPos = -1
            count = count + 1
        lineTemp = lineTemp.replace("&lt","<")
        lineTemp = lineTemp.replace("&gt",">")                  
        writeto.write(lineTemp)  
    writeto.close() 
    print "Write To --- >" , sys.argv[2]
except:
    print "Help: invalid arguments or exception"
    print "Usage : ",sys.argv[0]," inputfile outputfile"

1

স্যারেন-ল্যাভবর্গের উত্তরের একটি অজগর 3 অভিযোজন

from html.parser import HTMLParser
from html.entities import html5

class HTMLTextExtractor(HTMLParser):
    """ Adaption of http://stackoverflow.com/a/7778368/196732 """
    def __init__(self):
        super().__init__()
        self.result = []

    def handle_data(self, d):
        self.result.append(d)

    def handle_charref(self, number):
        codepoint = int(number[1:], 16) if number[0] in (u'x', u'X') else int(number)
        self.result.append(unichr(codepoint))

    def handle_entityref(self, name):
        if name in html5:
            self.result.append(unichr(html5[name]))

    def get_text(self):
        return u''.join(self.result)

def html_to_text(html):
    s = HTMLTextExtractor()
    s.feed(html)
    return s.get_text()

1

একটি প্রকল্পের জন্য, আমার এত স্ট্রিপ এইচটিএমএল প্রয়োজন, তবে সিএসএস এবং জেএসও। এইভাবে, আমি এলফস উত্তরের একটি পরিবর্তন করেছি:

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.strict = False
        self.convert_charrefs= True
        self.fed = []
        self.css = False
    def handle_starttag(self, tag, attrs):
        if tag == "style" or tag=="script":
            self.css = True
    def handle_endtag(self, tag):
        if tag=="style" or tag=="script":
            self.css=False
    def handle_data(self, d):
        if not self.css:
            self.fed.append(d)
    def get_data(self):
        return ''.join(self.fed)

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()

1

এখানে বর্তমানে গৃহীত উত্তরের ( https://stackoverflow.com/a/925630/95989 ) এর অনুরূপ একটি সমাধান রয়েছে , কেবলমাত্র এটি অভ্যন্তরীণ HTMLParserশ্রেণীর সরাসরি ব্যবহার করে (অর্থাত্ কোনও সাবক্লাসিং নয়), যার ফলে এটি উল্লেখযোগ্যভাবে আরও সংশ্লেষিত হয়:

Def স্ট্রিপ_এইচটিএমএল (পাঠ্য):
    অংশ = []                                                                      
    পার্সার = এইচটিএমএল পার্সার ()                                                           
    parser.handle_data = parts.append                                               
    parser.feed (পাঠ্য)                                                               
    ফিরে '' .জাইন (অংশ)

0

আমি গিথুব রেডিমেস পার্স করছি এবং আমি দেখতে পাচ্ছি যে নিম্নলিখিতগুলি সত্যই কার্যকরভাবে কাজ করে:

import re
import lxml.html

def strip_markdown(x):
    links_sub = re.sub(r'\[(.+)\]\([^\)]+\)', r'\1', x)
    bold_sub = re.sub(r'\*\*([^*]+)\*\*', r'\1', links_sub)
    emph_sub = re.sub(r'\*([^*]+)\*', r'\1', bold_sub)
    return emph_sub

def strip_html(x):
    return lxml.html.fromstring(x).text_content() if x else ''

এবং তারপর

readme = """<img src="https://raw.githubusercontent.com/kootenpv/sky/master/resources/skylogo.png" />

            sky is a web scraping framework, implemented with the latest python versions in mind (3.4+). 
            It uses the asynchronous `asyncio` framework, as well as many popular modules 
            and extensions.

            Most importantly, it aims for **next generation** web crawling where machine intelligence 
            is used to speed up the development/maintainance/reliability of crawling.

            It mainly does this by considering the user to be interested in content 
            from *domains*, not just a collection of *single pages*
            ([templating approach](#templating-approach))."""

strip_markdown(strip_html(readme))

সমস্ত মার্কডাউন এবং এইচটিএমএল সঠিকভাবে সরান।


0

বিউটিফুলসৌপ, এইচটিএমএল টেক্সট বা @ এলফের কোড ব্যবহার করে বেশিরভাগ সময় এটি কিছু এইচটিএমএল উপাদান, জাভাস্ক্রিপ্ট কোড ...

সুতরাং আপনি এই লাইব্রেরির সংমিশ্রণটি ব্যবহার করতে পারেন এবং মার্কডাউন ফর্ম্যাটিংটি (পাইথন 3) মুছতে পারেন:

import re
import html2text
from bs4 import BeautifulSoup
def html2Text(html):
    def removeMarkdown(text):
        for current in ["^[ #*]{2,30}", "^[ ]{0,30}\d\\\.", "^[ ]{0,30}\d\."]:
            markdown = re.compile(current, flags=re.MULTILINE)
            text = markdown.sub(" ", text)
        return text
    def removeAngular(text):
        angular = re.compile("[{][|].{2,40}[|][}]|[{][*].{2,40}[*][}]|[{][{].{2,40}[}][}]|\[\[.{2,40}\]\]")
        text = angular.sub(" ", text)
        return text
    h = html2text.HTML2Text()
    h.images_to_alt = True
    h.ignore_links = True
    h.ignore_emphasis = False
    h.skip_internal_links = True
    text = h.handle(html)
    soup = BeautifulSoup(text, "html.parser")
    text = soup.text
    text = removeAngular(text)
    text = removeMarkdown(text)
    return text

এটি আমার পক্ষে ভাল কাজ করে তবে অবশ্যই এটি বাড়ানো যেতে পারে ...


0

সাধারণ কোড !. এটি এর ভিতরে থাকা সমস্ত ধরণের ট্যাগ এবং সামগ্রী সরিয়ে ফেলবে।

def rm(s):
    start=False
    end=False
    s=' '+s
    for i in range(len(s)-1):
        if i<len(s):
            if start!=False:
                if s[i]=='>':
                    end=i
                    s=s[:start]+s[end+1:]
                    start=end=False
            else:
                if s[i]=='<':
                    start=i
    if s.count('<')>0:
        self.rm(s)
    else:
        s=s.replace('&nbsp;', ' ')
        return s

তবে পাঠ্যের ভিতরে <> চিহ্ন থাকলে এটি সম্পূর্ণ ফলাফল দেয় না।


0
# This is a regex solution.
import re
def removeHtml(html):
  if not html: return html
  # Remove comments first
  innerText = re.compile('<!--[\s\S]*?-->').sub('',html)
  while innerText.find('>')>=0: # Loop through nested Tags
    text = re.compile('<[^<>]+?>').sub('',innerText)
    if text == innerText:
      break
    innerText = text

  return innerText.strip()

-2

এই পদ্ধতিটি আমার পক্ষে নির্দ্বিধায় কাজ করে এবং কোনও অতিরিক্ত ইনস্টলেশন প্রয়োজন নেই:

import re
import htmlentitydefs

def convertentity(m):
    if m.group(1)=='#':
        try:
            return unichr(int(m.group(2)))
        except ValueError:
            return '&#%s;' % m.group(2)
        try:
            return htmlentitydefs.entitydefs[m.group(2)]
        except KeyError:
            return '&%s;' % m.group(2)

def converthtml(s):
    return re.sub(r'&(#?)(.+?);',convertentity,s)

html =  converthtml(html)
html.replace("&nbsp;", " ") ## Get rid of the remnants of certain formatting(subscript,superscript,etc).

3
এটি এইচটিএমএল সত্তাকে প্লেইন টেক্সটে ডিকোড করে তবে স্পষ্টতই কোনও ট্যাগ ফেলা যায় না, যা মূল প্রশ্ন ছিল। (এছাড়াও, দ্বিতীয় চেষ্টাটি বাদে কোডটি আরও বেশি করার জন্য ডি-ইন্টেন্ট করা দরকার)।
সেরেন ল্যাভবার্গ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.