在刮擦动态网页内容时,您的结果是否很差?不仅仅是你。爬行动态数据是标准刮板的一项具有挑战性的工作(至少可以说)。这是因为提出HTTP请求时JavaScript在后台运行。
刮擦动态网站需要在浏览器中渲染整个页面并提取目标信息。
加入我们的分步教程,了解有关动态网络刮擦的所有内容
让我们深入研究!
什么是动态网站?
动态网站是一个没有直接在静态HTML中的内容的网站。它使用服务器端或客户端来显示数据,有时基于用户的操作(例如, ,单击,滚动等)。
简单地说,这些网站在每个服务器请求中显示不同的内容或布局。这有助于加载时间,因为每次用户想要查看“新”内容时,都无需重新加载相同的信息。
如何识别它们?一种方法是在浏览器>/strong>上的命令调色板中禁用JavaScript。如果网站是动态的,内容将消失。
让我们以Saleor React店面为例。这是其头版的外观:
注意标题,图像和艺术家的名字。
现在,让我们使用以下步骤禁用JavaScript:
- 检查页面:右键单击并选择“检查”以打开DevTools窗口。
- 导航到命令调色板:ctrl/cmd + shift + p。
- 搜索“ JavaScript”。
- 单击禁用JavaScript。
- 点击刷新。
结果是什么?请参阅下面:
您自己看到它!禁用JavaScript删除所有动态的Web内容。
使用Python的动态网络刮擦的替代方案
所以,您想用python刮擦动态网站...
由于诸如Beautiful Soup或Requests之类的库不会自动获取动态内容,因此您还有两个选项可以完成任务:
- 将内容提供给标准库。
- 刮擦时执行页面的内部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作为我们的目标网站:
让我们尝试用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时发生的事情:
这正是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:
在解决此问题之前,我们需要检查网站并确定要提取的元素的位置。
我们可以看到这些头条新闻很常见。我们将其复制并映射H2S以使用Chrome驱动程序获取元素。
粘贴此代码:
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的示例页面。
此脚本将滚动浏览前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调用来刮擦动态网站。立即免费尝试并节省时间和资源。
您发现内容有帮助吗?在Twitter,LinkedIn和Facebook上分享单词并在
本文最初发表在Zenrows上:Dynamic Web Pages Scraping with Python: Guide to Scrape All Content