من HTML إلى بيانات: جداول الويب
كيف نحرّر البيانات المحبوسة في صفحات HTML إلى جداول نحلّلها؟ ⏱ نحو 40 دقيقة.
- تحلّل
HTMLبـBeautifulSoup. - تختار العناصر بالأصناف
select/select_one. - تبني
DataFrameمن جدولHTML. - تحوّل النصّ المستخرج إلى أرقام، وتراعي الإذن.
١الصفحة مليئة ببيانات
كثير من بيانات الويب محبوسٌ داخل صفحات HTML: جداول الأسعار، نتائج المباريات، إحصاءات لوحات التحكم. استخراجها يسمّى الكشط Web Scraping. أداتنا BeautifulSoup: تحلّل HTML إلى شجرة نبحث فيها بالوسوم والأصناف ثم نبني منها جدولًا.
٢قراءة عناصر متفرّقة
نحلّل HTML بـ BeautifulSoup(html, "html.parser")، ثم نختار العناصر: select يجد كل المطابق، وselect_one أوّله، و.text النصّ داخله:
from bs4 import BeautifulSoup html = """<ul> <li class="prod"><span class="name">سماعة</span><span class="price">120</span></li> <li class="prod"><span class="name">كاميرا</span><span class="price">210</span></li></ul>""" soup = BeautifulSoup(html, "html.parser")for item in soup.select(".prod"): name = item.select_one(".name").text price = int(item.select_one(".price").text) print(name, "=", price, "ريال")
نعتمد على الأصناف (class) لا على ترتيب العناصر؛ فالترتيب يتغيّر مع تحديث الصفحة، والصنف أثبت.
٣من جدول HTML إلى DataFrame
الجدول حالة شائعة: نمرّ على صفوف <tr> ونجمع خلاياها، ثم نسلّمها إلى Pandas:
from bs4 import BeautifulSoupimport pandas as pd html = """<table> <tr><th>page</th><th>views</th><th>avg_time</th></tr> <tr><td>home</td><td>1200</td><td>12</td></tr> <tr><td>products</td><td>860</td><td>45</td></tr> <tr><td>checkout</td><td>210</td><td>90</td></tr></table>""" soup = BeautifulSoup(html, "html.parser")rows = soup.select("tr")header = [th.text for th in rows[0].select("th")]data = [[td.text for td in r.select("td")] for r in rows[1:]] df = pd.DataFrame(data, columns=header)df["views"] = df["views"].astype(int) # النصّ إلى رقمprint(df)print("إجمالي المشاهدات:", df["views"].sum())
لاحظ astype(int): كل ما يُستخرج من HTML نصّ، فنحوّل الأعمدة الرقمية صراحةً قبل الحساب.
توقّع وتحقّق
مكتبة تحليل HTML في بايثون:
select_one يعيد:
كل ما يُستخرج من HTML نوعه:
قبل كشط موقع يجب:
الخلاصة
- كثير من بيانات الويب داخل
HTML؛ استخراجها يسمّى الكشط. BeautifulSoupتحلّلHTMLإلى شجرة؛selectوselect_oneو .textأدواتك.- من جدول
HTMLنبنيDataFrameبالمرور على صفوفtrوخلاياtd. - كل مستخرَج نصّ؛ حوّل الأعمدة الرقمية بـ
astype، واكشط بإذن.
تحدٍّ برمجي: اكشط جدولًا
متوسطحلّل جدول HTML التالي بـ BeautifulSoup، وابنِ منه إطارًا، ثم اطبع عدد المدن ومجموع المبيعات.
- استخرج صفوف الجدول وابنِ DataFrame بعمودي
cityوsales. - اطبع عدد المدن ثم مجموع
sales(بعد تحويله لرقم).
ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:
from bs4 import BeautifulSoupimport pandas as pdhtml = """<table> <tr><th>city</th><th>sales</th></tr> <tr><td>Riyadh</td><td>300</td></tr> <tr><td>Jeddah</td><td>250</td></tr> <tr><td>Dammam</td><td>180</td></tr></table>"""# ابنِ الإطار ثم اطبع عدد المدن ومجموع المبيعات
💡 تلميح 1
[td.text for td in r.select("td")].💡 تلميح 2
df["sales"].astype(int) قبل الجمع.حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
from bs4 import BeautifulSoupimport pandas as pdhtml = """<table> <tr><th>city</th><th>sales</th></tr> <tr><td>Riyadh</td><td>300</td></tr> <tr><td>Jeddah</td><td>250</td></tr> <tr><td>Dammam</td><td>180</td></tr></table>"""soup = BeautifulSoup(html, "html.parser")rows = soup.select("tr")data = [[td.text for td in r.select("td")] for r in rows[1:]]df = pd.DataFrame(data, columns=["city", "sales"])df["sales"] = df["sales"].astype(int)print(len(df))print(int(df["sales"].sum()))