使用 Selenium 进行网页抓取:初学者终极指南
使用 Selenium 进行网页抓取的分步指南。
现代网站(如社交媒体)依赖于 JavaScript。不幸的是,传统脚本在从动态元素中提取信息时会遇到困难。这是因为您需要 JavaScript 来呈现整个页面,然后才能获取数据。Selenium 因其实现这一功能而广受欢迎 - 它可以像冠军一样处理异步加载或无限滚动。
本文将解释为什么您应该选择 Selenium 进行网页抓取以及如何增加成功请求的机会。您还将找到有关如何使用 Python 构建 Selenium 网页抓取器的分步教程。
什么是使用 Selenium 进行 Python Web 抓取?
为什么选择 Selenium 进行网页抓取?
Selenium 是网页抓取的热门选择,原因如下:
- 能够呈现 JavaScript。 Selenium 主要用于浏览器自动化,这使得它非常适合抓取依赖 JavaScript 的网站。它将完全呈现目标网站并提取数据。
- 跨浏览器支持。 Selenium 最好的一点是它可以模拟 Chrome、Firefox 和 Microsoft Edge 等主流浏览器。
- 支持多种编程语言。 它在编程语言方面也很灵活——您可以使用 Python、Java、Ruby 和 C#。
- 模拟用户行为。 使用 Selenium,您可以通过与网页交互来模仿人类行为,包括单击按钮、填写表格、提交数据、滚动和浏览页面。
- 处理 CAPTCHA。 一些网站使用 CAPTCHA 来防止类似机器人的活动。Selenium 可以通过在浏览器中显示这些测试并允许您解决它们或与第三方服务集成以自动化该过程来处理这些测试。
- 防止指纹检测。 Selenium 有类似的软件包 硒隐形 隐藏您的数字指纹。正确配置后,它可以阻止登录或通过 reCAPTCHA。
- 大型社区。 该图书馆有一个活跃的社区,这意味着有许多资源、教程和插件可用于简化您的体验。
虽然 Selenium 是用于网页抓取的强大工具,但它可能不是所有情况下最有效的选择。对于简单的抓取任务或处理静态网站时,其他库(如 BeautifulSoup 或 Requests)可能是更好的选择。此外,您还可以使用其他无头库,例如 木偶戏 占用更少的资源。然而,在处理复杂、动态的网站时,Selenium 的功能使其成为可靠的选择。
准备构建 Selenium Web 爬虫
选择项目构想并设计项目参数
构建 Selenium 网络抓取工具的第一步是设计项目参数。
在使用 Selenium 进行网页抓取时,有多种编程语言可供选择。但决定使用哪一种可能很困难,因此我们 比较流行语言 最适合抓取任务(*Selenium 并不支持列表中的所有语言)。如果您仍然无法决定,请选择 Python – 它是最容易使用的语言之一,并且符合大多数项目要求。
您不需要额外的库来获取或解析数据,因为 Selenium 有自己的包和模块,涵盖所有 Web 抓取阶段。例如,如果您需要清理数据,您可以安装 selenium.by 模块。除此之外,Selenium 可以与其他强大的解析器完美配合,例如 美丽的汤.
现在,让我们开始讨论项目本身。您可以抓取亚马逊等真实目标,也可以在专门为抓取而创建的网站上练习您的技能。这样,您就可以在安全的环境中探索不同的技术、语言和工具。您可以在我们的 网络抓取沙箱列表.
当你掌握了 Selenium 后,你可能会想把你的技能付诸实践。假设你想获得最优惠的航班;你可以建立一个抓取工具来收集价格并每天下载结果。如果你没有任何用例,你可以查看一份针对初学者和高级用户的创意列表 在我们的指南中.
考虑网页抓取指南
使用代理服务器
如何使用 Selenium 进行网页抓取:分步教程
两个链接都包含 JavaScript 生成的内容,第二个页面延迟渲染。为什么你需要学习如何处理延迟内容?有时页面需要一段时间才能加载,或者你需要等待特定元素(或条件)满足后才能提取数据。
硬件需求
- Python 3。 确保你的系统上安装了最新的 Python。你可以从官方网站下载 Python.org.
- 硒。 使用以下方式安装 Selenium 包 点子. 打开命令提示符或终端并运行以下命令: 点安装硒.
- Chrome WebDriver: 下载 Chrome 网络驱动程序 与您的 Chrome 浏览器相对应。
导入库
from selenium import webdriver
2)然后使用 By 来自 Selenium 的选择器模块,用于简化元素选择。
from selenium.webdriver.common.by import By
3) 在进行下一步之前,请确保已准备好暂停刮刀的所有元素。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
4)由于我们将使用 CSV 模块,因此您也需要导入它。
import csv
设置全局变量并查找所需元素
步骤 1。 现在,让我们设置全局变量,以便我们可以存储值:
- 网址 – 您要抓取的页面;
- 超时 – 如果页面加载时间超过超时时间,您的抓取将失败。因此,您需要指定超时时间以等待元素出现,然后再解决错误;
- 产量 – 您要将抓取的引文写入其中的列表。
url = 'http://quotes.toscrape.com/js/'
#url = 'http://quotes.toscrape.com/js-delayed/'
timeout = 10 #seconds
output = []
步骤 2。 然后,检查页面源代码 quotes.toscrape.com/js 右键单击页面上的任意位置。
步骤 3。 您需要选择所有引言类对象,并在其中找到以下类的文本:引言、作者和标签。您可以使用 Selenium By 模块来查找所有这些元素。
quotes = driver.find_elements(By.CLASS_NAME, 'quote')
步骤 4。 对于引用文本和作者,使用 find_element() 函数 通过类名查找元素。然后提取文本并将其保存在变量中。
for quote in quotes:
text = quote.find_element(By.CLASS_NAME, 'text').text
print (f'Text: {text}')
author = quote.find_element(By.CLASS_NAME, 'author').text
print (f'Author: {author}')
步骤 5。 由于每句引言可以有多个标签,因此你必须使用 查找元素() 函数来查找所有标签。然后,遍历每个标签并将其文本附加到 标签 名单。
tags = []
for tag in quote.find_elements(By.CLASS_NAME, 'tag'):
tags.append(tag.text)
print (tags)
最后,你可以将变量放入字典中,然后将其附加到 产量 您创建的列表。
output.append({
'author': author,
'text': text,
'tags': tags,
})
如果您的目标网站包含多个 URL,您可以使用 CSS 或 XPath 选择器来找到它们。
有关如何使用 Selenium 查找所有 URL 的分步指南。
您还可以通过文本查找元素:
有关如何使用 Selenium 通过文本查找元素的分步指南。
或者通过查看 ID 来找到它们:
有关如何使用 Selenium 通过 id 查找元素的分步指南。
使用 Python Selenium 抓取动态网页
步骤 1。 首先,您需要使用 Selenium 设置浏览器。在此示例中,我们将使用 Chromium。
def prepare_browser():
#Initializing Chrome options
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Chrome(options= chrome_options)
return driver
注意: 如果需要添加 selenium_stealth 掩盖您的数字指纹或设置代理以避免速率限制,这里就是您要做的。如果您不知道如何使用 Python 设置 Selenium 代理,您可以参考我们的指南,其中将详细解释所有内容。
有关如何使用 Python 设置和验证 Selenium 代理的分步指南。
def main():
driver = prepare_browser()
scrape(url, driver)
driver.quit()
print (output)
if __name__ == '__main__':
main()
步骤 3。 现在,让我们开始抓取。使用 驱动程序.get(url) 函数,我们将告诉 Selenium 打开浏览器并转到该 URL。由于选择器已经准备好,因此只需粘贴代码即可。
def scrape(url, driver):
driver.get(url)
quotes = driver.find_elements(By.CLASS_NAME, 'quote')
for quote in quotes:
text = quote.find_element(By.CLASS_NAME, 'text').text
print (f'Text: {text}')
author = quote.find_element(By.CLASS_NAME, 'author').text
print (f'Author: {author}')
tags = []
for tag in quote.find_elements(By.CLASS_NAME, 'tag'):
tags.append(tag.text)
print (tags)
output.append({
'author': author,
'text': text,
'tags': tags,
})
这将打开浏览器窗口,抓取一页,将抓取的文本打印到控制台并在脚本运行完成后打印整个输出。
控制台输出示例:
Opened: http://quotes.toscrape.com/js/
Text: “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”
Author: Albert Einstein
['change', 'deep-thoughts', 'thinking', 'world']
Text: “It is our choices, Harry, that show what we truly are, far more than our abilities.”
Author: J.K. Rowling
['abilities', 'choices']
Text: “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a
miracle.”
Author: Albert Einstein
['inspirational', 'life', 'live', 'miracle', 'miracles']
Text: “The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”
Author: Jane Austen
['aliteracy', 'books', 'classic', 'humor']
Text: “Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”
Author: Marilyn Monroe
['be-yourself', 'inspirational']
Text: “Try not to become a man of success. Rather become a man of value.”
Author: Albert Einstein
['adulthood', 'success', 'value']
列表中输出的示例:
[{'author': 'Albert Einstein', 'text': '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”', 'tags': ['change', 'deep-thoughts', 'thinking', 'world']}, {'author': 'J.K. Rowling', 'text': '“It is our choices, Harry, that show what we truly are, far more than our abilities.”', 'tags': ['abilities', 'choices']}, {'author': 'Albert Einstein', 'text': '“There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”', 'tags': ['inspirational', 'life', 'live', 'miracle', 'miracles']}, {'author': 'Jane Austen', 'text': '“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”', 'tags': ['aliteracy', 'books', 'classic', 'humor']}, {'author': 'Marilyn Monroe', 'text': "“Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”", 'tags': ['be-yourself', 'inspirational']}, {'author': 'Albert Einstein', 'text': '“Try not to become a man of success. Rather become a man of value.”', 'tags': ['adulthood', 'success', 'value']}
抓取多个页面
步骤 1。 首先,找到带您进入下一页的链接。检查 HTML;链接位于类为“next”的列表项下。查找该元素内的标签。
在第二行中,查找 HREF 从元素中获取下一页的 URL,并将其分配给 下一个网址 变量。
最后,致电 刮() 再次运行该函数并将新的 URL 传递给它,以便与 Webdriver 一起进行抓取。
elem_next = driver.find_element(By.CLASS_NAME, 'next').find_element(By.TAG_NAME,'a')
next_url = elem_next.get_attribute("href")
scrape(next_url, driver)
步骤 2。 现在,脚本将能够处理分页并抓取整个类别。但是,它仍然不知道何时停止,并且会在最后一页崩溃,因为带有类的元素 下页 不会出现。
您可以将代码包装在 尝试除外 阻止以防止崩溃,并且如果需要,在到达最后一个之后在页面上执行其他操作。
WebDriverWait(driver, timeout).until(
expected_conditions.presence_of_element_located((By.CLASS_NAME, 'quote'))
)
步骤 2。 您还可以将上面的代码放在 尝试除外 块。这样,如果代码超时或没有元素 报价 类出现在页面中,您可以重试相同的请求。
现在,你的抓取功能已经完成:
def scrape(url, driver):
driver.get(url)
print (f"Opened: {driver.current_url}")
try:
WebDriverWait(driver, timeout).until(
expected_conditions.presence_of_element_located((By.CLASS_NAME, 'quote'))
)
# Finding all elements with a class of 'quote' in the page
quotes = driver.find_elements(By.CLASS_NAME, 'quote')
for quote in quotes:
text = quote.find_element(By.CLASS_NAME, 'text').text
print (f'Text: {text}')
author = quote.find_element(By.CLASS_NAME, 'author').text
print (f'Author: {author}')
tags = []
for tag in quote.find_elements(By.CLASS_NAME, 'tag'):
tags.append(tag.text)
print (tags)
output.append({
'author': author,
'text': text,
'tags': tags,
})
try:
elem_next = driver.find_element(By.CLASS_NAME, 'next').find_element(By.TAG_NAME,'a')
next_url = elem_next.get_attribute("href")
scrape(next_url, driver)
except:
print('Next button not found. Quitting.')
except:
print ('Timed out.')
将输出保存为 CSV
最后,你可以将输出写入 CSV 文件(使用 CSV 库)通过向 主() 函数。为此,我们需要一个名为 output_filename 的新变量。
field_names = ['author', 'text', 'tags']
output_filename = 'quotes.csv'
with open (output_filename, 'w', newline='', encoding='utf-8') as f_out:
writer = csv.DictWriter(f_out, fieldnames = field_names)
writer.writeheader()
writer.writerows(output)
上面的代码创建文件,写入 字段名称 列表作为 CSV 标头。然后,它会使用输出列表中的字典对象填充文件。
以下是完整脚本:
from selenium import webdriver
# Using By to simplify selection
from selenium.webdriver.common.by import By
# The latter two will be used to make sure that needed elements are present
# Before we begin scraping
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
# For writing output to a CSV file
import csv
url = 'http://quotes.toscrape.com/js/'
#url = 'http://quotes.toscrape.com/js-delayed/'
timeout = 20 #seconds
output = []
def prepare_browser() -> webdriver:
# Initializing Chrome options
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Chrome(options= chrome_options)
return driver
def scrape(url: str, driver: webdriver) -> None:
driver.get(url)
print (f"Opened: {driver.current_url}")
try:
WebDriverWait(driver, timeout).until(
expected_conditions.presence_of_element_located((By.CLASS_NAME, 'quote'))
)
# Finding all elements with a class of 'quote' in the page
quotes = driver.find_elements(By.CLASS_NAME, 'quote')
for quote in quotes:
text = quote.find_element(By.CLASS_NAME, 'text').text
print (f'Text: {text}')
author = quote.find_element(By.CLASS_NAME, 'author').text
print (f'Author: {author}')
tags = []
for tag in quote.find_elements(By.CLASS_NAME, 'tag'):
tags.append(tag.text)
print (tags)
output.append({
'author': author,
'text': text,
'tags': tags,
})
try:
elem_next = driver.find_element(By.CLASS_NAME, 'next').find_element(By.TAG_NAME,'a')
next_url = elem_next.get_attribute("href")
scrape(next_url, driver)
except:
print('Next button not found. Quitting.')
except:
print ('Timed out.')
def main() -> None:
driver = prepare_browser()
scrape(url, driver)
driver.quit()
print (output)
# CSV
field_names = ['author', 'text', 'tags']
output_filename = 'quotes.csv'
with open (output_filename, 'w', newline='', encoding='utf-8') as f_out:
writer = csv.DictWriter(f_out, fieldnames = field_names)
writer.writeheader()
writer.writerows(output)
if __name__ == '__main__':
main()