แยกส่วนของการจับคู่นิพจน์ทั่วไป


132

ฉันต้องการนิพจน์ทั่วไปเพื่อแยกหัวเรื่องจากหน้า HTML ขณะนี้ฉันมีสิ่งนี้:

title = re.search('<title>.*</title>', html, re.IGNORECASE).group()
if title:
    title = title.replace('<title>', '').replace('</title>', '') 

มีนิพจน์ทั่วไปในการแยกเฉพาะเนื้อหาของ <title> ดังนั้นฉันจึงไม่ต้องลบแท็กออกหรือไม่


5
ว้าวฉันไม่อยากจะเชื่อเลยว่าคำตอบทั้งหมดที่เรียกให้แยกวิเคราะห์หน้า HTML ทั้งหมดเพียงเพื่อแยกชื่อเรื่องง่ายๆ อะไรมากเกินไป!
hoju

4
ชื่อคำถามที่บอกว่ามันทั้งหมด - ตัวอย่างให้เกิดขึ้นจะเป็น HTML แต่ปัญหาทั่วไปคือ ... ทั่วไป
ฟิล

คำตอบ:


209

ใช้( )ใน regexp และgroup(1)ใน python เพื่อดึงสตริงที่จับได้ ( re.searchจะส่งคืนNoneหากไม่พบผลลัพธ์ดังนั้นอย่าใช้group()โดยตรง ):

title_search = re.search('<title>(.*)</title>', html, re.IGNORECASE)

if title_search:
    title = title_search.group(1)

1
หากคุณไม่ได้ทำอะไรเลยเมื่อไม่พบชื่อทำไมการใช้ group () โดยตรงจึงเป็นเรื่องไม่ดี (คุณสามารถจับข้อยกเว้นได้)
tonfa

1
ใช่ แต่คนส่วนใหญ่ลืมเกี่ยวกับข้อยกเว้นและประหลาดใจมากเมื่อเห็นพวกเขาในรันไทม์ :)
Krzysztof Krasoń

อย่าลืมวิ่งimport reไม่งั้นคุณจะได้รับNameError: name 're' is not defined
พลัง

16

โปรดทราบว่าการเริ่มต้นPython 3.8และการแนะนำนิพจน์การกำหนด (PEP 572) ( :=ตัวดำเนินการ) เป็นไปได้ที่จะปรับปรุงโซลูชันของ Krzysztof Krasońโดยการจับผลการจับคู่โดยตรงภายในเงื่อนไข if เป็นตัวแปรและนำกลับมาใช้ใหม่ในเนื้อหาของเงื่อนไข :

# pattern = '<title>(.*)</title>'
# text = '<title>hello</title>'
if match := re.search(pattern, text, re.IGNORECASE):
  title = match.group(1)
# hello



4

ฉันขอแนะนำให้คุณซุปสวย Soup เป็น lib ที่ดีมากในการแยกวิเคราะห์เอกสาร html ทั้งหมดของคุณ

soup = BeatifulSoup(html_doc)
titleName = soup.title.name

ฉันอยากจะเพิ่มว่า beautifulsoup นั้นยังแยกวิเคราะห์ html ที่ไม่สมบูรณ์และนั่นก็ดีจริงๆ
สิ้นสุด

3

ลอง:

title = re.search('<title>(.*)</title>', html, re.IGNORECASE).group(1)

หากคุณต้องการใช้ REGEX สำหรับการแยกวิเคราะห์ HTML อย่าเรียกใช้. group () โดยตรงในการจับคู่เนื่องจากอาจส่งคืน None
iElectric

คุณควรใช้.*?ในกรณีที่มี</title>เอกสารหลายชุด (ไม่น่าจะเป็นไปได้ แต่คุณไม่เคยรู้)
tonfa

@ iElectric: คุณสามารถลองใช้ยกเว้นบล็อกถ้าคุณต้องการจริงๆใช่ไหม?
tonfa

3

โค้ดที่ให้มาไม่สามารถใช้ได้กับExceptions May I Suggest

getattr(re.search(r"<title>(.*)</title>", s, re.IGNORECASE), 'groups', lambda:[u""])()[0]

สิ่งนี้จะส่งคืนสตริงว่างตามค่าเริ่มต้นหากไม่พบรูปแบบหรือการจับคู่ครั้งแรก


1

ฉันคิดว่ามันน่าจะพอเพียง:

#!python
import re
pattern = re.compile(r'<title>([^<]*)</title>', re.MULTILINE|re.IGNORECASE)
pattern.search(text)

... สมมติว่าข้อความ (HTML) ของคุณอยู่ในตัวแปรชื่อ "text"

นอกจากนี้ยังถือว่าไม่มีแท็ก HTML อื่น ๆ ที่สามารถฝังไว้ในแท็ก HTML TITLE ได้อย่างถูกกฎหมายและไม่มีทางที่จะฝังอักขระ <อื่น ๆ ภายในคอนเทนเนอร์ / บล็อกดังกล่าวได้อย่างถูกกฎหมาย

อย่างไรก็ตาม ...

อย่าใช้นิพจน์ทั่วไปสำหรับการแยกวิเคราะห์ HTML ใน Python ใช้โปรแกรมแยกวิเคราะห์ HTML! (เว้นแต่คุณจะเขียนตัวแยกวิเคราะห์แบบเต็มซึ่งจะเป็นงานพิเศษเมื่อตัวแยกวิเคราะห์ HTML, SGML และ XML ต่างๆอยู่ในไลบรารีมาตรฐานแล้ว

หากการจัดการแท็ก "โลกแห่งความจริง" ของคุณใช้ HTML (ซึ่งมักไม่เป็นไปตามโปรแกรมตรวจสอบ SGML / XML ใด ๆ ) ให้ใช้แพ็คเกจBeautifulSoup มันไม่ได้อยู่ในไลบรารีมาตรฐาน (ยัง) แต่แนะนำกว้าง ๆ สำหรับวัตถุประสงค์นี้

อีกทางเลือกหนึ่งคือ: lxml ... ซึ่งเขียนขึ้นสำหรับ HTML ที่มีโครงสร้างอย่างถูกต้อง (ตามมาตรฐาน) แต่มันก็มีตัวเลือกในการ fallback กับการใช้ BeautifulSoup เป็นตัวแยกวิเคราะห์ที่ใช้งาน: ElementSoup

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.