0Pricing
R Academy · درس

كشط الجداول والروابط

حلّل جداول HTML إلى إطارات بيانات واجمع جميع الروابط التشعبية في الصفحة.

كشط الجداول والروابط درس مجاني في R Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.

جداول HTML في صفحات الويب

تُعدّ جداول HTML (<table>) أهدافًا مناسبة جدًا للكشط لأنها منظّمة مسبقًا. وتحولها html_table() في rvest مباشرةً إلى إطارات بيانات في R، مع معالجة الرؤوس تلقائيًا.

library(rvest)
html <- read_html('
  <table>
    <thead><tr><th>Country</th><th>GDP</th><th>Pop</th></tr></thead>
    <tbody>
      <tr><td>USA</td><td>25T</td><td>330M</td></tr>
      <tr><td>China</td><td>18T</td><td>1400M</td></tr>
    </tbody>
  </table>
')
# html_table converts to data frame
tbl <- html_table(html_element(html, 'table'))
class(tbl)      # 'data.frame'
names(tbl)      # c('Country', 'GDP', 'Pop')
nrow(tbl)       # 2
print(tbl)

html_table() على صفحة كاملة

عندما تحتوي الصفحة على جداول متعددة، استخدموا html_elements() (بصيغة الجمع) للحصول على جميع الجداول، ثم طبّقوا html_table() على مجموعة العقد الناتجة لإعادة قائمة من إطارات البيانات. اختاروا الجدول المطلوب باستخدام الفهرس.

library(rvest)
html <- read_html('
  <table id="t1"><tr><th>A</th></tr><tr><td>1</td></tr></table>
  <table id="t2"><tr><th>X</th><th>Y</th></tr>
    <tr><td>10</td><td>20</td></tr></table>
')
# Get ALL tables as a list of data frames
tables <- html_table(html_elements(html, 'table'))
length(tables)  # 2

# First table
tables[[1]]

# Second table
tables[[2]]

# Select a specific table by its id
table2 <- html_table(html_element(html, '#t2'))
print(table2)

تنظيف بيانات الجداول

غالبًا ما تحتوي الجداول المكشوطة من المواقع على رؤوس غير مرتبة، أو خلايا مدمجة، أو مسافات بيضاء زائدة. استخدموا janitor::clean_names() لتنظيف الرؤوس، وعمليات dplyr وstringr المعتادة لتنظيف قيم الخلايا.

library(rvest)
html <- read_html('
  <table>
    <tr><th>Product Name</th><th>Price (USD)</th><th>In Stock?</th></tr>
    <tr><td>  Widget A  </td><td>$12.50</td><td>Yes</td></tr>
    <tr><td>Gadget B</td><td>$7.99</td><td>No</td></tr>
  </table>
')
df <- html_table(html_element(html, 'table'))

# Clean column names
names(df) <- c('product', 'price', 'in_stock')

# Strip whitespace and dollar signs
df$product  <- trimws(df$product)
df$price    <- as.numeric(gsub('[$]', '', df$price))
df$in_stock <- df$in_stock == 'Yes'
print(df)

كشط جميع الروابط في صفحة

الروابط هي وسوم ارتساء (<a>) تحتوي على سمات href. استخدموا html_elements(page, 'a') للحصول على جميع وسوم الارتساء، ثم html_attr('href') للحصول على عناوين URL وhtml_text2() للحصول على نصوص الروابط.

library(rvest)
html <- read_html('
  <div>
    <a href="/about">About Us</a>
    <a href="/products">Products</a>
    <a href="https://partner.com" rel="external">Partner</a>
    <a>No href link</a>
  </div>
')
# Get all anchor elements
anchors <- html_elements(html, 'a')

# Extract text and href
link_text <- html_text2(anchors)
link_href <- html_attr(anchors, 'href')

data.frame(text = link_text, href = link_href)
# Note: last row has NA href

تصفية الروابط المفيدة

تختلط في الصفحات الفعلية روابط التنقّل وروابط التذييل والارتساءات الداخلية بالروابط التي تريدونها فعلًا. أزيلوا قيم NA والارتساءات (#) وروابط javascript:، ثم طبّقوا مطابقة الأنماط للاحتفاظ بعناوين URL ذات الصلة فقط.

library(rvest)
html <- read_html('
  <div>
    <a href="/article/1">Article One</a>
    <a href="/article/2">Article Two</a>
    <a href="#top">Back to top</a>
    <a href="javascript:void(0)">JS link</a>
    <a href="/article/3">Article Three</a>
  </div>
')
anchors <- html_elements(html, 'a')
hrefs <- html_attr(anchors, 'href')
texts <- html_text2(anchors)

# Keep only article links
article_idx <- grepl('^/article/', hrefs) & !is.na(hrefs)
article_links <- data.frame(
  text = texts[article_idx],
  href = hrefs[article_idx]
)
print(article_links)

من عناوين URL النسبية إلى المطلقة

غالبًا ما تكون قيم href المكشوطة مسارات نسبية مثل /page. حوّلوها إلى عناوين URL مطلقة بإضافة عنوان URL الأساسي إليها. وتتولى الدالة xml2::url_absolute() تنفيذ ذلك على النحو الصحيح.

library(rvest)
base_url <- 'https://books.toscrape.com'

html <- read_html('
  <ul>
    <li><a href="/catalogue/book1">Book One</a></li>
    <li><a href="/catalogue/book2">Book Two</a></li>
    <li><a href="https://external.com/book">External</a></li>
  </ul>
')
hrefs <- html_attr(html_elements(html, 'a'), 'href')

# xml2::url_absolute resolves relative + keeps absolute
abs_urls <- xml2::url_absolute(hrefs, base = base_url)
abs_urls
# 'https://books.toscrape.com/catalogue/book1'
# 'https://books.toscrape.com/catalogue/book2'
# 'https://external.com/book'  <- kept as-is

كشط الروابط المستهدفة

بدلًا من كشط جميع الروابط ثم تصفيتها، استخدموا محدِّدات CSS محددة لاستهداف الروابط المطلوبة فقط. واجمعوا بين سياق العنصر ومحدِّدات السمات لتحقيق دقة أكبر.

library(rvest)
html <- read_html('
  <nav class="breadcrumb">
    <a href="/">Home</a> > <a href="/books">Books</a>
  </nav>
  <ul class="products">
    <li><a href="/books/1" class="prod-link">Clean Code</a></li>
    <li><a href="/books/2" class="prod-link">Refactoring</a></li>
  </ul>
  <footer>
    <a href="/privacy">Privacy</a>
  </footer>
')
# Target ONLY product links (not nav or footer)
prod_links <- html_elements(html, 'ul.products a.prod-link')
data.frame(
  title = html_text2(prod_links),
  url   = html_attr(prod_links, 'href')
)

دمج بيانات الجداول والروابط

غالبًا ما تحتوي خلايا الجدول على روابط. اجمعوا بين html_table() للحصول على القيم النصية وhtml_attr() المستهدفة للحصول على الروابط المضمّنة، وذلك لإنشاء إطار بيانات أكثر ثراءً.

library(rvest)
html <- read_html('
  <table class="results">
    <tr><th>Book</th><th>Author</th></tr>
    <tr>
      <td><a href="/b/1">Clean Code</a></td>
      <td>Robert Martin</td>
    </tr>
    <tr>
      <td><a href="/b/2">Refactoring</a></td>
      <td>Martin Fowler</td>
    </tr>
  </table>
')
# Get text from table
df <- html_table(html_element(html, 'table'))

# Get links embedded in first column
links <- html_attr(html_elements(html, 'table td a'), 'href')
df$url <- links
print(df)

معامل fill في html_table()

تحتوي جداول HTML أحيانًا على خلايا مفقودة أو صفوف ذات بنية غير منتظمة. يملأ المعامل fill=TRUE في html_table() القيم المفقودة باستخدام NA بدلًا من إطلاق خطأ.

library(rvest)
html <- read_html('
  <table>
    <tr><th>Name</th><th>Score</th><th>Grade</th></tr>
    <tr><td>Alice</td><td>95</td><td>A</td></tr>
    <tr><td>Bob</td><td>80</td></tr>
  </table>
')
# Without fill=TRUE this may error on uneven rows
df <- html_table(html_element(html, 'table'), fill = TRUE)
print(df)
# Name  Score Grade
# Alice    95     A
# Bob      80  <NA>

# fill=TRUE is safe even when rows are uniform
is.na(df[2, 'Grade'])  # TRUE

استخراج مصادر الصور

تستخدم الصور سمات src (وأحيانًا data-src للتحميل الكسول). ويستخرج الأسلوب نفسه باستخدام html_attr() عناوين URL للصور بهدف تنزيلها أو فهرستها.

library(rvest)
html <- read_html('
  <div class="gallery">
    <img src="/img/photo1.jpg" alt="Sunset">
    <img src="/img/photo2.jpg" alt="Mountains">
    <img data-src="/img/lazy.jpg" class="lazy" alt="Lake">
  </div>
')
# Regular images
images <- html_elements(html, 'img')
srcs  <- html_attr(images, 'src')
alts  <- html_attr(images, 'alt')

data.frame(alt = alts, src = srcs)
# For lazy-loaded images check data-src
lazy_src <- html_attr(html_element(html, '.lazy'), 'data-src')
lazy_src  # '/img/lazy.jpg'

حفظ البيانات المكشوطة

بعد كشط الجداول والروابط في إطار بيانات، احفظوا النتائج باستخدام write.csv() أو readr::write_csv(). أدرجوا دائمًا طابعًا زمنيًا أو عنوان URL للمصدر لضمان تتبّع مصدر البيانات.

library(rvest)
html <- read_html('
  <table>
    <tr><th>Product</th><th>Price</th></tr>
    <tr><td>Widget</td><td>9.99</td></tr>
    <tr><td>Gadget</td><td>14.50</td></tr>
  </table>
')
df <- html_table(html_element(html, 'table'))

# Add metadata
df$scraped_at <- Sys.time()
df$source_url <- 'https://example.com/products'

# Save to CSV
# write.csv(df, 'products.csv', row.names = FALSE)
print(df)
cat('Data ready for analysis or storage')

اختبار سريع

اختبروا مدى فهمكم لكشط جداول HTML والروابط باستخدام rvest.

مراجعة: الجداول والروابط

أهم النقاط: تحوّل html_table() جداول HTML تلقائيًا إلى إطارات بيانات؛ استخدموا fill=TRUE مع الجداول غير المنتظمة. وبالنسبة إلى الروابط، احصلوا على جميع وسوم الارتساء باستخدام html_elements('a')، والنصوص باستخدام html_text2()، وعناوين URL باستخدام html_attr('href'). حوّلوا عناوين URL النسبية إلى مطلقة باستخدام xml2::url_absolute(). صفّوا الروابط غير المرغوبة بحسب النمط. ادمجوا نصوص الجداول وعناوين URL للروابط المضمّنة للحصول على مجموعات بيانات أغنى.

library(rvest)
# Table scraping pattern:
# tables <- html_table(html_elements(page, 'table'))
# df <- tables[[1]]

# Link scraping pattern:
# links <- html_elements(page, 'a[href]')
# data.frame(
#   text = html_text2(links),
#   url  = xml2::url_absolute(
#            html_attr(links, 'href'),
#            base = base_url
#          )
# )

# Combine: scrape table text AND embedded link URLs
cat('Tables + links = most of what the web offers')

الأسئلة الشائعة

هل درس «كشط الجداول والروابط» مجاني؟

نعم — نص درس «كشط الجداول والروابط» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.

ماذا ستتعلم في «كشط الجداول والروابط»؟

حلّل جداول HTML إلى إطارات بيانات واجمع جميع الروابط التشعبية في الصفحة. تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟

لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «كشط الجداول والروابط»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟

نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. بنية HTML ومحدّدات CSS
  2. أساسيات html_element() وhtml_text()
  3. كشط الجداول والروابط
  4. التعامل مع تقسيم الصفحات والصفحات المتعددة
← العودة إلى R Academy