动态网页用Python刮擦:刮擦所有内容的指南
#python #webscraping #howto

在刮擦动态网页内容时,您的结果是否很差?不仅仅是你。爬行动态数据是标准刮板的一项具有挑战性的工作(至少可以说)。这是因为提出HTTP请求时JavaScript在后台运行。

刮擦动态网站需要在浏览器中渲染整个页面并提取目标信息。

加入我们的分步教程,了解有关动态网络刮擦的所有内容

让我们深入研究!

什么是动态网站?

动态网站是一个没有直接在静态HTML中的内容的网站。它使用服务器端或客户端来显示数据,有时基于用户的操作(例如, ,单击,滚动等)。

简单地说,这些网站在每个服务器请求中显示不同的内容或布局。这有助于加载时间,因为每次用户想要查看“新”内容时,都无需重新加载相同的信息。

如何识别它们?一种方法是在浏览器>/strong>上的命令调色板中禁用JavaScript。如果网站是动态的,内容将消失。

让我们以Saleor React店面为例。这是其头版的外观:

Saleor React Storefront

注意标题,图像和艺术家的名字。

现在,让我们使用以下步骤禁用JavaScript:

  1. 检查页面:右键单击并选择“检查”以打开DevTools窗口。
  2. 导航到命令调色板:ctrl/cmd + shift + p。
  3. 搜索“ JavaScript”。
  4. 单击禁用JavaScript。
  5. 点击刷新。

结果是什么?请参阅下面:

Result of Disabling JavaScript

您自己看到它!禁用JavaScript删除所有动态的Web内容。

使用Python的动态网络刮擦的替代方案

所以,您想用python刮擦动态网站...

由于诸如Beautiful SoupRequests之类的库不会自动获取动态内容,因此您还有两个选项可以完成任务:

  • 将内容提供给标准库。
  • 刮擦时执行页面的内部JavaScript。

但是,并非所有动态页面都是相同的。一些通过JS API渲染内容可以通过检查“网络”选项卡来访问。其他人将JS渲染的内容存储在DOM中的某个地方(文档对象模型)中。

好消息是我们可以在两种情况下解析JSON字符串以提取必要的数据。

请记住,在某些情况下,这些解决方案是不可能的。对于此类网站,您可以使用无头浏览器渲染页面并提取所需的数据。

使用Python爬行动态网页的替代方法是:

  • 手动找到数据和解析JSON字符串。
  • 使用无头浏览器执行该页面的内部JavaScript (例如,selenium或Pyppeteer,一个非正式的python python PorteTer)。

在Python中刮擦动态网站的最简单方法是什么?

是的,无头浏览器可能会缓慢且性能密集。但是,它们取消了对网络刮擦的所有限制。那就是您不计算反机器人检测。而且您不应该因为我们已经告诉过您how to bypass such protections

手动找到数据和解析JSON字符串假定可以访问动态数据的JSON版本。不幸的是,并非总是如此,尤其是在高级单页应用程序(SPA)方面。

更不用说模仿API请求是无法扩展的。他们通常需要饼干和身份验证以及其他可以轻松阻止您的限制。

在Python中刮擦动态网页的最佳方法取决于您的目标和资源。如果您可以访问网站的JSON并希望提取单个页面的数据,则可能不需要无头浏览器。

但是,除非这一小部分案例,大多数情况下,使用美丽的汤和硒是您最好,最简单的选择。

是时候让我们的手变得肮脏了!准备编写一些代码,并准确查看如何在Python中刮擦动态网站!

先决条件

要遵循本教程,您需要满足一些要求。我们将使用以下工具:

  • Python 3:最新版本的Python将效果最好。在写作时,即3.11.2。
  • Selenium
  • Webdriver Manager:这将确保浏览器和驾驶员的版本匹配。为此,您无需手动下载网络驱动器。
pip install selenium webdriver-manager

您现在拥有所需的一切。让我们走!

方法1:使用美丽的汤与Python进行动态网络刮擦

美丽的汤可以说是最受欢迎的python库,用于爬行HTML数据。

要提取信息,我们需要目标页面的HTML字符串。但是,动态内容并不直接存在于网站的静态HTML中。这意味着美丽的汤无法访问JavaScript生成的数据

这是一个解决方案:如果网站使用AJAX请求加载内容,则可以使用extract data from XHR requests

方法#2:使用Selenium在Python中刮擦动态网页

要了解硒如何帮助您刮擦动态网站,首先,我们需要检查常规库,例如Requests,与它们互动。

我们将使用Angular作为我们的目标网站:

Angular

让我们尝试用Requests刮擦并查看结果。在此之前,我们必须安装可以使用pip命令执行的Requests库。

pip install requests

这是我们的代码的样子:

import requests 

url = 'https://angular.io/' 

response = requests.get(url) 

html = response.text 

print(html)

您可以看到,仅提取以下HTML:

<noscript> 
    <div class="background-sky hero"></div> 
    <section id="intro" style="text-shadow: 1px 1px #1976d2;"> 
        <div class="hero-logo"></div> 
        <div class="homepage-container"> 
            <div class="hero-headline">The modern web<br>developer's platform</div> 
        </div> 
    </section> 
    <h2 style="color: red; margin-top: 40px; position: relative; text-align: center; text-shadow: 1px 1px #fafafa; border-top: none;"> 
        <b><i>This website requires JavaScript.</i></b> 
    </h2> 
</noscript>

但是,检查网站的内容比检索到的内容更多。

这是我们在页面上禁用JavaScript时发生的事情:

Angular with Disabled JavaScript

这正是Requests能够返回的。该图书馆从网站的静态HTML中解析数据时没有任何错误,这正是它创建的。

在这种情况下,旨在取得与网站上显示的结果相同的结果。你能猜出为什么吗?是的,这是因为这是一个动态的网页。

要访问整个内容并提取我们的目标数据,我们必须渲染JavaScript。

是时候使用Selenium Dynamic Web刮擦做正确的时候了。

我们将使用以下脚本快速爬网我们的目标网站:

from selenium import webdriver 
from selenium.webdriver.chrome.service import Service as ChromeService 
from webdriver_manager.chrome import ChromeDriverManager 

url = 'https://angular.io/' 

driver = webdriver.Chrome(service=ChromeService( 
    ChromeDriverManager().install())) 

driver.get(url) 

print(driver.page_source)

那里有!该页面的完整HTML,包括动态Web内容。

恭喜!您刚刚刮过了第一个动态网站。

选择硒中的元素

有不同的方法可以访问硒中的元素。我们在web scraping with Selenium in Python指南中深入讨论此问题。

仍然,我们将以一个示例来解释这一点。让我们在目标网站上仅选择H2S:

Selecting H2 Elements

在解决此问题之前,我们需要检查网站并确定要提取的元素的位置。

我们可以看到这些头条新闻很常见。我们将其复制并映射H2S以使用Chrome驱动程序获取元素。

Using ChromeDriver to copy and map H2 elements

粘贴此代码:

from selenium import webdriver 
from selenium.webdriver.common.by import By 
from selenium.webdriver.chrome.service import Service as ChromeService 
from webdriver_manager.chrome import ChromeDriverManager 

# instantiate options 
options = webdriver.ChromeOptions() 

# run browser in headless mode 
options.headless = True 

# instantiate driver 
driver = webdriver.Chrome(service=ChromeService( 
    ChromeDriverManager().install()), options=options) 

# load website 
url = 'https://angular.io/' 

# get the entire website content 
driver.get(url) 

# select elements by class name 
elements = driver.find_elements(By.CLASS_NAME, 'text-container') 
for title in elements: 
    # select H2s, within element, by tag name 
    heading = title.find_element(By.TAG_NAME, 'h2').text 
    # print H2s 
    print(heading)

您将获得以下内容:

"DEVELOP ACROSS ALL PLATFORMS" 
"SPEED & PERFORMANCE" 
"INCREDIBLE TOOLING" 
"LOVED BY MILLIONS"

很好,轻松!您现在可以轻松地用硒刮擦动态站点。

如何用硒刮擦无限滚动网页

当用户向下滚动到页面底部时,一些动态页面加载了更多内容。这些被称为“ Infine Scroll网站”。爬它们更具挑战性。为此,我们需要指示蜘蛛滚动到底部,等待所有新内容加载,然后开始刮擦。

用一个示例理解这一点。让我们使用Scraping Club的示例页面。

Scraping Club's sample page

此脚本将滚动浏览前20个结果并提取其标题:

from selenium import webdriver 
from selenium.webdriver.common.by import By 
from selenium.webdriver.chrome.service import Service as ChromeService 
from webdriver_manager.chrome import ChromeDriverManager 
import time 

options = webdriver.ChromeOptions() 
options.headless = True 
driver = webdriver.Chrome(service=ChromeService( 
    ChromeDriverManager().install()), options=options) 

# load target website 
url = 'https://scrapingclub.com/exercise/list_infinite_scroll/' 

# get website content 
driver.get(url) 

# instantiate items 
items = [] 

# instantiate height of webpage 
last_height = driver.execute_script('return document.body.scrollHeight') 

# set target count 
itemTargetCount = 20 

# scroll to bottom of webpage 
while itemTargetCount > len(items): 
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight);') 

    # wait for content to load 
    time.sleep(1) 

    new_height = driver.execute_script('return document.body.scrollHeight') 

    if new_height == last_height: 
        break 

    last_height == new_height 

    # select elements by XPath 
    elements = driver.find_elements(By.XPATH, "//div[@class='card-body']/h4/a") 
    h4_texts = [element.text for element in elements] 

    items.extend(h4_texts) 

    # print title 
    print(h4_texts)

备注:为无限滚动页面设定目标计数很重要,以便您可以在某个时候结束脚本。

在上一个示例中,我们使用了另一个选择器:By.XPath。如前所述,它将根据XPATH而不是类和ID找到元素。检查页面,右键单击包含要刮擦元素的<div>,然后选择复制路径

您的结果应该像这样:

['Short Dress', 'Patterned Slacks', 'Short Chiffon Dress', 'Off-the-shoulder Dress', ...]

您有了它,前20种产品的H4S!

备注:使用连续的Selenium updates使用硒进行动态网络刮擦可能会变得棘手。做好最新的更改。

结论

动态网页无处不在。因此,在数据提取工作中您会遇到足够的机会。请记住,熟悉它们的结构将有助于您确定检索目标信息的最佳方法。

我们在本文中探索的所有方法都带有自己的缺点和缺点。因此,看看ZenRows提供的内容。该解决方案允许您使用简单的API调用来刮擦动态网站。立即免费尝试并节省时间和资源。

您发现内容有帮助吗?在TwitterLinkedInFacebook上分享单词并在

本文最初发表在Zenrows上:Dynamic Web Pages Scraping with Python: Guide to Scrape All Content