ซุปสวย - คู่มือฉบับย่อ

ในโลกปัจจุบันเรามีข้อมูล / ข้อมูลที่ไม่มีโครงสร้างมากมาย (ส่วนใหญ่เป็นข้อมูลเว็บ) ที่สามารถใช้ได้อย่างอิสระ บางครั้งข้อมูลที่มีอยู่อย่างอิสระนั้นอ่านง่ายและบางครั้งก็ไม่ ไม่ว่าข้อมูลของคุณจะพร้อมใช้งานอย่างไรการขูดเว็บเป็นเครื่องมือที่มีประโยชน์มากในการเปลี่ยนข้อมูลที่ไม่มีโครงสร้างให้เป็นข้อมูลที่มีโครงสร้างซึ่งอ่านและวิเคราะห์ได้ง่ายขึ้น กล่าวอีกนัยหนึ่งวิธีหนึ่งในการรวบรวมจัดระเบียบและวิเคราะห์ข้อมูลจำนวนมหาศาลนี้คือการขูดเว็บ ดังนั้นให้เราทำความเข้าใจก่อนว่าการขูดเว็บคืออะไร

Web-scraping คืออะไร?

การคัดลอกเป็นเพียงขั้นตอนการแยก (จากวิธีการต่างๆ) การคัดลอกและการคัดกรองข้อมูล

เมื่อเราทำการขูดหรือดึงข้อมูลหรือฟีดจากเว็บ (เช่นจากหน้าเว็บหรือเว็บไซต์) จะเรียกว่าการขูดเว็บ

ดังนั้นการขูดเว็บซึ่งเรียกอีกอย่างว่าการดึงข้อมูลเว็บหรือการเก็บเกี่ยวเว็บคือการดึงข้อมูลจากเว็บ ในระยะสั้นการขูดเว็บเป็นวิธีที่นักพัฒนาสามารถรวบรวมและวิเคราะห์ข้อมูลจากอินเทอร์เน็ตได้

ทำไมต้องขูดเว็บ?

การขูดเว็บเป็นหนึ่งในเครื่องมือที่ยอดเยี่ยมในการทำสิ่งต่างๆส่วนใหญ่ที่มนุษย์ทำในขณะที่ท่องเว็บโดยอัตโนมัติ Web-scraping ใช้ในองค์กรได้หลายวิธี -

ข้อมูลสำหรับการวิจัย

นักวิเคราะห์ที่ชาญฉลาด (เช่นนักวิจัยหรือนักข่าว) ใช้เว็บ scrapper แทนการรวบรวมและทำความสะอาดข้อมูลจากเว็บไซต์ด้วยตนเอง

ราคาสินค้าและการเปรียบเทียบความนิยม

ปัจจุบันมีบริการสองสามอย่างที่ใช้เครื่องขูดเว็บเพื่อรวบรวมข้อมูลจากเว็บไซต์ออนไลน์จำนวนมากและใช้เพื่อเปรียบเทียบความนิยมของผลิตภัณฑ์และราคา

การตรวจสอบ SEO

มีเครื่องมือ SEO มากมายเช่น Ahrefs, Seobility, SEMrush เป็นต้นซึ่งใช้สำหรับการวิเคราะห์การแข่งขันและการดึงข้อมูลจากเว็บไซต์ของลูกค้าของคุณ

เครื่องมือค้นหา

มี บริษัท ไอทีรายใหญ่บางแห่งที่ธุรกิจขึ้นอยู่กับการขูดเว็บเพียงอย่างเดียว

การขายและการตลาด

ข้อมูลที่รวบรวมผ่านการขูดเว็บสามารถใช้โดยนักการตลาดเพื่อวิเคราะห์เฉพาะกลุ่มและคู่แข่งที่แตกต่างกันหรือโดยผู้เชี่ยวชาญด้านการขายเพื่อขายการตลาดเนื้อหาหรือบริการส่งเสริมการขายผ่านโซเชียลมีเดีย

ทำไมต้อง Python สำหรับการขูดเว็บ

Python เป็นหนึ่งในภาษายอดนิยมสำหรับการขูดเว็บเนื่องจากสามารถจัดการกับงานที่เกี่ยวข้องกับการรวบรวมข้อมูลเว็บส่วนใหญ่ได้อย่างง่ายดาย

ด้านล่างนี้เป็นประเด็นบางประการเกี่ยวกับสาเหตุที่ต้องเลือก python สำหรับการขูดเว็บ:

สะดวกในการใช้

เนื่องจากนักพัฒนาส่วนใหญ่ยอมรับว่า python นั้นเขียนโค้ดได้ง่ายมาก เราไม่ต้องใช้วงเล็บปีกกา“ {}” หรือเซมิโคลอน“;” ได้ทุกที่ซึ่งทำให้อ่านง่ายขึ้นและใช้งานง่ายในขณะที่พัฒนาตัวขูดเว็บ

การสนับสนุนห้องสมุดขนาดใหญ่

Python มีไลบรารีจำนวนมากสำหรับความต้องการที่แตกต่างกันดังนั้นจึงเหมาะสำหรับการขูดเว็บรวมถึงการสร้างภาพข้อมูลการเรียนรู้ของเครื่อง ฯลฯ

ไวยากรณ์ที่อธิบายได้อย่างง่ายดาย

Python เป็นภาษาโปรแกรมที่อ่านง่ายมากเนื่องจากไวยากรณ์ของ python นั้นเข้าใจง่าย Python มีความชัดเจนมากและการเยื้องรหัสช่วยให้ผู้ใช้แยกความแตกต่างของบล็อกหรือสกู๊ปต่างๆในโค้ด

ภาษาที่พิมพ์แบบไดนามิก

Python เป็นภาษาที่พิมพ์แบบไดนามิกซึ่งหมายถึงข้อมูลที่กำหนดให้กับตัวแปรบอกประเภทของตัวแปร ช่วยประหยัดเวลาได้มากและทำให้งานเร็วขึ้น

ชุมชนขนาดใหญ่

ชุมชน Python มีขนาดใหญ่ซึ่งช่วยให้คุณไม่ว่าคุณจะติดอยู่ที่ใดขณะเขียนโค้ด

บทนำสู่ Beautiful Soup

The Beautiful Soup เป็นห้องสมุดงูเหลือมซึ่งตั้งชื่อตามบทกวีของ Lewis Carroll ที่มีชื่อเดียวกันใน“ Alice's Adventures in the Wonderland” Beautiful Soup เป็นแพ็คเกจ python และตามชื่อที่แนะนำจะแยกวิเคราะห์ข้อมูลที่ไม่ต้องการและช่วยในการจัดระเบียบและจัดรูปแบบข้อมูลเว็บที่ยุ่งเหยิงโดยการแก้ไข HTML ที่ไม่ดีและนำเสนอให้เราในโครงสร้าง XML ที่เข้าถึงได้ง่าย

ในระยะสั้น Beautiful Soup เป็นแพ็คเกจหลามที่ช่วยให้เราดึงข้อมูลออกจากเอกสาร HTML และ XML

เนื่องจาก BeautifulSoup ไม่ใช่ไลบรารี python มาตรฐานเราจึงต้องติดตั้งก่อน เรากำลังจะติดตั้งไลบรารี BeautifulSoup 4 (หรือที่เรียกว่า BS4) ซึ่งเป็นไลบรารีล่าสุด

ในการแยกสภาพแวดล้อมการทำงานของเราเพื่อไม่ให้รบกวนการตั้งค่าที่มีอยู่ก่อนอื่นให้เราสร้างสภาพแวดล้อมเสมือน

การสร้างสภาพแวดล้อมเสมือน (ทางเลือก)

สภาพแวดล้อมเสมือนช่วยให้เราสร้างสำเนาการทำงานที่แยกได้ของ python สำหรับโปรเจ็กต์เฉพาะโดยไม่ส่งผลกระทบต่อการตั้งค่าภายนอก

วิธีที่ดีที่สุดในการติดตั้งเครื่องแพ็กเกจ python คือการใช้ pip อย่างไรก็ตามหากยังไม่ได้ติดตั้ง pip (คุณสามารถตรวจสอบได้โดยใช้ - "pip --version" ในคำสั่งหรือพร้อมต์เชลล์ของคุณ) คุณสามารถติดตั้งได้โดยให้คำสั่งด้านล่าง -

สภาพแวดล้อม Linux

$sudo apt-get install python-pip

สภาพแวดล้อมของ Windows

ในการติดตั้ง pip ใน windows ให้ทำดังต่อไปนี้ -

  • ดาวน์โหลด get-pip.py จาก https://bootstrap.pypa.io/get-pip.py หรือจาก github ไปยังคอมพิวเตอร์ของคุณ

  • เปิดพรอมต์คำสั่งและไปที่โฟลเดอร์ที่มีไฟล์ get-pip.py

  • เรียกใช้คำสั่งต่อไปนี้ -

>python get-pip.py

เพียงเท่านี้ pip ก็ได้รับการติดตั้งในเครื่อง windows ของคุณแล้ว

คุณสามารถตรวจสอบ pip ที่ติดตั้งได้โดยเรียกใช้คำสั่งด้านล่าง -

>pip --version
pip 19.2.3 from c:\users\yadur\appdata\local\programs\python\python37\lib\site-packages\pip (python 3.7)

การติดตั้งสภาพแวดล้อมเสมือน

เรียกใช้คำสั่งด้านล่างในพรอมต์คำสั่งของคุณ -

>pip install virtualenv

หลังจากเรียกใช้คุณจะเห็นภาพหน้าจอด้านล่าง -

คำสั่งด้านล่างนี้จะสร้างสภาพแวดล้อมเสมือน (“ myEnv”) ในไดเร็กทอรีปัจจุบันของคุณ -

>virtualenv myEnv

ภาพหน้าจอ

ในการเปิดใช้งานสภาพแวดล้อมเสมือนของคุณให้รันคำสั่งต่อไปนี้ -

>myEnv\Scripts\activate

ในภาพหน้าจอด้านบนคุณจะเห็นว่าเรามี“ myEnv” เป็นคำนำหน้าซึ่งบอกว่าเราอยู่ภายใต้สภาพแวดล้อมเสมือน“ myEnv”

หากต้องการออกจากสภาพแวดล้อมเสมือนให้รันปิดใช้งาน

(myEnv) C:\Users\yadur>deactivate
C:\Users\yadur>

เมื่อสภาพแวดล้อมเสมือนของเราพร้อมแล้วตอนนี้ให้เราติดตั้ง beautifulsoup

การติดตั้ง BeautifulSoup

เนื่องจาก BeautifulSoup ไม่ใช่ไลบรารีมาตรฐานเราจึงจำเป็นต้องติดตั้ง เราจะใช้แพ็คเกจ BeautifulSoup 4 (เรียกว่า bs4)

เครื่องลินุกซ์

ในการติดตั้ง bs4 บน Debian หรือ Ubuntu linux โดยใช้ตัวจัดการแพ็คเกจระบบให้เรียกใช้คำสั่งด้านล่าง -

$sudo apt-get install python-bs4 (for python 2.x)
$sudo apt-get install python3-bs4 (for python 3.x)

คุณสามารถติดตั้ง bs4 โดยใช้ easy_install หรือ pip (ในกรณีที่คุณพบปัญหาในการติดตั้งโดยใช้ system packager)

$easy_install beautifulsoup4
$pip install beautifulsoup4

(คุณอาจต้องใช้ easy_install3 หรือ pip3 ตามลำดับหากคุณใช้ python3)

เครื่อง Windows

การติดตั้ง beautifulsoup4 ใน windows นั้นง่ายมากโดยเฉพาะถ้าคุณติดตั้ง pip ไว้แล้ว

>pip install beautifulsoup4

ตอนนี้ beautifulsoup4 ถูกติดตั้งในเครื่องของเราแล้ว ให้เราพูดถึงปัญหาที่พบหลังการติดตั้ง

ปัญหาหลังการติดตั้ง

บนเครื่อง windows คุณอาจพบข้อผิดพลาดในการติดตั้งเวอร์ชันผิดส่วนใหญ่ผ่าน -

  • ข้อผิดพลาด: ImportError “No module named HTMLParser”จากนั้นคุณต้องเรียกใช้โค้ดเวอร์ชัน python 2 ภายใต้ Python 3

  • ข้อผิดพลาด: ImportError “No module named html.parser” ข้อผิดพลาดคุณต้องเรียกใช้รหัสเวอร์ชัน Python 3 ภายใต้ Python 2

วิธีที่ดีที่สุดในการออกจากสองสถานการณ์ข้างต้นคือการติดตั้ง BeautifulSoup ใหม่อีกครั้งโดยลบการติดตั้งที่มีอยู่ออกทั้งหมด

หากคุณได้รับไฟล์ SyntaxError “Invalid syntax” ในบรรทัด ROOT_TAG_NAME = u '[document]' จากนั้นคุณต้องแปลงรหัส python 2 เป็น python 3 เพียงแค่ติดตั้งแพ็คเกจ -

$ python3 setup.py install

หรือโดยการรันสคริปต์การแปลง 2 ถึง 3 ของ python ด้วยตนเองบนไดเรกทอรี bs4 -

$ 2to3-3.2 -w bs4

การติดตั้ง Parser

โดยค่าเริ่มต้น Beautiful Soup สนับสนุนตัวแยกวิเคราะห์ HTML ที่รวมอยู่ในไลบรารีมาตรฐานของ Python แต่ยังรองรับตัวแยกวิเคราะห์ python ภายนอกหลายตัวเช่นตัวแยกวิเคราะห์ lxml หรือตัวแยกวิเคราะห์ html5lib

ในการติดตั้งตัวแยกวิเคราะห์ lxml หรือ html5lib ให้ใช้คำสั่ง -

เครื่องลินุกซ์

$apt-get install python-lxml
$apt-get insall python-html5lib

เครื่อง Windows

$pip install lxml
$pip install html5lib

โดยทั่วไปผู้ใช้จะใช้ lxml เพื่อความเร็วและขอแนะนำให้ใช้ตัวแยกวิเคราะห์ lxml หรือ html5lib หากคุณใช้ python 2 เวอร์ชันเก่ากว่า (ก่อน 2.7.3 เวอร์ชัน) หรือ python 3 (ก่อน 3.2.2) เนื่องจากตัวแยกวิเคราะห์ HTML ในตัวของ python คือ ไม่ค่อยดีในการจัดการเวอร์ชันเก่า

ใช้ซุปที่สวยงาม

ได้เวลาทดสอบแพ็กเกจ Beautiful Soup ของเราในหน้า html (โดยใช้หน้าเว็บ - https://www.tutorialspoint.com/index.htmคุณสามารถเลือกหน้าเว็บอื่น ๆ ที่คุณต้องการ) และดึงข้อมูลบางส่วนออกมา

ในโค้ดด้านล่างนี้เราพยายามดึงชื่อจากหน้าเว็บ -

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)

เอาต์พุต

<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>

งานทั่วไปอย่างหนึ่งคือการแยก URL ทั้งหมดภายในเว็บเพจ เพื่อที่เราจะต้องเพิ่มบรรทัดด้านล่างของรหัส -

for link in soup.find_all('a'):
print(link.get('href'))

เอาต์พุต

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

ในทำนองเดียวกันเราสามารถดึงข้อมูลที่เป็นประโยชน์โดยใช้ beautifulsoup4

ตอนนี้ให้เราทำความเข้าใจเพิ่มเติมเกี่ยวกับ“ ซุป” ในตัวอย่างข้างต้น

ในตัวอย่างโค้ดก่อนหน้านี้เราแยกวิเคราะห์เอกสารผ่านตัวสร้างที่สวยงามโดยใช้วิธีสตริง อีกวิธีหนึ่งคือการส่งเอกสารผ่าน open filehandle

from bs4 import BeautifulSoup
with open("example.html") as fp:
   soup = BeautifulSoup(fp)
soup = BeautifulSoup("<html>data</html>")

ขั้นแรกเอกสารจะถูกแปลงเป็น Unicode และเอนทิตี HTML จะถูกแปลงเป็นอักขระ Unicode: </p>

import bs4
html = '''<b>tutorialspoint</b>, <i>&web scraping &data science;</i>'''
soup = bs4.BeautifulSoup(html, 'lxml')
print(soup)

เอาต์พุต

<html><body><b>tutorialspoint</b>, <i>&web scraping &data science;</i></body></html>

จากนั้น BeautifulSoup จะแยกวิเคราะห์ข้อมูลโดยใช้ตัวแยกวิเคราะห์ HTML หรือคุณบอกให้แยกวิเคราะห์โดยใช้ตัวแยกวิเคราะห์ XML

โครงสร้างต้นไม้ HTML

ก่อนที่เราจะดูส่วนประกอบต่างๆของหน้า HTML ให้เราทำความเข้าใจโครงสร้างต้นไม้ HTML ก่อน

องค์ประกอบรากในแผนผังเอกสารคือ html ซึ่งสามารถมีพ่อแม่ลูกและพี่น้องและสิ่งนี้กำหนดโดยตำแหน่งในโครงสร้างต้นไม้ ในการย้ายไปมาระหว่างองค์ประกอบ HTML แอตทริบิวต์และข้อความคุณต้องย้ายไปมาระหว่างโหนดต่างๆในโครงสร้างต้นไม้ของคุณ

ให้เราสมมติว่าหน้าเว็บดังที่แสดงด้านล่าง -

ซึ่งแปลเป็นเอกสาร html ดังนี้ -

<html><head><title>TutorialsPoint</title></head><h1>Tutorialspoint Online Library</h1><p<<b>It's all Free</b></p></body></html>

ซึ่งหมายความว่าสำหรับเอกสาร html ด้านบนเรามีโครงสร้างต้นไม้ html ดังนี้ -

เมื่อเราส่งเอกสารหรือสตริง html ไปยังตัวสร้าง beautifulsoup โดยทั่วไป beautifulsoup จะแปลงหน้า html ที่ซับซ้อนเป็นวัตถุ python ที่แตกต่างกัน ด้านล่างนี้เราจะกล่าวถึงวัตถุสี่ประเภทหลัก ๆ :

  • Tag

  • NavigableString

  • BeautifulSoup

  • Comments

แท็กวัตถุ

แท็ก HTML ใช้เพื่อกำหนดเนื้อหาประเภทต่างๆ ออบเจ็กต์แท็กใน BeautifulSoup สอดคล้องกับแท็ก HTML หรือ XML ในหน้าจริงหรือเอกสาร

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup('<b class="boldest">TutorialsPoint</b>')
>>> tag = soup.html
>>> type(tag)
<class 'bs4.element.Tag'>

แท็กมีแอตทริบิวต์และวิธีการจำนวนมากและคุณลักษณะที่สำคัญสองประการของแท็กคือชื่อและแอตทริบิวต์

ชื่อ (tag.name)

ทุกแท็กมีชื่อและสามารถเข้าถึงได้ผ่าน ".name" เป็นคำต่อท้าย tag.name จะส่งคืนประเภทของแท็กที่เป็น

>>> tag.name
'html'

อย่างไรก็ตามหากเราเปลี่ยนชื่อแท็กสิ่งเดียวกันนี้จะแสดงในมาร์กอัป HTML ที่สร้างโดย BeautifulSoup

>>> tag.name = "Strong"
>>> tag
<Strong><body><b class="boldest">TutorialsPoint</b></body></Strong>
>>> tag.name
'Strong'

แอตทริบิวต์ (tag.attrs)

ออบเจ็กต์แท็กสามารถมีแอตทริบิวต์จำนวนเท่าใดก็ได้ แท็ก <b class = "boldest"> มีแอตทริบิวต์ "class" ซึ่งมีค่าเป็น "boldest" สิ่งที่ไม่ใช่แท็กโดยพื้นฐานแล้วจะเป็นแอตทริบิวต์และต้องมีค่า คุณสามารถเข้าถึงแอตทริบิวต์ได้โดยการเข้าถึงคีย์ (เช่นการเข้าถึง "class" ในตัวอย่างด้านบน) หรือเข้าถึงโดยตรงผ่าน ".attrs"

>>> tutorialsP = BeautifulSoup("<div class='tutorialsP'></div>",'lxml')
>>> tag2 = tutorialsP.div
>>> tag2['class']
['tutorialsP']

เราสามารถแก้ไขแอตทริบิวต์ของแท็กได้ทุกประเภท (เพิ่ม / ลบ / แก้ไข)

>>> 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'

แอตทริบิวต์หลายมูลค่า

แอตทริบิวต์ HTML5 บางรายการสามารถมีได้หลายค่า ที่ใช้กันมากที่สุดคือ class-attribute ซึ่งสามารถมี CSS-values ​​ได้หลายค่า อื่น ๆ ได้แก่ "rel", "rev", "headers", "accesskey" และ "accept-charset" คุณลักษณะหลายมูลค่าในซุปที่สวยงามแสดงอยู่ในรายการ

>>> 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']

อย่างไรก็ตามหากแอตทริบิวต์ใด ๆ มีมากกว่าหนึ่งค่า แต่ไม่ใช่แอตทริบิวต์ที่มีหลายค่าตามมาตรฐาน HTML เวอร์ชันใดก็ตามซุปที่สวยงามจะปล่อยให้แอตทริบิวต์เพียงอย่างเดียว -

>>> id_soup = BeautifulSoup('<p id="body bold"></p>')
>>> id_soup.p['id']
'body bold'
>>> type(id_soup.p['id'])
<class 'str'>

คุณสามารถรวมค่าแอตทริบิวต์หลายค่าได้หากคุณเปลี่ยนแท็กเป็นสตริง

>>> 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' คุณจะได้รับค่าที่เป็นรายการสตริงเสมอไม่ว่าจะเป็นค่าหลายค่าหรือไม่ก็ตาม

id_soup.p.get_attribute_list(‘id’)

อย่างไรก็ตามหากคุณแยกวิเคราะห์เอกสารเป็น 'xml' จะไม่มีแอตทริบิวต์ที่มีหลายค่า -

>>> xml_soup = BeautifulSoup('<p class="body bold"></p>', 'xml')
>>> xml_soup.p['class']
'body bold'

NavigableString

วัตถุ navigablestring ใช้เพื่อแสดงเนื้อหาของแท็ก ในการเข้าถึงเนื้อหาให้ใช้“ .string” พร้อมแท็ก

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>>
>>> soup.string
'Hello, Tutorialspoint!'
>>> type(soup.string)
>

คุณสามารถแทนที่สตริงด้วยสตริงอื่น แต่คุณไม่สามารถแก้ไขสตริงที่มีอยู่ได้

>>> 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>

ซุปที่สวยงาม

BeautifulSoup เป็นวัตถุที่สร้างขึ้นเมื่อเราพยายามขูดทรัพยากรบนเว็บ ดังนั้นมันจึงเป็นเอกสารฉบับสมบูรณ์ที่เราพยายามขูด โดยส่วนใหญ่จะถือว่าเป็นวัตถุแท็ก

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>> type(soup)
<class 'bs4.BeautifulSoup'>
>>> soup.name
'[document]'

ความคิดเห็น

ออบเจ็กต์ข้อคิดเห็นแสดงส่วนความคิดเห็นของเอกสารเว็บ มันเป็นเพียง NavigableString ชนิดพิเศษ

>>> 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 วัตถุ

ออบเจ็กต์ navigablestring ใช้เพื่อแสดงข้อความภายในแท็กแทนที่จะใช้แท็กเอง

ในบทนี้เราจะพูดถึงการนำทางโดยแท็ก

ด้านล่างนี้คือเอกสาร html ของเรา -

>>> 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')
>>>

จากเอกสารข้างต้นเราจะพยายามย้ายจากส่วนหนึ่งของเอกสารไปยังอีกส่วนหนึ่ง

กำลังลงไป

องค์ประกอบที่สำคัญอย่างหนึ่งในเอกสาร HTML คือแท็กซึ่งอาจมีแท็ก / สตริงอื่น ๆ (แท็กย่อย) Beautiful Soup นำเสนอวิธีต่างๆในการนำทางและวนซ้ำเด็ก ๆ ของแท็ก

การนำทางโดยใช้ชื่อแท็ก

วิธีที่ง่ายที่สุดในการค้นหาโครงสร้างการแยกวิเคราะห์คือการค้นหาแท็กด้วยชื่อ หากคุณต้องการแท็ก <head> ให้ใช้ soup.head -

>>> soup.head
<head>&t;title>Tutorials Point</title></head>
>>> soup.title
<title>Tutorials Point</title>

เพื่อรับแท็กเฉพาะ (เช่นแท็ก <b> แรก) ในแท็ก <body>

>>> soup.body.b
<b>The Biggest Online Tutorials Library, It's all Free</b>

การใช้ชื่อแท็กเป็นแอตทริบิวต์จะทำให้คุณมีแท็กแรกตามชื่อนั้นเท่านั้น -

>>> soup.a
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>

ในการรับแอตทริบิวต์ของแท็กทั้งหมดคุณสามารถใช้ find_all () วิธีการ -

>>> 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 และ. children

เราสามารถค้นหาลูกของแท็กในรายการตาม. เนื้อหา -

>>> 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 เองก็มีลูก ในกรณีนี้แท็ก <html> คือลูกของออบเจ็กต์ BeautifulSoup -

>>> len(soup.contents)
2
>>> soup.contents[1].name
'html'

สตริงไม่มี. เนื้อหาเนื่องจากไม่มีอะไรเลย -

>>> text = Ttag.contents[0]
>>> text.contents
self.__class__.__name__, attr))
AttributeError: 'NavigableString' object has no attribute 'contents'

แทนที่จะรับเป็นรายการให้ใช้. children generator เพื่อเข้าถึงแท็กลูก ๆ -

>>> for child in Ttag.children:
print(child)
Tutorials Point

. ผู้มีอำนาจ

แอตทริบิวต์. descendants ช่วยให้คุณทำซ้ำบนแท็กย่อย ๆ ทั้งหมดแบบวนซ้ำ -

ลูกโดยตรงและลูกของลูกโดยตรงและอื่น ๆ -

>>> for child in Htag.descendants:
print(child)
<title>Tutorials Point</title>
Tutorials Point

แท็ก <head> มีลูกเดียว แต่มีลูกหลานสองตัวคือแท็ก <title> และแท็กลูก <title> วัตถุ beautifulsoup มีลูกโดยตรงเพียงคนเดียว (แท็ก <html>) แต่มีลูกหลานจำนวนมาก -

>>> len(list(soup.children))
2
>>> len(list(soup.descendants))
33

.string

หากแท็กมีชายด์เพียงคนเดียวและชายด์นั้นคือ NavigableString ลูกนั้นจะพร้อมใช้งานเป็น. สตริง -

>>> Ttag.string
'Tutorials Point'

หากแท็กลูกเดียวของแท็กเป็นแท็กอื่นและแท็กนั้นมี. สตริงแท็กหลักจะถือว่ามี. สตริงเหมือนกับแท็กระดับล่าง -

>>> Htag.contents
[<title>Tutorials Point</title>]
>>>
>>> Htag.string
'Tutorials Point'

อย่างไรก็ตามหากแท็กมีมากกว่าหนึ่งสิ่งก็ไม่ชัดเจนว่า. สตริงควรหมายถึงอะไรดังนั้น. สตริงจึงถูกกำหนดให้เป็นไม่มี -

>>> print(soup.html.string)
None

.strings และ stripped_strings

หากมีมากกว่าหนึ่งสิ่งในแท็กคุณยังดูแค่สตริงได้ ใช้ตัวสร้าง. string -

>>> 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'

ในการลบช่องว่างเพิ่มเติมให้ใช้ตัวสร้าง. stripped_strings -

>>> 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'

กำลังขึ้นไป

ในการเปรียบเทียบแบบ "แผนผังครอบครัว" ทุกแท็กและทุกสตริงจะมีพาเรนต์: แท็กที่มี:

.parent

ในการเข้าถึงองค์ประกอบหลักขององค์ประกอบให้ใช้แอตทริบิวต์ .parent

>>> Ttag = soup.title
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.parent
<head>title>Tutorials Point</title></head>

ใน html_doc ของเราสตริงหัวเรื่องเองก็มีพาเรนต์: แท็ก <title> ที่มีมัน −

>>> Ttag.string.parent
<title>Tutorials Point</title>

ระดับบนสุดของแท็กระดับบนสุดเช่น <html> คือออบเจ็กต์ Beautifulsoup เอง -

>>> htmltag = soup.html
>>> type(htmltag.parent)
<class 'bs4.BeautifulSoup'>

.parent ของวัตถุ Beautifulsoup ถูกกำหนดให้เป็นไม่มี -

>>> print(soup.parent)
None

.parents

หากต้องการวนซ้ำองค์ประกอบหลักทั้งหมดให้ใช้แอตทริบิวต์ .parents

>>> 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]

ไปด้านข้าง

ด้านล่างนี้เป็นเอกสารง่ายๆ -

>>> 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>

ในเอกสารด้านบนแท็ก <b> และ <c> อยู่ในระดับเดียวกันและทั้งสองเป็นแท็กลูกของแท็กเดียวกัน ทั้ง <b> และ <c> แท็กเป็นพี่น้องกัน

.next_sibling และ .previous_sibling

ใช้. next_sibling และ. Previous_sibling เพื่อนำทางระหว่างองค์ประกอบของเพจที่อยู่ในระดับเดียวกันของโครงสร้างการแยกวิเคราะห์:

>>> 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> มี. next_sibling แต่ไม่มี. before_sibling เนื่องจากไม่มีอะไรอยู่ข้างหน้า <b> แท็กที่อยู่ในระดับเดียวกันของต้นไม้กรณีเดียวกันจึงมีแท็ก <c>

>>> print(sibling_soup.b.previous_sibling)
None
>>> print(sibling_soup.c.next_sibling)
None

สายอักขระทั้งสองไม่ใช่พี่น้องเนื่องจากไม่มีผู้ปกครองคนเดียวกัน

>>> sibling_soup.b.string
'TutorialsPoint'
>>>
>>> print(sibling_soup.b.string.next_sibling)
None

.next_siblings และ. Previous_siblings

ในการวนซ้ำพี่น้องของแท็กให้ใช้. next_siblings และ. previous_siblings

>>> 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'

ไปๆมาๆ

ตอนนี้ให้เรากลับไปที่สองบรรทัดแรกในตัวอย่าง "html_doc" ก่อนหน้าของเรา -

&t;html><head><title>Tutorials Point</title></head>
<body>
<h4 class="tagLine"><b>The Biggest Online Tutorials Library, It's all Free</b></h4>

โปรแกรมแยกวิเคราะห์ HTML รับสตริงอักขระเหนือสตริงและเปลี่ยนเป็นชุดของเหตุการณ์เช่น "เปิดแท็ก <html>" "เปิดแท็ก <head>" "เปิดแท็ก <title>" "เพิ่มสตริง" “ ปิดแท็ก </title>”“ ปิดแท็ก </head>”“ เปิดแท็ก <h4>” และอื่น ๆ BeautifulSoup นำเสนอวิธีการต่างๆในการสร้างการแยกวิเคราะห์เบื้องต้นของเอกสาร

.next_element และ. Previous_element

แอตทริบิวต์. next_element ของแท็กหรือสตริงชี้ไปที่สิ่งที่ถูกแยกวิเคราะห์ทันทีหลังจากนั้น บางครั้งอาจมีลักษณะคล้ายกับ. next_sibling แต่ก็ไม่เหมือนกันทั้งหมด ด้านล่างนี้คือแท็ก <a> สุดท้ายในเอกสารตัวอย่าง“ html_doc” ของเรา

>>> 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.'

อย่างไรก็ตาม. next_element ของแท็ก <a> นั้นสิ่งที่แยกวิเคราะห์ทันทีหลังแท็ก <a> ไม่ใช่ส่วนที่เหลือของประโยคนั้นคือคำว่า“ C”:

>>> last_a_tag.next_element
'C'

พฤติกรรมข้างต้นเป็นเพราะในมาร์กอัปดั้งเดิมตัวอักษร“ C” ปรากฏก่อนอัฒภาคนั้น โปรแกรมแยกวิเคราะห์พบแท็ก <a> ตามด้วยตัวอักษร“ C” ตามด้วยแท็กปิด </a> ตามด้วยอัฒภาคและส่วนที่เหลือของประโยค อัฒภาคอยู่ในระดับเดียวกับแท็ก <a> แต่พบตัวอักษร“ C” ก่อน

แอตทริบิวต์. Previous_element ตรงข้ามกับ. next_element ชี้ไปที่องค์ประกอบใด ๆ ที่ถูกแยกวิเคราะห์ทันทีก่อนหน้านี้

>>> 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 และ. Previous_elements

เราใช้ตัวทำซ้ำเหล่านี้เพื่อเลื่อนไปข้างหน้าและข้างหลังไปยังองค์ประกอบ

>>> 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'

มีวิธีการ Beautifulsoup มากมายซึ่งช่วยให้เราสามารถค้นหาต้นไม้แยกวิเคราะห์ได้ สองวิธีที่ใช้บ่อยที่สุดคือ find () และ find_all ()

ก่อนที่จะพูดถึง find () และ find_all () ให้เราดูตัวอย่างของตัวกรองต่างๆที่คุณสามารถส่งผ่านไปยังวิธีการเหล่านี้

ชนิดของตัวกรอง

เรามีตัวกรองที่แตกต่างกันซึ่งเราสามารถส่งผ่านไปยังวิธีการเหล่านี้และการทำความเข้าใจตัวกรองเหล่านี้มีความสำคัญเนื่องจากตัวกรองเหล่านี้ใช้ซ้ำแล้วซ้ำอีกตลอดทั้ง API การค้นหา เราสามารถใช้ตัวกรองเหล่านี้ตามชื่อแท็กแอตทริบิวต์ข้อความสตริงหรือผสมกัน

สตริง

ตัวกรองประเภทหนึ่งที่ง่ายที่สุดคือสตริง ส่งสตริงไปยังวิธีการค้นหาและ Beautifulsoup จะทำการจับคู่กับสตริงนั้น ๆ

ด้านล่างโค้ดจะพบแท็ก <p> ทั้งหมดในเอกสาร -

>>> 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>]

นิพจน์ทั่วไป

คุณสามารถค้นหาแท็กทั้งหมดที่เริ่มต้นด้วยสตริง / แท็กที่กำหนด ก่อนหน้านั้นเราต้องนำเข้าโมดูล re เพื่อใช้นิพจน์ทั่วไป

>>> 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>]

รายการ

คุณสามารถส่งหลายแท็กเพื่อค้นหาโดยระบุรายการ โค้ดด้านล่างค้นหาแท็ก <b> และ <pre> ทั้งหมด -

>>> markup.find_all(['pre', 'b'])
[<pre>Programming Languages are:</pre>, <b>Java, Python, Cplusplus</b>]

จริง

True จะส่งคืนแท็กทั้งหมดที่สามารถค้นหาได้ แต่ไม่มีสตริงในตัวเอง -

>>> 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>]

หากต้องการส่งคืนเฉพาะแท็กจากซุปข้างต้น -

>>> for tag in markup.find_all(True):
(tag.name)
'html'
'body'
'p'
'p'
'pre'
'p'
'b'

find_all ()

คุณสามารถใช้ find_all เพื่อดึงข้อมูลที่เกิดขึ้นทั้งหมดของแท็กเฉพาะออกจากการตอบสนองของเพจเป็น -

ไวยากรณ์

find_all(name, attrs, recursive, string, limit, **kwargs)

ให้เราดึงข้อมูลที่น่าสนใจจาก IMDB -“ ภาพยนตร์ยอดนิยม” ตลอดกาล

>>> 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

จากด้านบนเราจะเห็น find_all จะให้รายการทั้งหมดที่ตรงกับเกณฑ์การค้นหาที่เรากำหนด ตัวกรองทั้งหมดที่เราสามารถใช้กับ find_all () สามารถใช้ได้กับ find () และวิธีการค้นหาอื่น ๆ เช่น find_parents () หรือ find_siblings ()

หา()

เราได้เห็นด้านบนแล้ว find_all () ใช้เพื่อสแกนเอกสารทั้งหมดเพื่อค้นหาเนื้อหาทั้งหมด แต่มีบางอย่างข้อกำหนดคือการค้นหาผลลัพธ์เพียงรายการเดียว หากคุณทราบว่าเอกสารมีแท็ก <body> เพียงแท็กเดียวคุณจะเสียเวลาในการค้นหาทั้งเอกสาร วิธีหนึ่งคือเรียก find_all () ด้วยขีด จำกัด = 1 ทุกครั้งหรือมิฉะนั้นเราสามารถใช้วิธี find () เพื่อทำเช่นเดียวกัน -

ไวยากรณ์

find(name, attrs, recursive, string, **kwargs)

ดังนั้นด้านล่างสองวิธีที่แตกต่างกันจะให้ผลลัพธ์เดียวกัน -

>>> soup.find_all('title',limit=1)
[<title>IMDb Top 250 - IMDb</title>]
>>>
>>> soup.find('title')
<title>IMDb Top 250 - IMDb</title>

ในผลลัพธ์ข้างต้นเราจะเห็นวิธี find_all () ส่งคืนรายการที่มีรายการเดียวในขณะที่วิธี find () จะส่งคืนผลลัพธ์เดียว

ความแตกต่างอีกอย่างระหว่างวิธี find () และ find_all () คือ -

>>> soup.find_all('h2')
[]
>>>
>>> soup.find('h2')

หากเมธอด soup.find_all () ไม่พบอะไรเลยมันจะส่งกลับรายการว่างในขณะที่ find () จะส่งกลับ None

find_parents () และ find_parent ()

ต่างจากเมธอด find_all () และ find () ที่ข้ามต้นไม้โดยดูที่การสืบเชื้อสายของแท็ก find_parents () และวิธี find_parents () ทำตรงกันข้ามพวกเขาข้ามต้นไม้ขึ้นไปและมองไปที่พ่อแม่ของแท็ก (หรือสตริง)

ไวยากรณ์

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>]

มีอีกแปดวิธีที่คล้ายกัน -

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)

ที่ไหน

find_next_siblings() และ find_next_sibling() วิธีการจะวนซ้ำกับพี่น้องทั้งหมดขององค์ประกอบที่มาหลังจากองค์ประกอบปัจจุบัน

find_previous_siblings() และ find_previous_sibling() วิธีการจะวนซ้ำพี่น้องทั้งหมดที่มาก่อนองค์ประกอบปัจจุบัน

find_all_next() และ find_next() วิธีการจะวนซ้ำแท็กและสตริงทั้งหมดที่มาหลังจากองค์ประกอบปัจจุบัน

find_all_previous และ find_previous() วิธีการจะวนซ้ำแท็กและสตริงทั้งหมดที่มาก่อนองค์ประกอบปัจจุบัน

ตัวเลือก CSS

ไลบรารี BeautifulSoup เพื่อรองรับตัวเลือก CSS ที่ใช้บ่อยที่สุด คุณสามารถค้นหาองค์ประกอบโดยใช้ตัวเลือก CSS ด้วยความช่วยเหลือของเมธอด select ()

นี่คือตัวอย่างบางส่วน -

>>> 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 คือการค้นหาโครงสร้างการแยกวิเคราะห์และช่วยให้คุณสามารถเปลี่ยนแปลงเอกสารเว็บได้ตามความต้องการของคุณ เราสามารถทำการเปลี่ยนแปลงคุณสมบัติของแท็กโดยใช้แอตทริบิวต์เช่น. name, .string หรือ. append () วิธีการ ช่วยให้คุณสามารถเพิ่มแท็กและสตริงใหม่ให้กับแท็กที่มีอยู่โดยใช้วิธีการ. new_string () และ. new_tag () ยังมีวิธีการอื่น ๆ เช่น. insert (), .insert_before () หรือ. insert_after () เพื่อทำการแก้ไขต่างๆในเอกสาร HTML หรือ XML ของคุณ

การเปลี่ยนชื่อแท็กและแอตทริบิวต์

เมื่อคุณสร้างซุปแล้วคุณสามารถแก้ไขได้ง่ายเช่นเปลี่ยนชื่อแท็กแก้ไขแอตทริบิวต์เพิ่มแอตทริบิวต์ใหม่และลบแอตทริบิวต์

>>> soup = BeautifulSoup('<b class="bolder">Very Bold</b>')
>>> tag = soup.b

การปรับเปลี่ยนและเพิ่มคุณสมบัติใหม่มีดังนี้ -

>>> tag.name = 'Blockquote'
>>> tag['class'] = 'Bolder'
>>> tag['id'] = 1.1
>>> tag
<Blockquote class="Bolder" id="1.1">Very Bold</Blockquote>

การลบแอตทริบิวต์มีดังนี้ -

>>> del tag['class']
>>> tag
<Blockquote id="1.1">Very Bold</Blockquote>
>>> del tag['id']
>>> tag
<Blockquote>Very Bold</Blockquote>

การแก้ไข. string

คุณสามารถแก้ไขแอตทริบิวต์. string ของแท็กได้อย่างง่ายดาย -

>>> 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>

จากด้านบนเราสามารถดูว่าแท็กมีแท็กอื่นหรือไม่แท็กและเนื้อหาทั้งหมดจะถูกแทนที่ด้วยข้อมูลใหม่

ผนวก()

การเพิ่มข้อมูล / เนื้อหาใหม่ให้กับแท็กที่มีอยู่ทำได้โดยใช้เมธอด tag.append () มันคล้ายกับ append () method ในรายการ Python มาก

>>> 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 () และ. new_tag ()

ในกรณีที่คุณต้องการเพิ่มสตริงลงในเอกสารสามารถทำได้อย่างง่ายดายโดยใช้ตัวสร้าง append () หรือโดย NavigableString () -

>>> 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 () ดังต่อไปนี้

NameError: ไม่ได้กำหนดชื่อ 'NavigableString'

เพียงนำเข้าไดเร็กทอรี NavigableString จากแพ็คเกจ bs4 -

>>> from bs4 import NavigableString

เราสามารถแก้ไขข้อผิดพลาดข้างต้นได้

คุณสามารถเพิ่มความคิดเห็นลงในแท็กที่มีอยู่ของคุณหรือสามารถเพิ่มคลาสย่อยอื่น ๆ ของ NavigableString ได้เพียงแค่เรียกตัวสร้าง

>>> 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!']

การเพิ่มแท็กใหม่ทั้งหมด (ไม่ต่อท้ายแท็กที่มีอยู่) สามารถทำได้โดยใช้เมธอด Beautifulsoup inbuilt, BeautifulSoup.new_tag () -

>>> 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>

ต้องระบุเฉพาะอาร์กิวเมนต์แรกชื่อแท็ก

แทรก()

คล้ายกับ. insert () วิธีการในรายการ python tag.insert () จะแทรกองค์ประกอบใหม่อย่างไรก็ตามไม่เหมือนกับ tag.append () องค์ประกอบใหม่ไม่จำเป็นต้องไปที่ส่วนท้ายของเนื้อหาของพาเรนต์ สามารถเพิ่มองค์ประกอบใหม่ได้ทุกตำแหน่ง

>>> 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 () และ insert_after ()

ในการแทรกแท็กหรือสตริงก่อนบางสิ่งในโครงสร้างการแยกวิเคราะห์เราใช้ insert_before () -

>>> 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>

ในทำนองเดียวกันหากต้องการแทรกแท็กหรือสตริงหลังบางสิ่งในโครงสร้างแยกวิเคราะห์ให้ใช้ insert_after ()

>>> 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']

ชัดเจน()

ในการลบเนื้อหาของแท็กให้ใช้ tag.clear () -

>>> 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>

สารสกัด ()

หากต้องการลบแท็กหรือสตริงออกจากโครงสร้างให้ใช้ PageElement.extract ()

>>> 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

ย่อยสลาย ()

tag.decompose () ลบแท็กออกจากทรีและลบเนื้อหาทั้งหมด

>>> 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>
>>>

แทนที่ด้วย ()

ตามชื่อที่แนะนำฟังก์ชัน pageElement.replace_with () จะแทนที่แท็กหรือสตริงเก่าด้วยแท็กหรือสตริงใหม่ในแผนภูมิ -

>>> 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>

ในผลลัพธ์ด้านบนคุณสังเกตเห็นว่า replace_with () ส่งคืนแท็กหรือสตริงที่ถูกแทนที่ (เช่น "วัสดุ" ในกรณีของเรา) ดังนั้นคุณสามารถตรวจสอบหรือเพิ่มกลับไปที่ส่วนอื่นของต้นไม้ได้

ห่อ ()

pageElement.wrap () ล้อมรอบองค์ประกอบในแท็กที่คุณระบุและส่งคืน Wrapper ใหม่ -

>>> 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>

แกะ()

tag.unwrap () อยู่ตรงข้ามกับ wrap () และแทนที่แท็กด้วยอะไรก็ตามที่อยู่ในแท็กนั้น

>>> 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>

จากด้านบนคุณสังเกตเห็นว่าเช่น replace_with () การแกะ () จะส่งกลับแท็กที่ถูกแทนที่

ด้านล่างนี้เป็นอีกหนึ่งตัวอย่างของการแกะ () เพื่อให้เข้าใจได้ดีขึ้น -

>>> 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>

แกะ () เหมาะสำหรับการลอกมาร์กอัปออก

เอกสาร HTML หรือ XML ทั้งหมดเขียนด้วยการเข้ารหัสเฉพาะบางอย่างเช่น ASCII หรือ UTF-8 อย่างไรก็ตามเมื่อคุณโหลดเอกสาร HTML / XML นั้นลงใน BeautifulSoup เอกสารนั้นจะถูกแปลงเป็น Unicode

>>> markup = "<p>I will display £</p>"
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.p
<p>I will display £</p>
>>> Bsoup.p.string
'I will display £'

พฤติกรรมข้างต้นเป็นเพราะ BeautifulSoup ใช้ภายในไลบรารีย่อยที่เรียกว่า Unicode, Dammit เพื่อตรวจจับการเข้ารหัสของเอกสารจากนั้นแปลงเป็น Unicode

อย่างไรก็ตามไม่ใช่ตลอดเวลาที่ Unicode, Dammit เดาถูกต้อง เนื่องจากเอกสารถูกค้นหาแบบไบต์ต่อไบต์เพื่อคาดเดาการเข้ารหัสจึงต้องใช้เวลามาก คุณสามารถประหยัดเวลาและหลีกเลี่ยงข้อผิดพลาดได้หากคุณรู้จักการเข้ารหัสแล้วโดยส่งต่อไปยังตัวสร้าง BeautifulSoup เป็น from_encoding

ด้านล่างนี้เป็นตัวอย่างหนึ่งที่ BeautifulSoup ระบุผิดเอกสาร ISO-8859-8 เป็น ISO-8859-7 -

>>> markup = b"<h1>\xed\xe5\xec\xf9</h1>"
>>> soup = BeautifulSoup(markup)
>>> soup.h1
<h1>νεμω</h1>
>>> soup.original_encoding
'ISO-8859-7'
>>>

ในการแก้ไขปัญหาข้างต้นให้ส่งต่อไปยัง BeautifulSoup โดยใช้ from_encoding -

>>> soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
>>> soup.h1
<h1>ולש </h1>
>>> soup.original_encoding
'iso-8859-8'
>>>

อีกคุณสมบัติใหม่ที่เพิ่มเข้ามาจาก BeautifulSoup 4.4.0 คือ exclude_encoding สามารถใช้ได้เมื่อคุณไม่ทราบการเข้ารหัสที่ถูกต้อง แต่แน่ใจว่า Unicode, Dammit แสดงผลลัพธ์ที่ไม่ถูกต้อง

>>> soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])

การเข้ารหัสเอาต์พุต

ผลลัพธ์จาก BeautifulSoup คือเอกสาร UTF-8 โดยไม่คำนึงถึงเอกสารที่ป้อนไปยัง BeautifulSoup ด้านล่างเอกสารที่มีอักขระภาษาโปลิชอยู่ในรูปแบบ ISO-8859-2

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>

ในตัวอย่างข้างต้นหากคุณสังเกตเห็นแท็ก <meta> ได้รับการเขียนใหม่เพื่อแสดงเอกสารที่สร้างจาก BeautifulSoup ตอนนี้อยู่ในรูปแบบ UTF-8

หากคุณไม่ต้องการผลลัพธ์ที่สร้างขึ้นใน UTF-8 คุณสามารถกำหนดการเข้ารหัสที่ต้องการใน prettify ()

>>> 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'

ในตัวอย่างข้างต้นเราได้เข้ารหัสเอกสารฉบับสมบูรณ์ แต่คุณสามารถเข้ารหัสองค์ประกอบใด ๆ ในซุปได้ราวกับว่ามันเป็นสตริงงูหลาม -

>>> soup.p.encode("latin-1")
b'<p>0My first paragraph.</p>'
>>> soup.h1.encode("latin-1")
b'<h1>My First Heading</h1>'

อักขระใด ๆ ที่ไม่สามารถแสดงในการเข้ารหัสที่คุณเลือกจะถูกแปลงเป็นการอ้างอิงเอนทิตี XML ที่เป็นตัวเลข ด้านล่างนี้เป็นตัวอย่างหนึ่ง -

>>> 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>'

หากคุณพยายามเข้ารหัสข้างต้นเป็น“ latin-1” หรือ“ ascii” มันจะสร้าง“ ☃” แสดงว่าไม่มีการแทนค่านั้น

>>> print (tag.encode("latin-1"))
b'<b>☃</b>'
>>> print (tag.encode("ascii"))
b'<b>☃</b>'

Unicode, Dammit

Unicode, Dammit ใช้เป็นหลักเมื่อเอกสารขาเข้าอยู่ในรูปแบบที่ไม่รู้จัก (ส่วนใหญ่เป็นภาษาต่างประเทศ) และเราต้องการเข้ารหัสในรูปแบบที่รู้จัก (Unicode) และเราไม่จำเป็นต้องให้ Beautifulsoup ทำทั้งหมดนี้

จุดเริ่มต้นของโครงการ BeautifulSoup คือวัตถุ BeautifulSoup ออบเจ็กต์ BeautifulSoup แสดงถึงเอกสาร HTML / XML อินพุตที่ใช้สำหรับการสร้าง

เราสามารถส่งสตริงหรืออ็อบเจกต์คล้ายไฟล์สำหรับ Beautiful Soup โดยที่ไฟล์ (อ็อบเจ็กต์) จะถูกเก็บไว้ในเครื่องของเราหรือในหน้าเว็บ

วัตถุ BeautifulSoup ที่พบบ่อยที่สุดคือ -

  • Tag
  • NavigableString
  • BeautifulSoup
  • Comment

การเปรียบเทียบวัตถุเพื่อความเท่าเทียมกัน

ตามซุปที่สวยงามสตริงหรือแท็กที่ใช้งานได้สองรายการจะเท่ากันหากเป็นตัวแทนของมาร์กอัป HTML / XML เดียวกัน

ตอนนี้ให้เราดูตัวอย่างด้านล่างซึ่งแท็ก <b> สองแท็กได้รับการปฏิบัติเท่ากันแม้ว่าแท็กจะอยู่ในส่วนต่างๆของโครงสร้างออบเจ็กต์เนื่องจากทั้งสองมีลักษณะเหมือน "<b> Java </b>"

>>> 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

อย่างไรก็ตามหากต้องการตรวจสอบว่าตัวแปรทั้งสองอ้างถึงวัตถุเดียวกันหรือไม่คุณสามารถใช้สิ่งต่อไปนี้

>>> print(first_b is second_b)
False

คัดลอกวัตถุซุปที่สวยงาม

ในการสร้างสำเนาของแท็กหรือ NavigableString ให้ใช้ฟังก์ชัน copy.copy () เช่นเดียวกับด้านล่าง -

>>> 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>
>>>

แม้ว่าสองสำเนา (ต้นฉบับและสำเนาหนึ่งชุด) จะมีมาร์กอัปเหมือนกันอย่างไรก็ตามทั้งสองไม่ได้แสดงถึงวัตถุเดียวกัน -

>>> print(soup.p == p_copy)
True
>>>
>>> print(soup.p is p_copy)
False
>>>

ข้อแตกต่างที่แท้จริงเพียงอย่างเดียวคือสำเนาถูกแยกออกจากโครงสร้างวัตถุ Beautiful Soup ดั้งเดิมโดยสิ้นเชิงเช่นเดียวกับที่มีการเรียกใช้ extract ()

>>> print(p_copy.parent)
None

พฤติกรรมข้างต้นเกิดจากออบเจ็กต์แท็กที่แตกต่างกันสองรายการซึ่งไม่สามารถใช้พื้นที่เดียวกันในเวลาเดียวกันได้

มีหลายสถานการณ์ที่คุณต้องการดึงข้อมูลบางประเภท (เฉพาะแท็ก <a>) โดยใช้ Beautifulsoup4 คลาส SoupStrainer ใน Beautifulsoup ช่วยให้คุณสามารถแยกวิเคราะห์เฉพาะบางส่วนของเอกสารขาเข้า

วิธีหนึ่งคือสร้าง SoupStrainer และส่งต่อไปยังตัวสร้าง Beautifulsoup4 เป็นอาร์กิวเมนต์ parse_only

SoupStrainer

SoupStrainer จะบอก BeautifulSoup ว่าส่วนใดแยกออกมาและต้นไม้แยกวิเคราะห์ประกอบด้วยองค์ประกอบเหล่านี้เท่านั้น หากคุณ จำกัด ข้อมูลที่ต้องการให้แคบลงเป็นส่วนหนึ่งของ HTML สิ่งนี้จะทำให้ผลการค้นหาของคุณเร็วขึ้น

product = SoupStrainer('div',{'id': 'products_list'})
soup = BeautifulSoup(html,parse_only=product)

บรรทัดด้านบนของโค้ดจะแยกวิเคราะห์เฉพาะชื่อเรื่องจากไซต์ผลิตภัณฑ์ซึ่งอาจอยู่ในฟิลด์แท็ก

ในทำนองเดียวกันเช่นข้างต้นเราสามารถใช้ออบเจ็กต์ SouStrainer อื่น ๆ เพื่อแยกวิเคราะห์ข้อมูลเฉพาะจากแท็ก HTML ด้านล่างนี้คือตัวอย่างบางส่วน -

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)

การจัดการข้อผิดพลาด

มีข้อผิดพลาดสองประเภทหลักที่ต้องจัดการใน BeautifulSoup ข้อผิดพลาดทั้งสองนี้ไม่ได้มาจากสคริปต์ของคุณ แต่มาจากโครงสร้างของข้อมูลโค้ดเนื่องจาก BeautifulSoup API ทำให้เกิดข้อผิดพลาด

ข้อผิดพลาดหลักสองประการมีดังนี้ -

AttributeError

เกิดขึ้นเมื่อสัญกรณ์จุดไม่พบแท็กพี่น้องกับแท็ก HTML ปัจจุบัน ตัวอย่างเช่นคุณอาจพบข้อผิดพลาดนี้เนื่องจากไม่มี "แท็กจุดยึด" คีย์ต้นทุนจะทำให้เกิดข้อผิดพลาดเมื่อข้ามผ่านและต้องใช้แท็กจุดยึด

KeyError

ข้อผิดพลาดนี้เกิดขึ้นหากไม่มีแอตทริบิวต์แท็ก HTML ที่ต้องการ ตัวอย่างเช่นหากเราไม่มีแอตทริบิวต์ data-pid ในข้อมูลโค้ดคีย์ pid จะทำให้คีย์ผิดพลาด

เพื่อหลีกเลี่ยงข้อผิดพลาดสองรายการข้างต้นเมื่อแยกวิเคราะห์ผลลัพธ์ผลลัพธ์นั้นจะถูกข้ามไปเพื่อให้แน่ใจว่าไม่ได้แทรกตัวอย่างข้อมูลที่ผิดรูปแบบลงในฐานข้อมูล -

except(AttributeError, KeyError) as er:
pass

วินิจฉัย()

เมื่อใดก็ตามที่เราพบปัญหาในการทำความเข้าใจว่า BeautifulSoup ทำอะไรกับเอกสารหรือ HTML ของเราเพียงแค่ส่งต่อไปยังฟังก์ชันการวินิจฉัย () ในการส่งไฟล์เอกสารไปยังฟังก์ชันการวินิจฉัย () เราสามารถแสดงได้ว่ารายการตัวแยกวิเคราะห์ต่างๆจัดการกับเอกสารอย่างไร

ด้านล่างนี้เป็นตัวอย่างหนึ่งที่แสดงให้เห็นถึงการใช้งานฟังก์ชันการวินิจฉัย () -

from bs4.diagnose import diagnose

with open("20 Books.html",encoding="utf8") as fp:
   data = fp.read()
   
diagnose(data)

เอาต์พุต

ข้อผิดพลาดในการแยกวิเคราะห์

ข้อผิดพลาดในการแยกวิเคราะห์มีสองประเภทหลัก ๆ คุณอาจได้รับข้อยกเว้นเช่น HTMLParseError เมื่อคุณฟีดเอกสารของคุณไปยัง BeautifulSoup คุณอาจได้รับผลลัพธ์ที่ไม่คาดคิดโดยที่แผนผังการแยกวิเคราะห์ BeautifulSoup ดูแตกต่างจากผลลัพธ์ที่คาดหวังจากเอกสารแยกวิเคราะห์มาก

ไม่มีข้อผิดพลาดในการแยกวิเคราะห์เนื่องจาก BeautifulSoup เป็นเพราะตัวแยกวิเคราะห์ภายนอกที่เราใช้ (html5lib, lxml) เนื่องจาก BeautifulSoup ไม่มีรหัสตัวแยกวิเคราะห์ใด ๆ วิธีหนึ่งในการแก้ไขข้อผิดพลาดในการแยกวิเคราะห์ข้างต้นคือการใช้โปรแกรมแยกวิเคราะห์อื่น

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

ตัวแยกวิเคราะห์ HTML ในตัวของ Python ทำให้เกิดข้อผิดพลาดในการแยกวิเคราะห์ที่พบบ่อยที่สุด 2 ข้อคือ HTMLParser.HTMLParserError: แท็กเริ่มต้นที่ผิดรูปแบบและ HTMLParser HTMLParserError: แท็กปิดท้ายที่ไม่ดีและเพื่อแก้ไขปัญหานี้คือการใช้ตัวแยกวิเคราะห์อื่นเป็นหลัก: lxml หรือ html5lib

ลักษณะการทำงานที่ไม่คาดคิดทั่วไปอีกประเภทหนึ่งคือคุณไม่พบแท็กที่คุณทราบว่าอยู่ในเอกสาร อย่างไรก็ตามเมื่อคุณรัน find_all () จะส่งกลับ [] หรือ find () จะส่งกลับ None

อาจเป็นเพราะบางครั้งตัวแยกวิเคราะห์ HTML ในตัว python ข้ามแท็กที่ไม่เข้าใจ

ข้อผิดพลาดตัวแยกวิเคราะห์ XML

ตามค่าเริ่มต้นแพ็คเกจ BeautifulSoup จะแยกวิเคราะห์เอกสารเป็น HTML อย่างไรก็ตามมันใช้งานง่ายมากและจัดการ XML ที่มีรูปแบบไม่ถูกต้องในลักษณะที่สวยงามมากโดยใช้ beautifulsoup4

ในการแยกวิเคราะห์เอกสารเป็น XML คุณต้องมีตัวแยกวิเคราะห์ lxml และคุณเพียงแค่ส่ง "xml" เป็นอาร์กิวเมนต์ที่สองไปยังตัวสร้าง Beautifulsoup -

soup = BeautifulSoup(markup, "lxml-xml")

หรือ

soup = BeautifulSoup(markup, "xml")

ข้อผิดพลาดในการแยกวิเคราะห์ XML ทั่วไปอย่างหนึ่งคือ -

AttributeError: 'NoneType' object has no attribute 'attrib'

สิ่งนี้อาจเกิดขึ้นในกรณีที่องค์ประกอบบางส่วนหายไปหรือไม่ได้กำหนดไว้ในขณะที่ใช้ฟังก์ชัน find () หรือ findall ()

ข้อผิดพลาดในการแยกวิเคราะห์อื่น ๆ

ด้านล่างนี้เป็นข้อผิดพลาดในการแยกวิเคราะห์อื่น ๆ ที่เราจะพูดถึงในส่วนนี้ -

ปัญหาสิ่งแวดล้อม

นอกเหนือจากข้อผิดพลาดในการแยกวิเคราะห์ที่กล่าวถึงข้างต้นแล้วคุณอาจพบปัญหาในการแยกวิเคราะห์อื่น ๆ เช่นปัญหาด้านสิ่งแวดล้อมที่สคริปต์ของคุณอาจทำงานในระบบปฏิบัติการหนึ่ง แต่ไม่ใช่ในระบบปฏิบัติการอื่นหรืออาจทำงานในสภาพแวดล้อมเสมือนหนึ่ง แต่ไม่สามารถทำงานได้ นอกสภาพแวดล้อมเสมือนจริง ปัญหาทั้งหมดนี้อาจเป็นเพราะสภาพแวดล้อมทั้งสองมีไลบรารีตัวแยกวิเคราะห์ที่แตกต่างกัน

ขอแนะนำให้ทราบหรือตรวจสอบตัวแยกวิเคราะห์เริ่มต้นของคุณในสภาพแวดล้อมการทำงานปัจจุบันของคุณ คุณสามารถตรวจสอบตัวแยกวิเคราะห์เริ่มต้นปัจจุบันที่พร้อมใช้งานสำหรับสภาพแวดล้อมการทำงานปัจจุบันหรือส่งผ่านไลบรารีตัวแยกวิเคราะห์ที่จำเป็นอย่างชัดเจนเป็นอาร์กิวเมนต์ที่สองไปยังตัวสร้าง BeautifulSoup

ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่

เนื่องจากแท็ก HTML และแอตทริบิวต์ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ตัวแยกวิเคราะห์ HTML ทั้งสามจึงแปลงแท็กและชื่อแอตทริบิวต์เป็นตัวพิมพ์เล็ก อย่างไรก็ตามหากคุณต้องการเก็บแท็กและแอตทริบิวต์แบบผสมหรือแบบตัวพิมพ์ใหญ่หรือตัวพิมพ์ใหญ่คุณควรแยกวิเคราะห์เอกสารเป็น XML

UnicodeEncodeError

ให้เราดูส่วนโค้ดด้านล่าง -

soup = BeautifulSoup(response, "html.parser")
   print (soup)

เอาต์พุต

UnicodeEncodeError: 'charmap' codec can't encode character '\u011f'

ปัญหาข้างต้นอาจเป็นเพราะสองสถานการณ์หลัก คุณอาจพยายามพิมพ์อักขระ Unicode ที่คอนโซลของคุณไม่ทราบวิธีแสดง ประการที่สองคุณกำลังพยายามเขียนลงไฟล์และคุณส่งผ่านอักขระ Unicode ที่ไม่รองรับการเข้ารหัสเริ่มต้นของคุณ

วิธีหนึ่งในการแก้ไขปัญหาข้างต้นคือการเข้ารหัสข้อความตอบกลับ / อักขระก่อนที่จะทำซุปเพื่อให้ได้ผลลัพธ์ตามที่ต้องการดังนี้ -

responseTxt = response.text.encode('UTF-8')

KeyError: [attr]

เกิดจากการเข้าถึงแท็ก ['attr'] เมื่อแท็กที่เป็นปัญหาไม่ได้กำหนดแอตทริบิวต์ attr ข้อผิดพลาดที่พบบ่อย ได้แก่ “ KeyError: 'href'” และ“ KeyError: 'class'” ใช้ tag.get ('attr') หากคุณไม่แน่ใจว่าได้กำหนด attr ไว้

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 ดังต่อไปนี้ -

AttributeError: 'list' object has no attribute 'find_all'

ข้อผิดพลาดข้างต้นส่วนใหญ่เกิดขึ้นเนื่องจากคุณคาดว่า find_all () ส่งคืนแท็กหรือสตริงเดียว อย่างไรก็ตาม soup.find_all ส่งคืนรายการองค์ประกอบหลาม

สิ่งที่คุณต้องทำคือทำซ้ำในรายการและรับข้อมูลจากองค์ประกอบเหล่านั้น