خراش دادن وب با BeautifulSoup (در پایتون)

امروز، در مورد نحوه انجام کار یاد خواهید گرفت خراش دادن وب با BeautifulSoup. شما یاد خواهید گرفت که چگونه از کتابخانه درخواست ها برای واکشی صفحات وب و از کتابخانه BeautifulSoup برای تجزیه HTML در پایتون استفاده کنید.

در این آموزش یاد خواهید گرفت:

  • اصول اولیه خراش دادن و تجزیه وب
  • نحوه نصب BeautifulSoup
  • چگونه یک فایل HTML محلی را تجزیه کنیم
  • از Requests و BeautifulSoup برای خراش دادن و تجزیه صفحات وب استفاده کنید
  • روش هایی که برای یافتن عناصر درون HTML نیاز دارید
  • فیلترهایی که می توانید برای بهبود تطابق در داخل HTML استفاده کنید

Web Scraping چیست؟

خراش دادن وب فرآیند استفاده از یک ربات برای استخراج داده ها از یک وب سایت و صادرات آن به یک قالب قابل هضم است. یک وب اسکراپر کد HTML را از یک صفحه وب استخراج می کند، که سپس برای استخراج اطلاعات ارزشمند تجزیه می شود.

سوپ زیبا چیست؟

سوپ زیبا یک کتابخانه تجزیه در پایتون است که برای خراش دادن اطلاعات از HTML یا XML استفاده می شود. تجزیه کننده BeautifulSoup اصطلاحات پایتون را برای جستجو و اصلاح درخت تجزیه فراهم می کند.

به زبان ساده، BeautifulSoup کتابخانه ای است که به شما امکان می دهد HTML را به روشی قابل استفاده قالب بندی کنید و عناصر را از آن استخراج کنید.

تجزیه در Web Scraping چیست؟

تجزیه در وب اسکرپینگ فرآیند تبدیل داده های بدون ساختار به یک قالب ساختاریافته (به عنوان مثال درخت تجزیه) است که خواندن، استفاده و استخراج داده ها از آن آسان تر است.

اساساً تجزیه به معنای تقسیم یک سند در تکه های قابل استفاده است.

شروع با BeautifulSoup

نحوه نصب BeautifulSoup

از pip برای نصب BeautifulSoup در پایتون استفاده کنید.

$ pip install beautifulsoup4

تجزیه ساده با سوپ زیبا

from bs4 import BeautifulSoup
soup = BeautifulSoup("<p>I am learning <span>BeautifulSoup</span></p>")
soup.find('span')
<span>BeautifulSoup</span>

بهترین روش های اسکراپینگ وب

  1. از وب سایت های اسباب بازی برای تمرین استفاده کنید
  2. از API ها به جای وب اسکرپینگ استفاده کنید
  3. ابتدا بررسی کنید که آیا داده ها در جای دیگری در دسترس هستند (مثلاً خزیدن مشترک)
  4. به robots.txt احترام بگذارید
  5. سرعت خراشیدن خود را کاهش دهید
  6. درخواست های خود را کش کنید

چگونه HTML را با BeautifulSoup تجزیه کنیم

مراحل زیر را برای تجزیه HTML در BeautifulSoup دنبال کنید:

  1. BeautifulSoup را نصب کنید

    برای نصب BeautifulSoup از pip استفاده کنید
    $ pip install beautifulsoup4

  2. کتابخانه BeautifulSoup را در پایتون وارد کنید

    برای وارد کردن BeautifulSoup در پایتون، کلاس BeautifulSoup را از کتابخانه bs4 وارد کنید.
    from bs4 import BeautifulSoup

  3. HTML را تجزیه کنید

    برای تجزیه HTML، شی BeautifulSoup را ایجاد کنید و HTML را به عنوان آرگومان مورد نیاز اضافه کنید. شی سوپ یک نسخه تجزیه شده از HTML خواهد بود.
    soup = BeautifulSoup("<p>your HTML</p>")

  4. از روش های شی BeautifulSoup برای استخراج اطلاعات از HTML استفاده کنید

    کتابخانه BeautifulSoup روش‌های داخلی زیادی برای استخراج داده‌ها از HTML دارد. برای استخراج عناصر خاص از HTML تجزیه شده از متدهایی مانند ()soup.find یا ()soup.find_all استفاده کنید.

تجزیه اولین HTML خود با BeautifulSoup

اولین یادگیری این آموزش BeautifulSoup، تجزیه این HTML ساده خواهد بود.

نمونه HTML برای تجزیه

html = '''  
<html> 
    <head>
        <title>Simple SEO Title</title>
        <meta name="description" content="Meta Description with less than 300 characters.">  
        <meta name="robots" content="noindex, nofollow">
        <link rel="alternate" href="https://www.example.com/en" hreflang="en-ca">
        <link rel="canonical" href="https://www.example.com/fr"> 
    </head>
    <body>
        <header>
        <div class="nav">
            <ul>
            <li class="home"><a href="#">Home</a></li>
            <li class="blog"><a class="active" href="#">Blog</a></li>
            <li class="about"><a href="#">About</a></li>
            <li class="contact"><a href="#">Contact</a></li>
            </ul>
        </div>
        </header>
        <div class="body">
            <h1>Blog</h1>
            <p>Lorem ipsum dolor <a href="#">Anchor Text Link</a> sit amet consectetur adipisicing elit. Ipsum vel laudantium a voluptas labore. Dolorum modi doloremque, dolore molestias quos nam a laboriosam neque asperiores fugit sed aut optio earum!</p>
            <h2>Subtitle</h2>
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum vel laudantium a voluptas labore. Dolorum modi doloremque, dolore molestias quos nam a <a href="#" rel="nofollow">Nofollow link</a> laboriosam neque asperiores fugit sed aut optio earum!</p>
        </div>
    </body>
  </html>'''

متغیر HTML که به تازگی ایجاد کردیم مشابه خروجی است که هنگام خراش دادن یک صفحه وب به دست می آوریم. این HTML است، اما به عنوان متن ذخیره می شود.

این خیلی مفید نیست زیرا جستجو در آن دشوار است.

می توانید از عبارات منظم برای تجزیه محتوای متن استفاده کنید، اما راه بهتری در دسترس است: تجزیه با BeautifulSoup.

تجزیه HTML

برای تجزیه HTML با BeautifulSoup، یک سازنده BeautifulSoup را با اضافه کردن HTML برای تجزیه به عنوان یک آرگومان مورد نیاز، و نام تجزیه کننده به عنوان یک آرگومان اختیاری، نمونه سازی کنید.

# Parsing an HTML File
from bs4 import BeautifulSoup
import requests

soup = BeautifulSoup(html, 'html.parser')

این HTML تجزیه شده را به یک شی BeautifulSoup برمی گرداند.

سپس هر عنصر HTML (تگ عنوان در این مورد) را از شی BeautifulSoup با soup.find() روش.

print(soup.find('title'))
<title>Simple SEO Title</title>

یک فایل HTML محلی را با BeautifulSoup تجزیه کنید

اگر یک فایل HTML در جایی در رایانه خود ذخیره کرده اید، می توانید یک فایل HTML محلی را با BeautifulSoup نیز تجزیه کنید.

# Parsing an HTML File
from bs4 import BeautifulSoup
import requests

with open('/path/to/file.html') as f:
    soup = BeautifulSoup(f, 'html.parser')

print(soup)

تجزیه یک صفحه وب با BeautifulSoup

برای تجزیه یک صفحه وب با BeautifulSoup، HTML صفحه را با استفاده از کتابخانه درخواست های Python واکشی کنید. شما می توانید به روش های مختلف به HTML صفحه دسترسی داشته باشید: درخواست های HTTP، برنامه های کاربردی مبتنی بر مرورگر، دانلود دستی از مرورگر وب.

تا کنون، نحوه تجزیه یک فایل HTML محلی را که واقعاً در حال خراش دادن وب نیست، دیده‌ایم.

اکنون یک صفحه وب را برای استخراج HTML آن و سپس تجزیه محتوا با BeautifulSoup واکشی می کنیم.

Scraping وب را در Crawler-test.com تمرین کنید

برای این آموزش، ما خراش دادن وب را با BeautifulSoup در یک وب سایت اسباب بازی که برای این منظور ایجاد شده است، تمرین می کنیم: crawler-test.com.

برای استخراج محتوا از یک صفحه وب، با استفاده از کتابخانه درخواست‌های پایتون، یک درخواست HTTP به یک URL ایجاد کنید.

# Making an HTTP Request
import requests

url = 'https://crawler-test.com/'
response = requests.get(url)

print('Status code: ', response.status_code)
print('Text: ', response.text[:50])

تجزیه پاسخ با BeautifulSoup

برای تجزیه پاسخ با BeautifulSoup، HTML بازیابی شده را به عنوان آرگومان سازنده BeautifulSoup اضافه کنید.

هنگام واکشی یک صفحه وب با درخواست ها، شی پاسخ برگردانده می شود. از آن پاسخ، می توانید HTML صفحه را بازیابی کنید. آن HTML در یونیکد یا بایت (متن) ذخیره می شود.

قبلاً دیده‌ایم که چگونه این نمایش متنی HTML را با BeautifulSoup تجزیه کنیم. برای انجام این کار، تنها چیزی که نیاز داریم این است که answer.text را به کلاس BeautifulSoup منتقل کنیم.

from bs4 import BeautifulSoup

# Parse the HTML
soup = BeautifulSoup(response.text, 'html.parser')

# Extract any HTML tag
soup.find('title')
<title>Crawler Test Site</title>

از BeautifulSoup’s استفاده کنید find() و find_all() روش هایی برای استخراج تگ های HTML از HTML تجزیه شده.

برخی از تگ های بسیار رایج HTML که می خواهید آنها را پاک کنید عبارتند از عنوان، h1 و پیوندها.

عناصر را بر اساس نام برچسب پیدا کنید

برای یافتن یک عنصر HTML با نام تگ آن در BeautifulSoup، نام تگ را به عنوان آرگومان به متد شی BeautifulSoup ارسال کنید.

در اینجا مثالی از نحوه استخراج این تگ ها با bs4 آورده شده است.

# Extracting HTML tags
title = soup.find('title')
h1 = soup.find('h1')
links = soup.find_all('a', href=True)

# Print the outputs
print('Title: ', title)
print('h1: ', h1)
print('Example link: ', links[1]['href'])
Title:  <title>Crawler Test Site</title>
h1:  <h1>Crawler Test Site</h1>
Example link:  /mobile/separate_desktop

عناصر را با شناسه پیدا کنید

برای یافتن یک عنصر HTML با شناسه آن در BeautifulSoup، نام شناسه را به آن ارسال کنید id پارامتر متد find() شی سوپ.

<div id="header">
<a href="/" id="logo">Crawler Test <span class="neon-effect">two point oh!</span></a>
<div style="position:absolute;right:520px;top:-4px;"></div>
</div>

عناصر را بر اساس نام کلاس HTML پیدا کنید

برای پیدا کردن یک عنصر HTML بر اساس کلاس آن در BeautifulSoup، یک دیکشنری را به عنوان آرگومان شی سوپ ارسال کنید. find_all() روش.

soup.find_all('div', {'class': 'panel-header'})[0]
<div class="panel-header">
<h3>Mobile</h3>
</div>

سپس می توانید شی را حلقه کنید تا هر کاری که می خواهید انجام دهید.

# Find Elements by Class
boxes = soup.find_all('div', {'class': 'panel'})

box_names = []
for box in boxes:
    title = box.find('h3')
    box_names.append(title.text)

box_names[:5]
['Mobile', 'Description Tags', 'Encoding', 'Titles', 'Robots Protocol']

برای استخراج متن از یک عنصر HTML با استفاده از BeautifulSoup، از .text ویژگی روی شی سوپ اگر شیء یک لیست است (مثلاً با استفاده از find_all) از یک حلقه for برای تکرار هر عنصر استفاده کنید و از ویژگی text در هر عنصر استفاده کنید.

logo = soup.find('a', {'id': 'logo'})
logo.text
'Crawler Test two point oh!'

برای استخراج برچسب های HTML با استفاده از ویژگی های آنها، یک فرهنگ لغت را به آن ارسال کنید attrs پارامتر در متد find()

ویژگی های مثال عبارتند از name ویژگی مورد استفاده در توضیحات متا یا the href ویژگی مورد استفاده در یک هایپرلینک

برخی از عناصر HTML از شما می خواهند که عناصر را با استفاده از ویژگی آنها دریافت کنید.

در زیر، ما توضیحات متا و ویژگی های نام متا روبات ها را تجزیه می کنیم.

# Parsing using HTML tag attributes
description = soup.find('meta', attrs={'name':'description'})
meta_robots =  soup.find('meta', attrs={'name':'robots'})
print('description: ',description)
print('meta robots: ',meta_robots)
description:  <meta content="Default description XIbwNE7SSUJciq0/Jyty" name="description"/>
meta robots:  None

در اینجا، عنصر متا روبات ها در دسترس نبود، و بنابراین بازگشت None.

بیایید ببینیم چگونه از برچسب های در دسترس مراقبت کنیم.

تجزیه برچسب های در دسترس

در زیر، توضیحات، ربات‌های متا و تگ‌های متعارف را از صفحه وب حذف می‌کنیم. اگر آنها در دسترس نباشند، یک رشته خالی را برمی گردانیم.

# Conditional parsing
canonical = soup.find('link', {'rel': 'canonical'})

# Extract if attribute ifound
description = description['content'] if description else ''
meta_robots =  meta_robots['content'] if meta_robots else ''
canonical = canonical['href'] if canonical else ''

# Print output
print('description: ', description)
print('meta_robots: ', meta_robots)
print('canonical: ', canonical)
description:  Default description XIbwNE7SSUJciq0/Jyty
meta_robots:  
canonical:  

برای استخراج تمام پیوندهای یک صفحه وب با BeautifulSoup، از soup.find_all() روش با "a" برچسب به عنوان آرگومان آن را تنظیم کنید href پارامتر به True.

soup.find_all('a', href=True)

استخراج پیوندها در یک صفحه وب مرتبط ترین چیزی است که باید در اسکراپینگ وب بدانید.

اکنون، ما یاد خواهیم گرفت که چگونه این کار را انجام دهیم.

علاوه بر این، ما یاد خواهیم گرفت که چگونه از روش urljoin از urllib برای غلبه بر یکی از رایج ترین چالش های ساخت یک خزنده وب استفاده کنیم: مراقبت از URL های نسبی و مطلق.

# Extract all links on the page
from urllib.parse import urlparse, urljoin

url = 'https://crawler-test.com/'

# Parse URL
parsed_url = urlparse(url)
domain = parsed_url.scheme + '://' + parsed_url.netloc
print('Domain root is: ', domain)

# Get href from all links
links = []
for link in soup.find_all('a', href=True):
    # join domain to path
    full_url = urljoin(domain, link['href']) 
    links.append(full_url)

# Print output
print('Top 5 links are :\n', links[:5])
Domain root is:  https://crawler-test.com
Top 5 links are :
 ['https://crawler-test.com/', 'https://crawler-test.com/mobile/separate_desktop', 'https://crawler-test.com/mobile/desktop_with_AMP_as_mobile', 'https://crawler-test.com/mobile/separate_desktop_with_different_h1', 'https://crawler-test.com/mobile/separate_desktop_with_different_title']

برای استخراج یک عنصر در قسمت خاصی از صفحه (مثلاً با استفاده از id آن)، نتیجه یک ()soup.find را به متغیر دیگری اختصاص دهید و از یکی از متدهای داخلی bs4 روی آن شی استفاده کنید.

# Get div that contains a specific ID
subset = soup.find('div', {'id': 'idname'})
# Find all p inside that div
subset.find_all('p')

مثال:

# Extract all links on the page
from urllib.parse import urljoin

domain = 'https://crawler-test.com/'
# Get div that contains a specific ID
menu = soup.find('div', {'id': 'header'})

# Find all links within the div
menu_links = menu.find_all('a', href=True)

# Print output
for link in menu_links[:5]:
    print(link['href'])
    print(urljoin(domain, link['href']) )
/
https://crawler-test.com/

برچسب های خاص HTML را با BeautifulSoup حذف کنید

برای حذف یک تگ HTML خاص از یک سند HTML با BeautifulSoup، از decompose() روش.

soup.tag_name.decompose()

مثال

# Prompt
wikipedia_text = '''
<p>In the United States, website owners can use three major <a href="/wiki/Cause_of_action" title="Cause of action">legal claims</a> to prevent undesired web scraping: (1) copyright infringement (compilation), (2) violation of the <a href="/wiki/Computer_Fraud_and_Abuse_Act" title="Computer Fraud and Abuse Act">Computer Fraud and Abuse Act</a> ("CFAA"), and (3) <a href="/wiki/Trespass_to_chattels" title="Trespass to chattels">trespass to chattel</a>.<sup id="cite_ref-6" class="reference"><a href="#cite_note-6">[6]</a></sup> However, the effectiveness of these claims relies upon meeting various criteria...</p>'''

# Parse HTML
wiki_soup = BeautifulSoup(wikipedia_text, 'html.parser')

# Get first paragraph
par = wiki_soup.find_all('p')[0]

# Get all links
par.find_all('a')
# Remove references tags from wikipedia
par.sup.decompose()
par.find_all('a')

عناصر را بر اساس محتوای متن پیدا کنید

برای یافتن عناصر در HTML با استفاده از محتوای متنی، متنی را که باید مطابق با مقدار آن باشد، اضافه کنید string پارامتر داخل find_all() روش.

# Getting Elements using Text
soup = BeautifulSoup(r.text, 'html.parser')
soup.find_all('a',string="Description Tag Too Long")
[<a href="/description_tags/description_over_max">Description Tag Too Long</a>]

مشکل این است که رشته باید دقیقا مطابقت داشته باشد. بنابراین، استفاده از یک رشته جزئی برای تطبیق با BeautifulSoup هیچ چیزی را باز نمی‌گرداند:

# Getting Elements using Partial String
soup.find_all('a',string="Description")

کار در مورد این مشکل تطبیق رشته استفاده از توابع کاربردی یا استفاده از عبارات منظم با عبارت است string پارامتر. در ادامه به این دو موقعیت خواهیم پرداخت.

یک تابع را به روش BeautifulSoup اعمال کنید

برای اعمال تابعی در متد BeautifulSoup، تابع را به پارامتر رشته اضافه کنید find_all() روش.

# Apply function to BeautifulSoup
def find_a_string(value):
    return lambda text: value in text

soup.find_all(string=find_a_string('Description Tag'))
['Description Tags',
 'Description Tag With Whitespace',
 'Description Tag Missing',
 'Description Tag Missing With Meta Nosnippet',
 'Description Tag Duplicate',
 'Description Tag Duplicate',
 'Noindex and Description Tag Duplicate',
 'Noindex and Description Tag Duplicate',
 'Description Tag Too Long']

تجزیه صفحه HTML با عبارات منظم در BeautifulSoup

برای استفاده از عبارات منظم برای تجزیه یک صفحه HTML با BeautifulSoup، وارد کنید re ماژول، و اختصاص a re.compile() شیء به پارامتر رشته از find_all() روش.

from bs4 import BeautifulSoup
import re

# Parse using regex
soup = BeautifulSoup(r.text, 'html.parser')
soup.find_all(string=re.compile('Description Tag'))
['Description Tags',
 'Description Tag With Whitespace',
 'Description Tag Missing',
 'Description Tag Missing With Meta Nosnippet',
 'Description Tag Duplicate',
 'Description Tag Duplicate',
 'Noindex and Description Tag Duplicate',
 'Noindex and Description Tag Duplicate',
 'Description Tag Too Long']

نحوه استفاده از XPath با BeautifulSoup (lxml)

برای استفاده از XPath برای استخراج عناصر از یک سند HTML با BeautifulSoup، باید کتابخانه پایتون lxml را نصب کنید زیرا Beautiful از عبارات XPath پشتیبانی نمی کند.

from lxml import html

# Parse HTML with XPath
content = html.fromstring(r.content)
panels = content.xpath('//*[@class="panel-header"]')

# get text from tags
[panel.find('h3').text for panel in panels][:5]

والدین، فرزندان و خواهران و برادران یک عنصر HTML را پیدا کنید

BeautifulSoup یک درخت تجزیه را برمی‌گرداند که می‌توانید از طریق هر یک از والدین، فرزند و خواهر و برادر در درخت حرکت کنید تا عناصر مورد نظر خود را پیدا کنید.

والد(های) یک عنصر HTML را پیدا کنید

برای پیدا کردن والد تک عنصر HTML، از عبارت استفاده کنید find_parent() روشی که عنصر مورد نظر و همچنین والد آن را در درخت HTML به شما نشان می دهد.

a_child = soup.find_all('a')[0]
a_child.find_parent()
<div id="header">
<a href="/" id="logo">Crawler Test <span class="neon-effect">two point oh!</span></a>
<div style="position:absolute;right:520px;top:-4px;"></div>
</div>

برای پیدا کردن تمام والدین یک عنصر HTML، از عبارت استفاده کنید find_parents() متد روی شی BeautifulSoup.

فرزند (فرزندان) یک عنصر HTML را پیدا کنید

برای پیدا کردن یک فرزند از یک عنصر HTML، از عبارت استفاده کنید findChild() روشی که فرزند عنصر در درخت HTML را به شما نشان می دهد.

a_child = soup.find_all('a')[0]
a_child.findChild()
<span class="neon-effect">two point oh!</span>

برای پیدا کردن تمام فرزندان یک عنصر HTML، از عبارت استفاده کنید fetchChildren() متد روی شی BeautifulSoup.

a_child.findChildren()
#or
list(a_child.children)

همه نوادگان عنصر HTML را پیدا کنید.

list(a_child.descendants)

خواهر و برادر (های) یک عنصر HTML را پیدا کنید

برای پیدا کردن خواهر و برادر بعدی بعد از یک عنصر HTML، از find_next_sibling() روشی که خواهر و برادر بعدی را در درخت HTML به شما نشان می دهد.

a_child = soup.find_all('a')[0]
a_child.find_next_sibling()
a_child.find_next_siblings()
<div style="position:absolute;right:520px;top:-4px;"></div>

جایی که این از آنجا می آید این است که اگر عنصر والد را بگیرید:

a_parent = soup.find('div',{'id':'header'})
a_parent

شما HTML عنصر را دریافت می‌کنید، و برادر بعدی تگ را دریافت می‌کنید، که div برجسته شده (و نتیجه نشان داده شده در قبل) است.

<div id="header">
<a href="/" id="logo">Crawler Test <span class="neon-effect">two point oh!</span></a>
<div style="position:absolute;right:520px;top:-4px;"></div>
</div>

به طور مشابه، می توانید خواهر و برادر قبلی را نیز پیدا کنید.

a_child. find_previous_sibling()
a_child. find_previous_siblings()

برای پیدا کردن تمام والدین یک عنصر HTML، از عبارت استفاده کنید find_parents() متد روی شی BeautifulSoup.

HTML شکسته را با BeautifulSoup رفع کنید

با BeautifulSoup، می‌توانید HTML شکسته را بگیرید و قسمت‌های گمشده را با استفاده از آن تکمیل کنید prettify() متد روی شی BeautifulSoup.

# Fix Broken HTML with BeautifulSoup
from bs4 import BeautifulSoup

soup = BeautifulSoup("<p>Incomplete Broken <span>HTML<</p>")
print(soup.prettify())
<html>
 <body>
  <p>
   Incomplete Broken
   <span>
    HTML
   </span>
  </p>
 </body>
</html>

مقالات مرتبط با وب اسکرپینگ

نتیجه

ما همه چیزهایی را که احتمالاً می‌توانید در مورد خراش دادن وب با BeautifulSoup بدانید، پوشش داده‌ایم. موفق باشید!

سئو PBN | خبر های جدید سئو و هک و سرور