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