返回

如何用 Python 和 Selenium 爬取网页表格数据?

python

如何使用 Selenium 和 Python 爬取网页表格数据

在数据分析和信息收集的过程中,我们常常需要从网页上获取数据。网页表格作为一种常见的数据展示形式,蕴藏着大量有价值的信息。手动复制粘贴显然效率低下且容易出错,这时就需要借助 Web Scraping 技术来自动化完成这项任务。Selenium 作为一个强大的浏览器自动化工具,结合 Python 的灵活语法,可以轻松实现网页表格数据的抓取。

本文将以一个包含响应式表格的网页为例,详细介绍如何使用 Selenium 和 Python 提取表格数据,并针对实际操作中可能遇到的动态加载问题提供解决方案。

爬取网页表格数据的挑战

许多网站采用响应式表格来展示数据,这类表格的 HTML 结构往往较为复杂,给数据提取带来了一定的挑战。你可能会尝试使用 Selenium 定位表格元素,并提取其中的文本内容,但最终得到的结果可能是一堆空列表或者不完整的数据。

以如下 HTML 代码为例,它展示了一个典型的响应式表格结构(为了保护隐私,部分代码已做修改,但结构与实际代码一致):

<table class="items">
    <tbody>
        <tr class="odd">
            <td class="centered">1</td>
            <td class="centered no-border-right">
                <a title="company 1" name="" href="/company1/year_id/1970"> <img src="https://company_1.com/logo.png"> </a>
            </td>
            <td class="mainlink no-border-links">
                <a title="company 1" name="" href="/company1/year_id/1970">company 1</a>
            </td>
            <td class="rights mainlink redtext">$270k</td>
            <td class="centered">
                <a href="/company 1/purchase/year_id/1970">5</a>
            </td>
            <td class="rights mainlink greentext">- </td>
            <td class="centered">
                <a href="/company 1/purchase/year_id/1970">4</a>
            </td>
            <td class="rights mainlink">
                <span class="redtext">$-270k</span>
            </td>
        </tr>
        <tr class="even"> 
            # 其他24行数据,结构类似
        </tbody>
</table>

如果你使用以下 Python 代码尝试提取数据:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from fake_useragent import UserAgent
from pandas import DataFrame

option = webdriver.ChromeOptions()
option.add_argument("--headless")
ua = UserAgent()
option.add_argument(f"user-agent={ua.chrome}")
driver = webdriver.Chrome(options=option)

table_class='items'

url_expenditure = 'https://target_website.com'
driver.get(url_expenditure)
driver.implicitly_wait(5)

table_element = driver.find_element(By.CLASS_NAME, table_class)
table_data = table_element.find_element(By.TAG_NAME, "tr") 

table_data = []
for row in table_element.find_elements(By.TAG_NAME, "tr"):
    row_data = [cell.text.strip() for cell in row.find_elements(By.TAG_NAME, "td")]  
    table_data.append(row_data)

driver.quit()

print(table_data)

你得到的结果很可能是:

[[], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', ''], ['', '', '', '', '', '', '', '']]

这与我们期望的结果([['1','','company 1','$270K','5','-','4','$-270K'],[#next row of data]...])相去甚远。

克服动态加载,精准提取数据

出现上述问题的原因在于目标网页可能使用了 JavaScript 动态加载表格数据。Selenium 在页面加载完成后立即获取表格内容,但此时数据尚未完全加载,因此无法获取到正确的结果。

为了解决这个问题,我们需要借助 WebDriverWait 等待数据加载完成后再进行提取。

修改后的代码如下:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from fake_useragent import UserAgent
from pandas import DataFrame

# 设置 Chrome 选项
option = webdriver.ChromeOptions()
option.add_argument("--headless")
ua = UserAgent()
option.add_argument(f"user-agent={ua.chrome}")
driver = webdriver.Chrome(options=option)

# 设置目标网页地址和表格 CSS 选择器
url_expenditure = 'https://target_website.com'
table_class = 'items'

# 打开网页
driver.get(url_expenditure)

# 等待表格数据加载完成
try:
    table_element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, table_class))
    )
except TimeoutException:
    print("表格加载超时!")
    driver.quit()
    exit()

# 提取表格数据
table_data = []
for row in table_element.find_elements(By.TAG_NAME, "tr"):
    row_data = [cell.text.strip() for cell in row.find_elements(By.TAG_NAME, "td")]  
    table_data.append(row_data)

# 关闭浏览器
driver.quit()

# 打印提取到的数据
print(table_data)

在这段代码中,我们使用了 WebDriverWait 和 expected_conditions 模块来等待表格元素加载完成。WebDriverWait(driver, 10) 表示等待最多 10 秒钟,EC.presence_of_element_located((By.CLASS_NAME, table_class)) 表示等待 class 为 'items' 的元素出现。

通过这种方式,Selenium 就可以在数据完全加载完成后再进行提取,从而获得正确的结果。

总结与扩展

本文介绍了如何使用 Selenium 和 Python 爬取网页表格数据,并提供了解决数据加载问题的方案。

以下是一些常见问题及其解答:

1. 如何处理网页表格翻页?

可以使用 Selenium 定位翻页按钮,模拟点击操作,并在每次翻页后重新提取表格数据,直至获取所有数据。

2. 如何将提取的数据保存到文件?

可以使用 Python 的文件操作功能将数据保存为 txt、csv 或 json 等格式,方便后续分析和使用。

3. 如何避免被网站识别为爬虫?

可以设置随机请求头、设置请求间隔、使用代理 IP 等方法,降低被识别为爬虫的风险。

希望这篇文章能够帮助你解决实际问题,并顺利完成 Web Scraping 任务。

SEO 关键词: Web Scraping, Selenium, Python, 数据提取, 网页表格, 响应式表格, 动态加载, WebDriverWait, expected_conditions

**SEO ** 学习如何使用 Selenium 和 Python 从网页表格中提取数据。本文提供了解决动态加载表格数据问题的解决方案,并附带详细的代码示例。