Güzel Çorba - Hızlı Kılavuz
Günümüz dünyasında, ücretsiz olarak erişilebilen tonlarca yapılandırılmamış veri / bilgiye (çoğunlukla web verileri) sahibiz. Bazen ücretsiz olarak sunulan verilerin okunması kolaydır ve bazen okunmaz. Verileriniz nasıl kullanılabilir olursa olsun, web kazıma, yapılandırılmamış verileri okunması ve analiz edilmesi daha kolay yapılandırılmış verilere dönüştürmek için çok yararlı bir araçtır. Diğer bir deyişle, bu muazzam miktardaki veriyi toplamanın, düzenlemenin ve analiz etmenin bir yolu da web kazımadır. Öyleyse önce web kazımanın ne olduğunu anlayalım.
Web kazıma nedir?
Kazıma, basitçe verilerin çıkarılması (çeşitli yollarla), kopyalanması ve taranması işlemidir.
Web'den (web sayfalarından veya web sitelerinden olduğu gibi) veri veya beslemeleri kazıdığımızda veya çıkardığımızda, buna web kazıma adı verilir.
Bu nedenle, web veri çıkarma veya web toplama olarak da bilinen web kazıma, web'den verilerin çıkarılmasıdır. Kısacası, web kazıma, geliştiricilere internetten veri toplama ve analiz etme yolu sağlar.
Neden Web kazıma?
Web kazıma, bir insanın internette gezinirken yaptığı çoğu şeyi otomatikleştirmek için harika araçlardan birini sağlar. Web kazıma, bir kuruluşta çeşitli şekillerde kullanılır -
Araştırma Verileri
Akıllı analist (araştırmacı veya gazeteci gibi), web sitelerinden verileri manuel olarak toplamak ve temizlemek yerine web sıyırıcı kullanır.
Ürün fiyatları ve popülerlik karşılaştırması
Şu anda, çok sayıda çevrimiçi siteden veri toplamak ve bunları ürünlerin popülerliğini ve fiyatlarını karşılaştırmak için web kazıyıcıları kullanan birkaç hizmet var.
SEO İzleme
Rekabet analizi yapmak ve müşterinizin web sitelerinden veri çekmek için kullanılan Ahrefs, Seobility, SEMrush vb. Gibi çok sayıda SEO aracı vardır.
Arama motorları
İşleri yalnızca web kazıma dayalı bazı büyük BT şirketleri var.
Satış ve Pazarlama
Web kazıma yoluyla toplanan veriler, pazarlamacılar tarafından farklı nişleri ve rakipleri analiz etmek için veya satış uzmanı tarafından içerik pazarlaması veya sosyal medya tanıtım hizmetleri satmak için kullanılabilir.
Neden Web Kazıma için Python?
Python, web tarama ile ilgili görevlerin çoğunu çok kolay bir şekilde gerçekleştirebildiği için web kazıma için en popüler dillerden biridir.
Aşağıda web kazıma için neden python seçmeniz gerektiğine dair bazı noktalar verilmiştir:
Kullanım kolaylığı
Geliştiricilerin çoğu python'un kodlanmasının çok kolay olduğu konusunda hemfikirdir. Küme parantezi "{}" veya noktalı virgül ";" kullanmak zorunda değiliz Web kazıyıcıları geliştirirken daha okunabilir ve kullanımı kolay hale getirir.
Büyük Kütüphane Desteği
Python, farklı gereksinimler için çok sayıda kitaplık sağlar, bu nedenle web kazıma ve veri görselleştirme, makine öğrenimi vb. İçin uygundur.
Kolayca Açıklanabilir Sözdizimi
Python, python sözdiziminin anlaşılması kolay olduğu için çok okunabilir bir programlama dilidir. Python çok etkileyici ve kod girintisi, kullanıcıların koddaki farklı blokları veya kapsamları ayırt etmelerine yardımcı olur.
Dinamik olarak yazılmış dil
Python, dinamik olarak yazılmış bir dildir, yani bir değişkene atanan veriler onun ne tür bir değişken olduğunu söyler. Çok zaman kazandırır ve işi daha hızlı hale getirir.
Büyük Topluluk
Python topluluğu çok büyüktür ve kod yazarken nereye takılırsan takılmana yardımcı olur.
Güzel Çorbaya Giriş
Güzel Çorba, adını "Alice Harikalar Diyarında" daki aynı adlı Lewis Carroll şiirinden alan bir python kitaplığıdır. Beautiful Soup bir python paketidir ve adından da anlaşılacağı gibi istenmeyen verileri ayrıştırır ve kötü HTML'yi düzelterek dağınık web verilerini düzenlemeye ve biçimlendirmeye yardımcı olur ve bize kolayca geçilebilir XML yapılarında sunar.
Kısacası, Beautiful Soup, HTML ve XML belgelerinden veri çekmemizi sağlayan bir python paketidir.
BeautifulSoup standart bir python kitaplığı olmadığı için önce onu kurmamız gerekiyor. En sonuncusu olan BeautifulSoup 4 kütüphanesini (BS4 olarak da bilinir) kuracağız.
Mevcut kurulumu bozmamak için çalışma ortamımızı izole etmek için önce sanal bir ortam oluşturalım.
Sanal ortam oluşturma (isteğe bağlı)
Bir sanal ortam, dış kurulumu etkilemeden belirli bir proje için izole edilmiş bir çalışma python kopyası oluşturmamızı sağlar.
Herhangi bir python paket makinesini kurmanın en iyi yolu pip kullanmaktır, ancak pip zaten kurulu değilse (komutunuzda veya kabuk isteminizde - "pip –version" kullanarak kontrol edebilirsiniz), aşağıdaki komutu vererek kurabilirsiniz -
Linux ortamı
$sudo apt-get install python-pip
Windows ortamı
Windows'ta pip kurmak için aşağıdakileri yapın -
Get-pip.py dosyasını şu adresten indirin: https://bootstrap.pypa.io/get-pip.py veya github'dan bilgisayarınıza.
Komut istemini açın ve get-pip.py dosyasını içeren klasöre gidin.
Aşağıdaki komutu çalıştırın -
>python get-pip.py
İşte bu, pip artık Windows makinenize yüklenmiştir.
Aşağıdaki komutu çalıştırarak pip'inizin kurulu olduğunu doğrulayabilirsiniz -
>pip --version
pip 19.2.3 from c:\users\yadur\appdata\local\programs\python\python37\lib\site-packages\pip (python 3.7)
Sanal ortamı kurma
Komut isteminizde aşağıdaki komutu çalıştırın -
>pip install virtualenv
Çalıştırdıktan sonra aşağıdaki ekran görüntüsünü göreceksiniz -
Aşağıdaki komut, mevcut dizininizde bir sanal ortam ("myEnv") oluşturacaktır -
>virtualenv myEnv
Ekran görüntüsü
Sanal ortamınızı etkinleştirmek için aşağıdaki komutu çalıştırın -
>myEnv\Scripts\activate
Yukarıdaki ekran görüntüsünde, "myEnv" sanal ortamı altında olduğumuzu söyleyen önek olarak "myEnv" olduğunu görebilirsiniz.
Sanal ortamdan çıkmak için devre dışı bırak'ı çalıştırın.
(myEnv) C:\Users\yadur>deactivate
C:\Users\yadur>
Sanal ortamımız hazır olduğu için şimdi beautifulsoup kuralım.
BeautifulSoup Kurulumu
BeautifulSoup standart bir kütüphane olmadığı için onu kurmamız gerekiyor. BeautifulSoup 4 paketini (bs4 olarak bilinir) kullanacağız.
Linux Makinesi
Sistem paket yöneticisini kullanarak bs4'ü Debian veya Ubuntu linux üzerine kurmak için aşağıdaki komutu çalıştırın -
$sudo apt-get install python-bs4 (for python 2.x)
$sudo apt-get install python3-bs4 (for python 3.x)
Bs4'ü easy_install veya pip kullanarak kurabilirsiniz (sistem paketleyiciyi kullanarak yüklemede sorun bulursanız).
$easy_install beautifulsoup4
$pip install beautifulsoup4
(Python3 kullanıyorsanız, sırasıyla easy_install3 veya pip3 kullanmanız gerekebilir)
Windows Makinesi
Beautifulsoup4'ü pencerelere kurmak çok basittir, özellikle zaten pip yüklediyseniz.
>pip install beautifulsoup4
Yani şimdi güzelsoup4 makinemize yüklendi. Kurulumdan sonra karşılaşılan bazı problemlerden bahsedelim.
Kurulumdan sonra sorunlar
Windows makinesinde karşılaşabilirsiniz, yanlış sürüm kurulurken esas olarak hata -
hata: ImportError “No module named HTMLParser”, sonra Python 3 altında kodun python 2 sürümünü çalıştırıyor olmalısınız.
hata: ImportError “No module named html.parser” hatası varsa, Python 2 altında kodun Python 3 sürümünü çalıştırıyor olmalısınız.
Yukarıdaki iki durumdan çıkmanın en iyi yolu BeautifulSoup'u yeniden kurmak ve mevcut kurulumu tamamen kaldırmaktır.
Eğer alırsan SyntaxError “Invalid syntax” ROOT_TAG_NAME = u '[belge]' satırındaysa, python 2 kodunu python 3'e, yalnızca paketi kurarak dönüştürmeniz gerekir -
$ python3 setup.py install
veya python'un 2 ila 3 dönüştürme komut dosyasını bs4 dizininde manuel olarak çalıştırarak -
$ 2to3-3.2 -w bs4
Bir Ayrıştırıcı Yükleme
Varsayılan olarak Beautiful Soup, Python'un standart kitaplığında bulunan HTML ayrıştırıcısını destekler, ancak aynı zamanda lxml ayrıştırıcı veya html5lib ayrıştırıcı gibi birçok harici üçüncü taraf python ayrıştırıcısını da destekler.
Lxml veya html5lib ayrıştırıcısını kurmak için şu komutu kullanın -
Linux Makinesi
$apt-get install python-lxml
$apt-get insall python-html5lib
Windows Makinesi
$pip install lxml
$pip install html5lib
Genellikle, kullanıcılar hız için lxml kullanırlar ve python'un yerleşik HTML ayrıştırıcısı olarak python 2'nin (2.7.3 sürümünden önce) veya python 3'ün (3.2.2'den önce) eski sürümünü kullanıyorsanız, lxml veya html5lib ayrıştırıcı kullanmanız önerilir. eski sürümün kullanımında pek iyi değil.
Güzel Çorba Koşuyor
Güzel Çorba paketimizi html sayfalarından birinde test etme zamanı (web sayfasını alarak - https://www.tutorialspoint.com/index.htm, istediğiniz herhangi bir web sayfasını seçebilir ve ondan bazı bilgiler alabilirsiniz.
Aşağıdaki kodda, başlığı web sayfasından çıkarmaya çalışıyoruz -
from bs4 import BeautifulSoup
import requests
url = "https://www.tutorialspoint.com/index.htm"
req = requests.get(url)
soup = BeautifulSoup(req.text, "html.parser")
print(soup.title)
Çıktı
<title>H2O, Colab, Theano, Flutter, KNime, Mean.js, Weka, Solidity, Org.Json, AWS QuickSight, JSON.Simple, Jackson Annotations, Passay, Boon, MuleSoft, Nagios, Matplotlib, Java NIO, PyTorch, SLF4J, Parallax Scrolling, Java Cryptography</title>
Yaygın bir görev, bir web sayfasındaki tüm URL'leri çıkarmaktır. Bunun için aşağıdaki kod satırını eklememiz yeterlidir -
for link in soup.find_all('a'):
print(link.get('href'))
Çıktı
https://www.tutorialspoint.com/index.htm
https://www.tutorialspoint.com/about/about_careers.htm
https://www.tutorialspoint.com/questions/index.php
https://www.tutorialspoint.com/online_dev_tools.htm
https://www.tutorialspoint.com/codingground.htm
https://www.tutorialspoint.com/current_affairs.htm
https://www.tutorialspoint.com/upsc_ias_exams.htm
https://www.tutorialspoint.com/tutor_connect/index.php
https://www.tutorialspoint.com/whiteboard.htm
https://www.tutorialspoint.com/netmeeting.php
https://www.tutorialspoint.com/index.htm
https://www.tutorialspoint.com/tutorialslibrary.htm
https://www.tutorialspoint.com/videotutorials/index.php
https://store.tutorialspoint.com
https://www.tutorialspoint.com/gate_exams_tutorials.htm
https://www.tutorialspoint.com/html_online_training/index.asp
https://www.tutorialspoint.com/css_online_training/index.asp
https://www.tutorialspoint.com/3d_animation_online_training/index.asp
https://www.tutorialspoint.com/swift_4_online_training/index.asp
https://www.tutorialspoint.com/blockchain_online_training/index.asp
https://www.tutorialspoint.com/reactjs_online_training/index.asp
https://www.tutorix.com
https://www.tutorialspoint.com/videotutorials/top-courses.php
https://www.tutorialspoint.com/the_full_stack_web_development/index.asp
….
….
https://www.tutorialspoint.com/online_dev_tools.htm
https://www.tutorialspoint.com/free_web_graphics.htm
https://www.tutorialspoint.com/online_file_conversion.htm
https://www.tutorialspoint.com/netmeeting.php
https://www.tutorialspoint.com/free_online_whiteboard.htm
http://www.tutorialspoint.com
https://www.facebook.com/tutorialspointindia
https://plus.google.com/u/0/+tutorialspoint
http://www.twitter.com/tutorialspoint
http://www.linkedin.com/company/tutorialspoint
https://www.youtube.com/channel/UCVLbzhxVTiTLiVKeGV7WEBg
https://www.tutorialspoint.com/index.htm
/about/about_privacy.htm#cookies
/about/faq.htm
/about/about_helping.htm
/about/contact_us.htm
Benzer şekilde, beautifulsoup4 kullanarak faydalı bilgiler elde edebiliriz.
Şimdi yukarıdaki örnekte "çorba" yı daha iyi anlayalım.
Önceki kod örneğinde, bir dize yöntemi kullanarak belgeyi güzel bir kurucu aracılığıyla ayrıştırıyoruz. Başka bir yol da belgeyi açık dosya tanıtıcısından geçirmektir.
from bs4 import BeautifulSoup
with open("example.html") as fp:
soup = BeautifulSoup(fp)
soup = BeautifulSoup("<html>data</html>")
Önce belge Unicode'a dönüştürülür ve HTML varlıkları Unicode karakterlere dönüştürülür: </p>
import bs4
html = '''<b>tutorialspoint</b>, <i>&web scraping &data science;</i>'''
soup = bs4.BeautifulSoup(html, 'lxml')
print(soup)
Çıktı
<html><body><b>tutorialspoint</b>, <i>&web scraping &data science;</i></body></html>
BeautifulSoup daha sonra verileri HTML ayrıştırıcısını kullanarak ayrıştırır veya siz ona açıkça bir XML ayrıştırıcı kullanarak ayrıştırmasını söylersiniz.
HTML ağaç Yapısı
Bir HTML sayfasının farklı bileşenlerine bakmadan önce, önce HTML ağaç yapısını anlayalım.
Belge ağacındaki kök öğe, ebeveynlere, çocuklara ve kardeşlere sahip olabilen html'dir ve bu, ağaç yapısındaki konumu ile belirlenir. HTML öğeleri, nitelikleri ve metin arasında hareket etmek için ağaç yapınızdaki düğümler arasında hareket etmeniz gerekir.
Web sayfasının aşağıda gösterildiği gibi olduğunu varsayalım -
Aşağıdaki gibi bir html belgesine çevrilen -
<html><head><title>TutorialsPoint</title></head><h1>Tutorialspoint Online Library</h1><p<<b>It's all Free</b></p></body></html>
Bu basitçe, yukarıdaki html belgesi için aşağıdaki gibi bir html ağaç yapımız olduğu anlamına gelir -
Güzel bir grup kurucusuna bir html belgesi veya dizesi aktardığımızda, beautifulsoup temelde karmaşık bir html sayfasını farklı python nesnelerine dönüştürür. Aşağıda dört ana tür nesneyi tartışacağız:
Tag
NavigableString
BeautifulSoup
Comments
Etiket Nesneleri
Çeşitli içerik türlerini tanımlamak için bir HTML etiketi kullanılır. BeautifulSoup'taki bir etiket nesnesi, gerçek sayfa veya belgedeki bir HTML veya XML etiketine karşılık gelir.
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup('<b class="boldest">TutorialsPoint</b>')
>>> tag = soup.html
>>> type(tag)
<class 'bs4.element.Tag'>
Etiketler birçok öznitelik ve yöntem içerir ve bir etiketin iki önemli özelliği adı ve öznitelikleridir.
İsim (tag.name)
Her etiket bir ad içerir ve sonek olarak '.name' üzerinden erişilebilir. tag.name, olduğu etiketin türünü döndürür.
>>> tag.name
'html'
Bununla birlikte, etiket adını değiştirirsek, aynısı BeautifulSoup tarafından oluşturulan HTML biçimlendirmesine yansıtılacaktır.
>>> tag.name = "Strong"
>>> tag
<Strong><body><b class="boldest">TutorialsPoint</b></body></Strong>
>>> tag.name
'Strong'
Öznitelikler (tag.attrs)
Bir etiket nesnesi herhangi bir sayıda niteliğe sahip olabilir. <B class = ”boldest”> etiketi, değeri “kalın” olan bir 'class' niteliğine sahiptir. Etiket OLMAYAN her şey temelde bir özniteliktir ve bir değer içermelidir. Özelliklere, anahtarlara erişerek (yukarıdaki örnekte "sınıf" a erişmek gibi) veya doğrudan ".attrs" aracılığıyla erişerek erişebilirsiniz.
>>> tutorialsP = BeautifulSoup("<div class='tutorialsP'></div>",'lxml')
>>> tag2 = tutorialsP.div
>>> tag2['class']
['tutorialsP']
Etiket özelliklerimizde her türlü değişikliği yapabiliriz (ekle / kaldır / değiştir).
>>> tag2['class'] = 'Online-Learning'
>>> tag2['style'] = '2007'
>>>
>>> tag2
<div class="Online-Learning" style="2007"></div>
>>> del tag2['style']
>>> tag2
<div class="Online-Learning"></div>
>>> del tag['class']
>>> tag
<b SecondAttribute="2">TutorialsPoint</b>
>>>
>>> del tag['SecondAttribute']
>>> tag
</b>
>>> tag2['class']
'Online-Learning'
>>> tag2['style']
KeyError: 'style'
Çok değerli öznitelikler
Bazı HTML5 özelliklerinin birden çok değeri olabilir. En yaygın olarak kullanılan, birden çok CSS değerine sahip olabilen sınıf niteliğidir. Diğerleri 'rel', 'rev', 'başlıklar', 'erişim anahtarı' ve 'kabul-karakter kümesini' içerir. Güzel çorbadaki çok değerli özellikler liste halinde gösterilir.
>>> from bs4 import BeautifulSoup
>>>
>>> css_soup = BeautifulSoup('<p class="body"></p>')
>>> css_soup.p['class']
['body']
>>>
>>> css_soup = BeautifulSoup('<p class="body bold"></p>')
>>> css_soup.p['class']
['body', 'bold']
Bununla birlikte, herhangi bir öznitelik birden fazla değer içeriyorsa ancak HTML standardının herhangi bir sürümüne göre çok değerli öznitelikler değilse, güzel çorba, özniteliği tek başına bırakacaktır -
>>> id_soup = BeautifulSoup('<p id="body bold"></p>')
>>> id_soup.p['id']
'body bold'
>>> type(id_soup.p['id'])
<class 'str'>
Bir etiketi dizeye çevirirseniz birden çok öznitelik değerini birleştirebilirsiniz.
>>> rel_soup = BeautifulSoup("<p> tutorialspoint Main <a rel='Index'> Page</a></p>")
>>> rel_soup.a['rel']
['Index']
>>> rel_soup.a['rel'] = ['Index', ' Online Library, Its all Free']
>>> print(rel_soup.p)
<p> tutorialspoint Main <a rel="Index Online Library, Its all Free"> Page</a></p>
'Get_attribute_list' kullanarak, çok değerli olup olmadığına bakılmaksızın her zaman bir liste, dize olan bir değer elde edersiniz.
id_soup.p.get_attribute_list(‘id’)
Ancak, belgeyi 'xml' olarak ayrıştırırsanız, çok değerli öznitelikler yoktur -
>>> xml_soup = BeautifulSoup('<p class="body bold"></p>', 'xml')
>>> xml_soup.p['class']
'body bold'
NavigableString
Navigablestring nesnesi, bir etiketin içeriğini temsil etmek için kullanılır. İçeriğe erişmek için, etiketiyle ".string" kullanın.
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>>
>>> soup.string
'Hello, Tutorialspoint!'
>>> type(soup.string)
>
Dizeyi başka bir dizeyle değiştirebilirsiniz, ancak mevcut dizeyi düzenleyemezsiniz.
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>> soup.string.replace_with("Online Learning!")
'Hello, Tutorialspoint!'
>>> soup.string
'Online Learning!'
>>> soup
<html><body><h2 id="message">Online Learning!</h2></body></html>
Güzel çorba
BeautifulSoup, bir web kaynağını kazımaya çalıştığımızda oluşturulan nesnedir. Yani, kazımaya çalıştığımız tam belgedir. Çoğu zaman etiket nesnesi olarak ele alınır.
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>> type(soup)
<class 'bs4.BeautifulSoup'>
>>> soup.name
'[document]'
Yorumlar
Yorum nesnesi, web belgesinin yorum bölümünü gösterir. Bu sadece özel bir NavigableString türüdür.
>>> soup = BeautifulSoup('<p><!-- Everything inside it is COMMENTS --></p>')
>>> comment = soup.p.string
>>> type(comment)
<class 'bs4.element.Comment'>
>>> type(comment)
<class 'bs4.element.Comment'>
>>> print(soup.p.prettify())
<p>
<!-- Everything inside it is COMMENTS -->
</p>
NavigableString Nesneleri
Gezinilebilir nesneler, etiketlerin kendileri yerine etiketlerin içindeki metni temsil etmek için kullanılır.
Bu bölümde, Etiketlere Göre Gezinmeyi tartışacağız.
Aşağıda html belgemiz var -
>>> html_doc = """
<html><head><title>Tutorials Point</title></head>
<body>
<p class="title"><b>The Biggest Online Tutorials Library, It's all Free</b></p>
<p class="prog">Top 5 most used Programming Languages are:
<a href="https://www.tutorialspoint.com/java/java_overview.htm" class="prog" id="link1">Java</a>,
<a href="https://www.tutorialspoint.com/cprogramming/index.htm" class="prog" id="link2">C</a>,
<a href="https://www.tutorialspoint.com/python/index.htm" class="prog" id="link3">Python</a>,
<a href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" class="prog" id="link4">JavaScript</a> and
<a href="https://www.tutorialspoint.com/ruby/index.htm" class="prog" id="link5">C</a>;
as per online survey.</p>
<p class="prog">Programming Languages</p>
"""
>>>
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html_doc, 'html.parser')
>>>
Yukarıdaki belgeye dayanarak, belgenin bir bölümünden diğerine geçmeye çalışacağız.
İnme
Herhangi bir HTML belgesindeki önemli öğe parçalarından biri, diğer etiketleri / dizeleri (etiketin alt öğeleri) içerebilen etiketlerdir. Beautiful Soup, etiketinin alt öğelerinde gezinmek ve üzerinde yinelemek için farklı yollar sunar.
Etiket adlarını kullanarak gezinme
Bir ayrıştırma ağacını aramanın en kolay yolu, etiketi adına göre aramaktır. <head> etiketini istiyorsanız, çorba.head kullanın -
>>> soup.head
<head>&t;title>Tutorials Point</title></head>
>>> soup.title
<title>Tutorials Point</title>
<body> etiketinde belirli bir etiketi (ilk <b> etiketi gibi) almak için.
>>> soup.body.b
<b>The Biggest Online Tutorials Library, It's all Free</b>
Bir etiket adını öznitelik olarak kullanmak, size yalnızca o ada sahip ilk etiketi verir -
>>> soup.a
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
Tüm etiketin özniteliğini almak için find_all () yöntemini kullanabilirsiniz -
>>> soup.find_all("a")
[<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>, <a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>, <a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>, <a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>, <a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>]>>> soup.find_all("a")
[<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>, <a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>, <a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>, <a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>, <a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>]
.contents ve .children
Etiketinin alt öğelerini bir listede .içeriklerine göre arayabiliriz -
>>> head_tag = soup.head
>>> head_tag
<head><title>Tutorials Point</title></head>
>>> Htag = soup.head
>>> Htag
<head><title>Tutorials Point</title></head>
>>>
>>> Htag.contents
[<title>Tutorials Point</title>
>>>
>>> Ttag = head_tag.contents[0]
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.contents
['Tutorials Point']
BeautifulSoup nesnesinin kendisinin alt öğeleri vardır. Bu durumda, <html> etiketi BeautifulSoup nesnesinin alt öğesidir -
>>> len(soup.contents)
2
>>> soup.contents[1].name
'html'
Bir dizede .contents yoktur, çünkü hiçbir şey içeremez -
>>> text = Ttag.contents[0]
>>> text.contents
self.__class__.__name__, attr))
AttributeError: 'NavigableString' object has no attribute 'contents'
Bunları liste olarak almak yerine etiketin alt öğelerine erişmek için .children oluşturucuyu kullanın -
>>> for child in Ttag.children:
print(child)
Tutorials Point
.torunları
.Descendants özniteliği, bir etiketin tüm alt öğelerini yinelemeli olarak yinelemenizi sağlar -
doğrudan çocukları ve doğrudan çocuklarının çocukları vb. -
>>> for child in Htag.descendants:
print(child)
<title>Tutorials Point</title>
Tutorials Point
<head> etiketinin yalnızca bir alt öğesi vardır, ancak iki nesli vardır: <title> etiketi ve <title> etiketinin alt öğesi. Beautifulsoup nesnesinin yalnızca bir doğrudan alt öğesi (<html> etiketi) vardır, ancak çok sayıda nesli vardır -
>>> len(list(soup.children))
2
>>> len(list(soup.descendants))
33
.string
Etiketin yalnızca bir alt öğesi varsa ve bu alt öğe bir NavigableString ise, alt öğe .string olarak kullanıma sunulur -
>>> Ttag.string
'Tutorials Point'
Bir etiketin tek alt etiketi başka bir etiketse ve bu etiketin bir .string'i varsa, bu durumda üst etiketin, alt etiketiyle aynı .string'e sahip olduğu kabul edilir -
>>> Htag.contents
[<title>Tutorials Point</title>]
>>>
>>> Htag.string
'Tutorials Point'
Bununla birlikte, bir etiket birden fazla şey içeriyorsa, .string'in neye başvurması gerektiği açık değildir, bu nedenle .string, Yok olarak tanımlanır -
>>> print(soup.html.string)
None
.strings ve stripped_strings
Bir etiketin içinde birden fazla şey varsa, yine de yalnızca dizelere bakabilirsiniz. .Strings oluşturucuyu kullanın -
>>> for string in soup.strings:
print(repr(string))
'\n'
'Tutorials Point'
'\n'
'\n'
"The Biggest Online Tutorials Library, It's all Free"
'\n'
'Top 5 most used Programming Languages are: \n'
'Java'
',\n'
'C'
',\n'
'Python'
',\n'
'JavaScript'
' and\n'
'C'
';\n \nas per online survey.'
'\n'
'Programming Languages'
'\n'
Fazladan boşlukları kaldırmak için .stripped_strings generator kullanın -
>>> for string in soup.stripped_strings:
print(repr(string))
'Tutorials Point'
"The Biggest Online Tutorials Library, It's all Free"
'Top 5 most used Programming Languages are:'
'Java'
','
'C'
','
'Python'
','
'JavaScript'
'and'
'C'
';\n \nas per online survey.'
'Programming Languages'
Yukarı çıkıyor
Bir "aile ağacı" benzetmesinde, her etiketin ve her dizenin bir üst öğesi vardır: onu içeren etiket:
.parent
Öğenin üst öğesine erişmek için, .parent özelliğini kullanın.
>>> Ttag = soup.title
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.parent
<head>title>Tutorials Point</title></head>
Bizim html_doc'umuzda, başlık dizesinin kendisinin bir ebeveyni vardır: onu içeren <title> etiketi−
>>> Ttag.string.parent
<title>Tutorials Point</title>
<html> gibi üst düzey bir etiketin üst öğesi Beautifulsoup nesnesinin kendisidir -
>>> htmltag = soup.html
>>> type(htmltag.parent)
<class 'bs4.BeautifulSoup'>
Beautifulsoup nesnesinin .parent öğesi Yok olarak tanımlanır -
>>> print(soup.parent)
None
.ebeveynler
Tüm üst öğe öğelerini yinelemek için .parents özelliğini kullanın.
>>> link = soup.a
>>> link
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
>>>
>>> for parent in link.parents:
if parent is None:
print(parent)
else:
print(parent.name)
p
body
html
[document]
Yana doğru gidiyor
Aşağıda basit bir belge var -
>>> sibling_soup = BeautifulSoup("<a><b>TutorialsPoint</b><c><strong>The Biggest Online Tutorials Library, It's all Free</strong></b></a>")
>>> print(sibling_soup.prettify())
<html>
<body>
<a>
<b>
TutorialsPoint
</b>
<c>
<strong>
The Biggest Online Tutorials Library, It's all Free
</strong>
</c>
</a>
</body>
</html>
Yukarıdaki dokümanda, <b> ve <c> etiketi aynı düzeydedir ve her ikisi de aynı etiketin alt öğesidir. Hem <b> hem de <c> etiketi kardeşlerdir.
.next_sibling ve .previous_sibling
Ayrıştırma ağacının aynı düzeyindeki sayfa öğeleri arasında gezinmek için .next_sibling ve .previous_sibling kullanın:
>>> sibling_soup.b.next_sibling
<c><strong>The Biggest Online Tutorials Library, It's all Free</strong></c>
>>>
>>> sibling_soup.c.previous_sibling
<b>TutorialsPoint</b>
<b> etiketinde .next_sibling bulunur ancak .previous_sibling yoktur, çünkü ağacın aynı düzeyinde <b> etiketinden önce hiçbir şey yoktur, aynı durum <c> etiketinde de geçerlidir.
>>> print(sibling_soup.b.previous_sibling)
None
>>> print(sibling_soup.c.next_sibling)
None
İki dizi aynı ebeveyne sahip olmadıkları için kardeş değildir.
>>> sibling_soup.b.string
'TutorialsPoint'
>>>
>>> print(sibling_soup.b.string.next_sibling)
None
.next_siblings ve .previous_siblings
Bir etiketin kardeşlerini yinelemek için .next_siblings ve .previous_siblings kullanın.
>>> for sibling in soup.a.next_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>
',\n'
>a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>
',\n'
<a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>
' and\n'
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm"
id="link5">C</a>
';\n \nas per online survey.'
>>> for sibling in soup.find(id="link3").previous_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>
',\n'
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
'Top 5 most used Programming Languages are: \n'
İleri geri gitmek
Şimdi, önceki "html_doc" örneğimizdeki ilk iki satıra geri dönelim -
&t;html><head><title>Tutorials Point</title></head>
<body>
<h4 class="tagLine"><b>The Biggest Online Tutorials Library, It's all Free</b></h4>
Bir HTML ayrıştırıcı, yukarıdaki karakter dizisini alır ve bunu "<html> etiketi aç", "<head> etiketi aç", "<title> etiketini aç", "dize ekle" gibi bir dizi etkinliğe dönüştürür, "</title> etiketini kapat", "</head> etiketini kapat", "bir <h4> etiketi aç" vb. BeautifulSoup, belgenin ilk ayrıştırmasını yeniden yapılandırmak için farklı yöntemler sunar.
.next_element ve .previous_element
Bir etiketin veya dizenin .next_element özniteliği, hemen ardından ayrıştırılan şeyi gösterir. Bazen .next_sibling'e benziyor, ancak tamamen aynı değil. “Html_doc” örnek belgemizdeki son <a> etiketi aşağıdadır.
>>> last_a_tag = soup.find("a", id="link5")
>>> last_a_tag
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>
>>> last_a_tag.next_sibling
';\n \nas per online survey.'
Ancak, <a> etiketinin hemen ardından ayrıştırılan o <a> etiketinin .next_element cümlenin geri kalanı değil: "C" kelimesidir:
>>> last_a_tag.next_element
'C'
Yukarıdaki davranış, orijinal işaretlemede "C" harfinin bu noktalı virgülden önce görünmesidir. Ayrıştırıcı bir <a> etiketiyle, ardından "C" harfiyle, ardından kapanış </a> etiketiyle, ardından noktalı virgülle ve cümlenin geri kalanıyla karşılaştı. Noktalı virgül <a> etiketiyle aynı düzeydedir, ancak önce "C" harfiyle karşılaşılmıştır.
.Previous_element özniteliği, .next_element öğesinin tam tersidir. Bundan hemen önce ayrıştırılan öğeye işaret eder.
>>> last_a_tag.previous_element
' and\n'
>>>
>>> last_a_tag.previous_element.next_element
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>
.next_elements ve .previous_elements
Bu yineleyicileri, bir öğeye ileri ve geri gitmek için kullanırız.
>>> for element in last_a_tag.next_e lements:
print(repr(element))
'C'
';\n \nas per online survey.'
'\n'
<p class="prog">Programming Languages</p>
'Programming Languages'
'\n'
Bir ayrıştırma ağacını aramamıza izin veren birçok Beautifulsoup yöntemi vardır. En yaygın ve kullanılan iki yöntem find () ve find_all () 'dır.
Find () ve find_all () hakkında konuşmadan önce, bu yöntemlere geçirebileceğiniz bazı farklı filtre örneklerini görelim.
Filtre Türleri
Bu yöntemlere aktarabileceğimiz farklı filtrelerimiz var ve bu filtrelerin anlaşılması, bu filtrelerin arama API'si boyunca tekrar tekrar kullanıldığı için çok önemlidir. Bu filtreleri etiketin adına, özniteliklerine, bir dizenin metnine veya bunların karışımına göre kullanabiliriz.
Dizi
En basit filtre türlerinden biri dizedir. Arama yöntemine ve Beautifulsoup'a bir dize iletmek, bu tam dizeyle bir eşleşme gerçekleştirir.
Aşağıdaki kod, belgedeki tüm <p> etiketlerini bulacaktır -
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>> markup.find_all('p')
[<p>Top Three</p>, <p></p>, <p><b>Java, Python, Cplusplus</b></p>]
Düzenli ifade
Belirli bir dizeyle / etiketle başlayan tüm etiketleri bulabilirsiniz. Bundan önce, normal ifadeyi kullanmak için re modülünü içe aktarmamız gerekir.
>>> import re
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>>
>>> markup.find_all(re.compile('^p'))
[<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>]
Liste
Bir liste sağlayarak bulmak için birden çok etiketi iletebilirsiniz. Aşağıdaki kod tüm <b> ve <pre> etiketlerini bulur -
>>> markup.find_all(['pre', 'b'])
[<pre>Programming Languages are:</pre>, <b>Java, Python, Cplusplus</b>]
Doğru
True, bulabildiği tüm etiketleri döndürür, ancak kendi başına dizeleri döndürmez -
>>> markup.find_all(True)
[<html><body><p>Top Three</p><p></p><pre>Programming Languages are:</pre>
<p><b>Java, Python, Cplusplus</b> </p> </body></html>,
<body><p>Top Three</p><p></p><pre> Programming Languages are:</pre><p><b>Java, Python, Cplusplus</b></p>
</body>,
<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>, <b>Java, Python, Cplusplus</b>]
Yalnızca yukarıdaki çorbadaki etiketleri döndürmek için -
>>> for tag in markup.find_all(True):
(tag.name)
'html'
'body'
'p'
'p'
'pre'
'p'
'b'
hepsini bul()
Find_all işlevini, belirli bir etiketin tüm oluşumlarını sayfa yanıtından şu şekilde çıkarmak için kullanabilirsiniz:
Sözdizimi
find_all(name, attrs, recursive, string, limit, **kwargs)
Tüm zamanların IMDB- “En beğenilen filmlerinden” bazı ilginç veriler çıkaralım.
>>> url="https://www.imdb.com/chart/top/?ref_=nv_mv_250"
>>> content = requests.get(url)
>>> soup = BeautifulSoup(content.text, 'html.parser')
#Extract title Page
>>> print(soup.find('title'))
<title>IMDb Top 250 - IMDb</title>
#Extracting main heading
>>> for heading in soup.find_all('h1'):
print(heading.text)
Top Rated Movies
#Extracting sub-heading
>>> for heading in soup.find_all('h3'):
print(heading.text)
IMDb Charts
You Have Seen
IMDb Charts
Top India Charts
Top Rated Movies by Genre
Recently Viewed
Yukarıdan, find_all'ın bize tanımladığımız arama kriterleriyle eşleşen tüm öğeleri vereceğini görebiliriz. Find_all () ile kullanabileceğimiz tüm filtreler, find () ve find_parents () veya find_siblings () gibi diğer arama yöntemleriyle kullanılabilir.
bul ()
Yukarıda gördüğümüz gibi, find_all () tüm içeriği bulmak için belgenin tamamını taramak için kullanılır, ancak bir şey, yalnızca bir sonuç bulmaktır. Belgenin yalnızca bir <body> etiketi içerdiğini biliyorsanız, tüm belgeyi aramak zaman kaybıdır. Bunun bir yolu find_all () 'ı her seferinde limit = 1 ile çağırmaktır, yoksa aynı şeyi yapmak için find () yöntemini kullanabiliriz -
Sözdizimi
find(name, attrs, recursive, string, **kwargs)
Yani aşağıda iki farklı yöntem aynı çıktıyı verir -
>>> soup.find_all('title',limit=1)
[<title>IMDb Top 250 - IMDb</title>]
>>>
>>> soup.find('title')
<title>IMDb Top 250 - IMDb</title>
Yukarıdaki çıktılarda, find_all () yönteminin tek bir öğe içeren bir liste döndürdüğünü, ancak find () yönteminin tek bir sonuç döndürdüğünü görebiliriz.
Find () ve find_all () yöntemi arasındaki diğer bir fark -
>>> soup.find_all('h2')
[]
>>>
>>> soup.find('h2')
Soup.find_all () yöntemi hiçbir şey bulamazsa, boş liste döndürür, ancak find () None döndürür.
find_parents () ve find_parent ()
Ağaçta ilerleyen, etiketin alt öğelerine bakan find_all () ve find () yöntemlerinin aksine, find_parents () ve find_parents yöntemleri () tam tersini yapar, ağacı yukarı doğru hareket ettirir ve bir etiketin (veya bir dizenin) üst öğelerine bakarlar.
Sözdizimi
find_parents(name, attrs, string, limit, **kwargs)
find_parent(name, attrs, string, **kwargs)
>>> a_string = soup.find(string="The Godfather")
>>> a_string
'The Godfather'
>>> a_string.find_parents('a')
[<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>]
>>> a_string.find_parent('a')
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
>>> a_string.find_parent('tr')
<tr>
<td class="posterColumn">
<span data-value="2" name="rk"></span>
<span data-value="9.149038526210072" name="ir"></span>
<span data-value="6.93792E10" name="us"></span>
<span data-value="1485540" name="nv"></span>
<span data-value="-1.850961473789928" name="ur"></span>
<a href="/title/tt0068646/"> <img alt="The Godfather" height="67" src="https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_UY67_CR1,0,45,67_AL_.jpg" width="45"/>
</a> </td>
<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>
<td class="ratingColumn imdbRating">
<strong title="9.1 based on 1,485,540 user ratings">9.1</strong>
</td>
<td class="ratingColumn">
<div class="seen-widget seen-widget-tt0068646 pending" data-titleid="tt0068646">
<div class="boundary">
<div class="popover">
<span class="delete"> </span><ol><li>1<li>2<li>3<li>4<li>5<li>6<li>7<li>8<li>9<li>10</li>0</li></li></li></li&td;</li></li></li></li></li></ol> </div>
</div>
<div class="inline">
<div class="pending"></div>
<div class="unseeable">NOT YET RELEASED</div>
<div class="unseen"> </div>
<div class="rating"></div>
<div class="seen">Seen</div>
</div>
</div>
</td>
<td class="watchlistColumn">
<div class="wlb_ribbon" data-recordmetrics="true" data-tconst="tt0068646"></div>
</td>
</tr>
>>>
>>> a_string.find_parents('td')
[<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>]
Sekiz başka benzer yöntem var -
find_next_siblings(name, attrs, string, limit, **kwargs)
find_next_sibling(name, attrs, string, **kwargs)
find_previous_siblings(name, attrs, string, limit, **kwargs)
find_previous_sibling(name, attrs, string, **kwargs)
find_all_next(name, attrs, string, limit, **kwargs)
find_next(name, attrs, string, **kwargs)
find_all_previous(name, attrs, string, limit, **kwargs)
find_previous(name, attrs, string, **kwargs)
Nerede,
find_next_siblings() ve find_next_sibling() yöntemler, geçerli olandan sonra gelen öğenin tüm kardeşleri üzerinde yinelenir.
find_previous_siblings() ve find_previous_sibling() yöntemler, geçerli öğeden önce gelen tüm kardeşler üzerinde yinelenir.
find_all_next() ve find_next() yöntemler, geçerli öğeden sonra gelen tüm etiketleri ve dizeleri yineler.
find_all_previous ve find_previous() yöntemler, geçerli öğeden önce gelen tüm etiketleri ve dizeleri yineler.
CSS seçiciler
En sık kullanılan CSS seçicilerini desteklemek için BeautifulSoup kitaplığı. Select () yönteminin yardımıyla CSS seçicilerini kullanarak öğeleri arayabilirsiniz.
İşte bazı örnekler -
>>> soup.select('title')
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>>
>>> soup.select("p:nth-of-type(1)")
[<p>The Top Rated Movie list only includes theatrical features.</p>, <p> class="imdb-footer__copyright _2-iNNCFskmr4l2OFN2DRsf">© 1990- by IMDb.com, Inc.</p>]
>>> len(soup.select("p:nth-of-type(1)"))
2
>>> len(soup.select("a"))
609
>>> len(soup.select("p"))
2
>>> soup.select("html head title")
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>> soup.select("head > title")
[<title>IMDb Top 250 - IMDb</title>]
#print HTML code of the tenth li elemnet
>>> soup.select("li:nth-of-type(10)")
[<li class="subnav_item_main">
<a href="/search/title?genres=film_noir&sort=user_rating,desc&title_type=feature&num_votes=25000,">Film-Noir
</a> </li>]
BeautifulSoup'un önemli yönlerinden biri ayrıştırma ağacında arama yapmaktır ve ihtiyacınıza göre web belgesinde değişiklik yapmanıza izin verir. .Name, .string veya .append () yöntemi gibi özniteliklerini kullanarak etiketin özelliklerinde değişiklikler yapabiliriz. .New_string () ve .new_tag () yöntemleri yardımıyla mevcut bir etikete yeni etiketler ve dizeler eklemenizi sağlar. HTML veya XML belgenizde çeşitli değişiklikler yapmak için .insert (), .insert_before () veya .insert_after () gibi başka yöntemler de vardır.
Etiket adlarını ve niteliklerini değiştirme
Çorbayı oluşturduktan sonra, etiketi yeniden adlandırmak, özniteliklerinde değişiklik yapmak, yeni öznitelikler eklemek ve öznitelikleri silmek gibi değişiklikler yapmak kolaydır.
>>> soup = BeautifulSoup('<b class="bolder">Very Bold</b>')
>>> tag = soup.b
Değişiklik ve yeni özniteliklerin eklenmesi aşağıdaki gibidir -
>>> tag.name = 'Blockquote'
>>> tag['class'] = 'Bolder'
>>> tag['id'] = 1.1
>>> tag
<Blockquote class="Bolder" id="1.1">Very Bold</Blockquote>
Özniteliklerin silinmesi aşağıdaki gibidir -
>>> del tag['class']
>>> tag
<Blockquote id="1.1">Very Bold</Blockquote>
>>> del tag['id']
>>> tag
<Blockquote>Very Bold</Blockquote>
.String değiştiriliyor
Etiketin .string özniteliğini kolayca değiştirebilirsiniz -
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">Must for every <i>Learner>/i<</a>'
>>> Bsoup = BeautifulSoup(markup)
>>> tag = Bsoup.a
>>> tag.string = "My Favourite spot."
>>> tag
<a href="https://www.tutorialspoint.com/index.htm">My Favourite spot.</a>
Yukarıdan, etiketin başka bir etiket içerip içermediğini görebiliriz, bunlar ve tüm içerikleri yeni verilerle değiştirilecektir.
ekle ()
Mevcut bir etikete yeni veri / içerik eklemek tag.append () yöntemini kullanmaktır. Python listesindeki append () metoduna çok benzer.
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">Must for every <i>Learner</i></a>'
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.a.append(" Really Liked it")
>>> Bsoup
<html><body><a href="https://www.tutorialspoint.com/index.htm">Must for every <i>Learner</i> Really Liked it</a></body></html>
>>> Bsoup.a.contents
['Must for every ', <i>Learner</i>, ' Really Liked it']
NavigableString () ve .new_tag ()
Bir belgeye bir dize eklemek istemeniz durumunda, bu, append () veya NavigableString () yapıcısı kullanılarak kolayca yapılabilir -
>>> soup = BeautifulSoup("<b></b>")
>>> tag = soup.b
>>> tag.append("Start")
>>>
>>> new_string = NavigableString(" Your")
>>> tag.append(new_string)
>>> tag
<b>Start Your</b>
>>> tag.contents
['Start', ' Your']
Note: NavigableString () işlevine erişirken herhangi bir ad hatası bulursanız, aşağıdaki gibi−
NameError: 'NavigableString' adı tanımlı değil
Sadece bs4 paketinden NavigableString dizinini içe aktarın -
>>> from bs4 import NavigableString
Yukarıdaki hatayı çözebiliriz.
Mevcut etiketinize yorumlar ekleyebilir veya NavigableString'in başka bir alt sınıfını ekleyebilirsiniz, sadece yapıcıyı çağırın.
>>> from bs4 import Comment
>>> adding_comment = Comment("Always Learn something Good!")
>>> tag.append(adding_comment)
>>> tag
<b>Start Your<!--Always Learn something Good!--></b>
>>> tag.contents
['Start', ' Your', 'Always Learn something Good!']
Tamamen yeni bir etiket eklemek (mevcut bir etikete eklenmez) Beautifulsoup dahili yöntemi BeautifulSoup.new_tag () kullanılarak yapılabilir -
>>> soup = BeautifulSoup("<b></b>")
>>> Otag = soup.b
>>>
>>> Newtag = soup.new_tag("a", href="https://www.tutorialspoint.com")
>>> Otag.append(Newtag)
>>> Otag
<b><a href="https://www.tutorialspoint.com"></a></b>
Yalnızca ilk bağımsız değişken olan etiket adı gereklidir.
ekle ()
Python listesindeki .insert () yöntemine benzer şekilde, tag.insert () yeni öğe ekler, ancak tag.append () 'den farklı olarak, yeni öğe mutlaka üst öğesinin içeriğinin sonuna gitmez. Herhangi bir pozisyonda yeni eleman eklenebilir.
>>> markup = '<a href="https://www.djangoproject.com/community/">Django Official website <i>Huge Community base</i></a>'
>>> soup = BeautifulSoup(markup)
>>> tag = soup.a
>>>
>>> tag.insert(1, "Love this framework ")
>>> tag
<a href="https://www.djangoproject.com/community/">Django Official website Love this framework <i>Huge Community base</i></a>
>>> tag.contents
['Django Official website ', 'Love this framework ', <i>Huge Community base</i
>]
>>>
insert_before () ve insert_after ()
Ayrıştırma ağacındaki bir şeyin hemen öncesine bir etiket veya dizge eklemek için, insert_before () kullanılır -
>>> soup = BeautifulSoup("Brave")
>>> tag = soup.new_tag("i")
>>> tag.string = "Be"
>>>
>>> soup.b.string.insert_before(tag)
>>> soup.b
<b><i>Be</i>Brave</b>
Ayrıştırma ağacındaki bir şeyden hemen sonra bir etiket veya dizge eklemek için, insert_after () kullanın.
>>> soup.b.i.insert_after(soup.new_string(" Always "))
>>> soup.b
<b><i>Be</i> Always Brave</b>
>>> soup.b.contents
[<i>Be</i>, ' Always ', 'Brave']
açık()
Bir etiketin içeriğini kaldırmak için tag.clear () kullanın -
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical&lr;/i> Contents</a>'
>>> soup = BeautifulSoup(markup)
>>> tag = soup.a
>>> tag
<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical</i> Contents</a>
>>>
>>> tag.clear()
>>> tag
<a href="https://www.tutorialspoint.com/index.htm"></a>
Ayıkla()
Ağaçtan bir etiketi veya dizeleri kaldırmak için PageElement.extract () kullanın.
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">For <i&gr;technical & Non-technical</i> Contents</a>'
>>> soup = BeautifulSoup(markup)
>>> a_tag = soup.a
>>>
>>> i_tag = soup.i.extract()
>>>
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">For Contents</a>
>>>
>>> i_tag
<i>technical & Non-technical</i>
>>>
>>> print(i_tag.parent)
None
ayrıştır ()
Tag.decompose (), ağaçtan bir etiketi kaldırır ve tüm içeriğini siler.
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical</i> Contents</a>'
>>> soup = BeautifulSoup(markup)
>>> a_tag = soup.a
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical</i> Contents</a>
>>>
>>> soup.i.decompose()
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">For Contents</a>
>>>
Şununla değiştir()
Adından da anlaşılacağı gibi pageElement.replace_with () işlevi eski etiketi veya dizeyi ağaçtaki yeni etiket veya dizeyle değiştirir -
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">Complete Python <i>Material</i></a>'
>>> soup = BeautifulSoup(markup)
>>> a_tag = soup.a
>>>
>>> new_tag = soup.new_tag("Official_site")
>>> new_tag.string = "https://www.python.org/"
>>> a_tag.i.replace_with(new_tag)
<i>Material</i>
>>>
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">Complete Python <Official_site>https://www.python.org/</Official_site></a>
Yukarıdaki çıktıda, replace_with () öğesinin değiştirilen etiketi veya dizeyi (bizim durumumuzda "Malzeme" gibi) döndürdüğünü fark ettiniz, böylece onu inceleyebilir veya ağacın başka bir bölümüne geri ekleyebilirsiniz.
paketlemek()
PageElement.wrap (), belirttiğiniz etikette bir öğe içeriyordu ve yeni bir sarmalayıcı döndürüyor -
>>> soup = BeautifulSoup("<p>tutorialspoint.com</p>")
>>> soup.p.string.wrap(soup.new_tag("b"))
<b>tutorialspoint.com</b>
>>>
>>> soup.p.wrap(soup.new_tag("Div"))
<Div><p><b>tutorialspoint.com</b></p></Div>
sarılmamış ()
Tag.unwrap (), wrap () 'nin tam tersidir ve bir etiketi bu etiketin içindeki her şeyle değiştirir.
>>> soup = BeautifulSoup('<a href="https://www.tutorialspoint.com/">I liked <i>tutorialspoint</i></a>')
>>> a_tag = soup.a
>>>
>>> a_tag.i.unwrap()
<i></i>
>>> a_tag
<a href="https://www.tutorialspoint.com/">I liked tutorialspoint</a>
Yukarıdan, replace_with () gibi, wrrap () 'in değiştirilen etiketi döndürdüğünü fark ettiniz.
Aşağıda, daha iyi anlamak için bir tane daha wrrap () örneği verilmiştir -
>>> soup = BeautifulSoup("<p>I <strong>AM</strong> a <i>text</i>.</p>")
>>> soup.i.unwrap()
<i></i>
>>> soup
<html><body><p>I <strong>AM</strong> a text.</p></body></html>
wrrap (), işaretlemeyi şeritlemek için iyidir.
Tüm HTML veya XML belgeleri, ASCII veya UTF-8 gibi bazı özel kodlamalarda yazılır. Ancak, bu HTML / XML belgesini BeautifulSoup'a yüklediğinizde, Unicode'a dönüştürülmüştür.
>>> markup = "<p>I will display £</p>"
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.p
<p>I will display £</p>
>>> Bsoup.p.string
'I will display £'
Yukarıdaki davranış, BeautifulSoup'un bir belgenin kodlamasını algılamak ve ardından bunu Unicode'a dönüştürmek için Unicode, Dammit adlı alt kitaplığı dahili olarak kullanmasıdır.
Ancak her zaman değil, Unicode, Dammit doğru tahmin ediyor. Belge, kodlamayı tahmin etmek için bayt bayt arandığında, çok zaman alır. From_encoding olarak BeautifulSoup yapıcısına geçirerek kodlamayı zaten biliyorsanız, biraz zaman kazanabilir ve hatalardan kaçınabilirsiniz.
Aşağıda BeautifulSoup'un yanlış tanımladığı bir örnek var, bir ISO-8859-8 belgesi ISO-8859-7 olarak -
>>> markup = b"<h1>\xed\xe5\xec\xf9</h1>"
>>> soup = BeautifulSoup(markup)
>>> soup.h1
<h1>νεμω</h1>
>>> soup.original_encoding
'ISO-8859-7'
>>>
Yukarıdaki sorunu çözmek için from_encoding kullanarak BeautifulSoup'a iletin -
>>> soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
>>> soup.h1
<h1>ולש </h1>
>>> soup.original_encoding
'iso-8859-8'
>>>
BeautifulSoup 4.4.0'dan eklenen bir diğer yeni özellik ise, exclude_encoding'dir. Doğru kodlamayı bilmediğinizde ancak Unicode, Dammit'in yanlış sonuç gösterdiğinden emin olduğunuzda kullanılabilir.
>>> soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])
Çıkış kodlaması
BeautifulSoup'tan elde edilen çıktı, BeautifulSoup'a girilen belgeden bağımsız olarak UTF-8 belgesidir. Lehçe karakterlerinin ISO-8859-2 biçiminde olduğu bir belgenin altında.
html_markup = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-2">
</HEAD>
<BODY>
ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
</BODY>
</HTML>
"""
>>> soup = BeautifulSoup(html_markup)
>>> print(soup.prettify())
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
</head>
<body>
ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
</body>
</html>
Yukarıdaki örnekte, <meta> etiketinin BeautifulSoup'tan oluşturulan belgeyi yansıtacak şekilde yeniden yazıldığını fark ederseniz artık UTF-8 biçiminde.
Üretilen çıktının UTF-8'de olmasını istemiyorsanız, istediğiniz kodlamayı prettify () içinde atayabilirsiniz.
>>> print(soup.prettify("latin-1"))
b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n <head>\n <meta content="text/html; charset=latin-1" http-equiv="content-type"/>\n </head>\n <body>\n ą ć ę ł ń \xf3 ś ź ż Ą Ć Ę Ł Ń \xd3 Ś Ź Ż\n </body>\n</html>\n'
Yukarıdaki örnekte, belgenin tamamını kodladık, ancak çorbadaki herhangi bir öğeyi bir python dizesi gibi kodlayabilirsiniz -
>>> soup.p.encode("latin-1")
b'<p>0My first paragraph.</p>'
>>> soup.h1.encode("latin-1")
b'<h1>My First Heading</h1>'
Seçtiğiniz kodlamada temsil edilemeyen karakterler, sayısal XML varlık referanslarına dönüştürülecektir. Aşağıda böyle bir örnek var -
>>> markup = u"<b>\N{SNOWMAN}</b>"
>>> snowman_soup = BeautifulSoup(markup)
>>> tag = snowman_soup.b
>>> print(tag.encode("utf-8"))
b'<b>\xe2\x98\x83</b>'
Yukarıdakileri "latin-1" veya "ascii" olarak kodlamaya çalışırsanız, bunun için bir temsil olmadığını belirten "☃" üretecektir.
>>> print (tag.encode("latin-1"))
b'<b>☃</b>'
>>> print (tag.encode("ascii"))
b'<b>☃</b>'
Unicode, Lanet olsun
Unicode, Dammit esas olarak gelen belge bilinmeyen formatta olduğunda (esas olarak yabancı dilde) ve bilinen bir formatta (Unicode) kodlamak istediğimizde kullanılır ve ayrıca tüm bunları yapmak için Beautifulsoup'a ihtiyacımız yoktur.
Herhangi bir BeautifulSoup projesinin başlangıç noktası, BeautifulSoup nesnesidir. BeautifulSoup nesnesi, oluşturulması için kullanılan girdi HTML / XML belgesini temsil eder.
Beautiful Soup için bir dize veya dosya benzeri bir nesne iletebiliriz, burada dosyalar (nesneler) ya makinemizde yerel olarak depolanır ya da bir web sayfası.
En yaygın BeautifulSoup Nesneleri şunlardır:
- Tag
- NavigableString
- BeautifulSoup
- Comment
Eşitlik için nesneleri karşılaştırma
Güzel çorbaya göre, aynı HTML / XML biçimlendirmesini temsil ediyorlarsa, iki gezilebilir dize veya etiket nesnesi eşittir.
Şimdi, nesne ağacının farklı bölümlerinde yaşıyor olsalar bile, iki <b> etiketinin eşit kabul edildiği, çünkü ikisi de "<b> Java </b>" gibi göründükleri aşağıdaki örneği görelim.
>>> markup = "<p>Learn Python and <b>Java</b> and advanced <b>Java</b>! from Tutorialspoint</p>"
>>> soup = BeautifulSoup(markup, "html.parser")
>>> first_b, second_b = soup.find_all('b')
>>> print(first_b == second_b)
True
>>> print(first_b.previous_element == second_b.previous_element)
False
Ancak, iki değişkenin aynı nesnelere atıfta bulunup bulunmadığını kontrol etmek için aşağıdakileri kullanabilirsiniz−
>>> print(first_b is second_b)
False
Güzel Çorba nesnelerini kopyalama
Herhangi bir etiketin veya NavigableString'in bir kopyasını oluşturmak için, aşağıdaki gibi copy.copy () işlevini kullanın -
>>> import copy
>>> p_copy = copy.copy(soup.p)
>>> print(p_copy)
<p>Learn Python and <b>Java</b> and advanced <b>Java</b>! from Tutorialspoint</p>
>>>
İki kopya (orijinal ve kopyalanmış olan) aynı işaretlemeyi içerse de, ikisi aynı nesneyi temsil etmez -
>>> print(soup.p == p_copy)
True
>>>
>>> print(soup.p is p_copy)
False
>>>
Tek gerçek fark, kopyanın orijinal Beautiful Soup nesne ağacından tamamen ayrılmış olmasıdır, sanki üzerinde extract () çağrılmış gibi.
>>> print(p_copy.parent)
None
Yukarıdaki davranış, aynı anda aynı alanı işgal edemeyen iki farklı etiket nesnesine bağlıdır.
Beautifulsoup4 kullanarak belirli türdeki bilgileri (yalnızca <a> etiketleri) çıkarmak istediğiniz birden çok durum vardır. Beautifulsoup'taki SoupStrainer sınıfı, gelen bir belgenin yalnızca belirli bir bölümünü ayrıştırmanıza olanak tanır.
Bir yol, bir SoupStrainer oluşturmak ve bunu Beautifulsoup4 yapıcısına parse_only argümanı olarak iletmektir.
Çorba Süzgeç
Bir SoupStrainer, BeautifulSoup'a hangi parçaların çıktığını söyler ve ayrıştırma ağacı yalnızca bu öğelerden oluşur. Gerekli bilgilerinizi HTML'nin belirli bir kısmına daraltırsanız, bu arama sonucunuzu hızlandıracaktır.
product = SoupStrainer('div',{'id': 'products_list'})
soup = BeautifulSoup(html,parse_only=product)
Yukarıdaki kod satırları, yalnızca bir ürün sitesindeki, bir etiket alanının içinde olabilecek başlıkları ayrıştırır.
Benzer şekilde, yukarıda olduğu gibi, bir HTML etiketinden belirli bilgileri ayrıştırmak için diğer çorbaStrainer nesnelerini kullanabiliriz. Aşağıda örneklerden bazıları verilmiştir -
from bs4 import BeautifulSoup, SoupStrainer
#Only "a" tags
only_a_tags = SoupStrainer("a")
#Will parse only the below mentioned "ids".
parse_only = SoupStrainer(id=["first", "third", "my_unique_id"])
soup = BeautifulSoup(my_document, "html.parser", parse_only=parse_only)
#parse only where string length is less than 10
def is_short_string(string):
return len(string) < 10
only_short_strings =SoupStrainer(string=is_short_string)
Hata yönetimi
BeautifulSoup'ta ele alınması gereken iki ana hata türü vardır. BeautifulSoup API bir hata attığından, bu iki hata komut dosyanızdan değil, kod parçacığının yapısından kaynaklanmaktadır.
İki ana hata aşağıdaki gibidir -
AttributeError
Nokta notasyonunun geçerli HTML etiketine bir kardeş etiket bulmamasından kaynaklanır. Örneğin, eksik "bağlantı etiketi" nedeniyle bu hatayla karşılaşmış olabilirsiniz, maliyet anahtarı geçiş yaparken bir hata atar ve bir bağlantı etiketi gerektirir.
KeyError
Bu hata, gerekli HTML etiketi özniteliği eksikse oluşur. Örneğin, bir ön bilgide data-pid özniteliğine sahip değilsek, pid anahtarı anahtar hatası atar.
Bir sonucu ayrıştırırken yukarıda listelenen iki hatayı önlemek için, veritabanlarına hatalı biçimlendirilmiş bir snippet eklenmediğinden emin olmak için bu sonuç atlanacaktır -
except(AttributeError, KeyError) as er:
pass
teşhis koymak()
BeautifulSoup'un belgemize veya HTML'ye ne yaptığını anlamada herhangi bir zorluk bulduğumuzda, bunu diagnose () işlevine aktarmanız yeterlidir. Belge dosyasını diagnose () işlevine iletirken, farklı ayrıştırıcı listesinin belgeyi nasıl işlediğini gösterebiliriz.
Aşağıda diagnose () işlevinin kullanımını gösteren bir örnek verilmiştir -
from bs4.diagnose import diagnose
with open("20 Books.html",encoding="utf8") as fp:
data = fp.read()
diagnose(data)
Çıktı
Ayrıştırma hatası
İki ana tür ayrıştırma hatası vardır. Belgenizi BeautifulSoup'a beslediğinizde HTMLParseError gibi bir istisna elde edebilirsiniz. Ayrıca, BeautifulSoup ayrıştırma ağacının ayrıştırma belgesinden beklenen sonuçtan çok farklı göründüğü beklenmedik bir sonuç da alabilirsiniz.
Ayrıştırma hatalarının hiçbiri BeautifulSoup'tan kaynaklanmadı. BeautifulSoup herhangi bir ayrıştırıcı kodu içermediğinden, kullandığımız harici ayrıştırıcı (html5lib, lxml) yüzünden. Yukarıdaki ayrıştırma hatasını çözmenin bir yolu, başka bir ayrıştırıcı kullanmaktır.
from HTMLParser import HTMLParser
try:
from HTMLParser import HTMLParseError
except ImportError, e:
# From python 3.5, HTMLParseError is removed. Since it can never be
# thrown in 3.5, we can just define our own class as a placeholder.
class HTMLParseError(Exception):
pass
Python yerleşik HTML ayrıştırıcısı en yaygın iki ayrıştırma hatasına neden olur, HTMLParser.HTMLParserError: hatalı biçimlendirilmiş başlangıç etiketi ve HTMLParser.HTMLParserError: bozuk bitiş etiketi ve bunu çözmek için, esas olarak başka bir ayrıştırıcı kullanmaktır: lxml veya html5lib.
Diğer bir yaygın beklenmeyen davranış türü de, belgede olduğunu bildiğiniz bir etiketi bulamamanızdır. Ancak, çalıştırdığınızda find_all () [] döndürür veya find () None döndürür.
Bunun nedeni python yerleşik HTML ayrıştırıcısının bazen anlamadığı etiketleri atlaması olabilir.
XML ayrıştırıcı Hatası
Varsayılan olarak, BeautifulSoup paketi belgeleri HTML olarak ayrıştırır, ancak kullanımı çok kolaydır ve güzel biçimlendirilmiş XML'i beautifulsoup4 kullanarak çok zarif bir şekilde işleyebilir.
Belgeyi XML olarak ayrıştırmak için, lxml ayrıştırıcısına sahip olmanız ve ikinci bağımsız değişken olarak "xml" yi Beautifulsoup yapıcısına iletmeniz yeterlidir -
soup = BeautifulSoup(markup, "lxml-xml")
veya
soup = BeautifulSoup(markup, "xml")
Yaygın bir XML ayrıştırma hatası:
AttributeError: 'NoneType' object has no attribute 'attrib'
Bu, find () veya findall () işlevi kullanılırken bazı elemanların eksik olması veya tanımlanmaması durumunda olabilir.
Diğer ayrıştırma hataları
Aşağıda, bu bölümde tartışacağımız diğer ayrıştırma hatalarından bazıları verilmiştir -
Çevresel sorun
Yukarıda belirtilen ayrıştırma hatalarının dışında, betiğinizin bir işletim sisteminde çalışıp başka bir işletim sisteminde çalışmayabileceği veya bir sanal ortamda çalışıp başka bir sanal ortamda çalışmayabileceği veya çalışmayabileceği çevre sorunları gibi başka ayrıştırma sorunları ile karşılaşabilirsiniz. sanal ortamın dışında. Tüm bu sorunlar, iki ortamın farklı ayrıştırıcı kitaplıklarına sahip olmasından kaynaklanabilir.
Mevcut çalışma ortamınızda varsayılan ayrıştırıcınızı bilmeniz veya kontrol etmeniz önerilir. Geçerli çalışma ortamı için mevcut olan geçerli varsayılan ayrıştırıcıyı kontrol edebilir veya gerekli ayrıştırıcı kitaplığını, BeautifulSoup yapıcısına ikinci bağımsız değişken olarak açıkça iletebilirsiniz.
Büyük / küçük harfe duyarlı değil
HTML etiketleri ve nitelikleri büyük / küçük harfe duyarlı olmadığından, üç HTML ayrıştırıcı da etiket ve nitelik adlarını küçük harfe dönüştürür. Bununla birlikte, karışık veya büyük harfli etiketleri ve nitelikleri korumak istiyorsanız, belgeyi XML olarak ayrıştırmak daha iyidir.
UnicodeEncodeError
Aşağıdaki kod segmentine bakalım -
soup = BeautifulSoup(response, "html.parser")
print (soup)
Çıktı
UnicodeEncodeError: 'charmap' codec can't encode character '\u011f'
Yukarıdaki sorun iki ana durumdan kaynaklanıyor olabilir. Konsolunuzun nasıl görüntüleneceğini bilmediği bir unicode karakteri yazdırmaya çalışıyor olabilirsiniz. İkincisi, bir dosyaya yazmaya çalışıyorsunuz ve varsayılan kodlamanız tarafından desteklenmeyen bir Unicode karakteri iletiyorsunuz.
Yukarıdaki sorunu çözmenin bir yolu, istenen sonucu elde etmek için çorbayı yapmadan önce yanıt metnini / karakterini aşağıdaki gibi kodlamaktır -
responseTxt = response.text.encode('UTF-8')
KeyError: [attr]
Bunun nedeni, söz konusu etiket attr özniteliğini tanımlamadığında ['attr'] etiketine erişilmesidir. En yaygın hatalar şunlardır: “KeyError: 'href'” ve “KeyError: 'class'”. Attr'ın tanımlı olduğundan emin değilseniz tag.get ('attr') kullanın.
for item in soup.fetch('a'):
try:
if (item['href'].startswith('/') or "tutorialspoint" in item['href']):
(...)
except KeyError:
pass # or some other fallback action
AttributeError
AttributeError ile aşağıdaki gibi karşılaşabilirsiniz -
AttributeError: 'list' object has no attribute 'find_all'
Yukarıdaki hata temel olarak find_all () işlevinin tek bir etiket veya dize döndürmesini beklediğiniz için oluşur. Ancak, çorba.find_all bir python öğe listesi döndürür.
Tek yapmanız gereken, listeyi yinelemek ve bu öğelerden veri toplamaktır.