高级网页抓取策略
介绍
Web Scraping 是一种从网页中提取数据的技术,但采用自动化方式。Web 抓取脚本可以根据需求从多个页面加载和提取数据。从浏览器手动获取数据是一项繁琐的任务,因此最好以自动化方式进行。
本指南将指导您如何处理在进行高级网页抓取时可能遇到的非常规问题和复杂性。本指南将介绍网页抓取的复杂性以及如何解决这些问题。
如果您是使用 Python 进行网页抓取的新手,请查阅我的使用 BeautifulSoup 从 HTML 中提取数据和使用 Python 和 Scrapy 抓取网页的指南。
选择正确的工具
选择正确的工具取决于您正在进行的项目类型,因为 Python 有各种各样的用于网页抓取的库和框架。因此,为您的项目选择最佳工具是您的责任。
我相信了解工具的优缺点有助于为您的项目选择最佳工具,这有助于进行有效的规划,从而可以节省您的前期时间。
Python 以其在网络抓取领域著名且流行的库和框架而闻名。三种最流行的网络抓取工具是:
BeautifulSoup :Beautiful Soup 是一个用于解析 HTML 和 XML 文档的库。Requests (处理 HTTP 会话并发出 HTTP 请求)与BeautifulSoup(解析库)结合使用是小型快速网页抓取的最佳软件包工具。对于更简单、静态、更少 JS 相关复杂性的抓取,这个工具可能就是您正在寻找的。如果您想了解有关 BeautifulSoup 的更多信息,请参阅我之前的使用BeautifulSoup 从 HTML 中提取数据的指南。
lxml是一个高性能、直接、快速且功能丰富的解析库,是BeautifulSoup的另一个突出的替代品。
Scrapy:Scrapy 是一个网络爬虫框架,提供完整的爬虫工具。在 Scrapy 中,我们创建了 Spider,它们是 Python 类,定义如何爬取特定站点/站点的数据。因此,如果您想构建一个强大、并发、可扩展、大规模的爬虫,那么 Scrapy 是您的绝佳选择。此外,Scrapy 还附带了一系列用于 cookie、重定向、会话、缓存等的中间件,可帮助您处理可能遇到的各种复杂情况。如果您想了解有关 Scrapy 的更多信息,请参阅我之前的使用 Python 和 Scrapy 爬取网络的指南。
Selenium对于重度 JS 渲染的页面或非常复杂的网站,Selenium webdriver 是最佳选择。Selenium 是一种自动化网络浏览器的工具,也称为网络驱动程序。有了它,您可以打开 Google Chrome/Mozilla Firefox 自动窗口,访问 URL 并导航到链接。但是,它不如我们迄今为止讨论的工具那么高效。当所有网络抓取的大门都关闭,而您仍然想要重要的数据时,可以使用此工具。如果您想了解有关 Selenium 的更多信息,请参阅使用 Selenium 进行网络抓取。
动态页面或客户端渲染
虽然网站的互动性和用户友好性正在日益增强,但这对网络爬虫却产生了相反的影响。
如今,现代网站使用了大量动态编码实践,这些实践对爬虫来说根本不友好。其中一些示例是延迟图像加载、无限滚动或通过 AJAX 调用加载的元素,这使得即使是 Googlebot 也难以抓取。
现代网站严重依赖 JavaScript 来加载动态元素。
如何知道它是动态页面还是静态页面?
您可以通过查看页面源代码来检测网页是否使用异步加载或是否为动态页面(如果右键单击页面,您将找到选项“查看页面源代码”)。如果在搜索您要查找的内容时找不到它,那么很可能是 Javascript 呈现了该内容。
现代网站都是用 Javascript 渲染的页面,这使得网络抓取工具很难对其进行抓取。
Webdriver 如何处理动态页面?
Selenium WebDriver 是最受欢迎的 Web UI 自动化工具之一。它允许自动执行在 Web 浏览器窗口中执行的操作,例如导航到网站、填写表单(包括处理文本框、单选按钮和下拉菜单)、提交表单、浏览网页、处理弹出窗口等。
让我们举一个像Pluralsight这样的动态网站的例子。在这个例子中,我们将抓取给定关键字可用的课程。
对于 Selenium,您需要从此处下载 Chrome webdriver ,并将 webdriver 放置在 Python 脚本的位置。此外,如果尚未安装selenium Python 包,请安装它。
pip install selenium
获取课程列表的方法是在输入框中输入关键字,然后按 Enter 键(但以自动方式),这将导航到课程列表页面。然后我们可以使用BeautifulSoup来解析内容。代码本身提到了步骤。
因此,脚本如下:
# pluralsight.py
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
def configure_driver():
# Add additional Options to the webdriver
chrome_options = Options()
# add the argument and make the browser Headless.
chrome_options.add_argument("--headless")
# Instantiate the Webdriver: Mention the executable path of the webdriver you have downloaded
# For linux/Mac
# driver = webdriver.Chrome(options = chrome_options)
# For windows
driver = webdriver.Chrome(executable_path="./chromedriver.exe", options = chrome_options)
return driver
def getCourses(driver, search_keyword):
# Step 1: Go to pluralsight.com, category section with selected search keyword
driver.get(f"https://www.pluralsight.com/search?q={search_keyword}&categories=course")
# wait for the element to load
try:
WebDriverWait(driver, 5).until(lambda s: s.find_element_by_id("search-results-category-target").is_displayed())
except TimeoutException:
print("TimeoutException: Element not found")
return None
# Step 2: Create a parse tree of page sources after searching
soup = BeautifulSoup(driver.page_source, "lxml")
# Step 3: Iterate over the search result and fetch the course
for course_page in soup.select("div.search-results-page"):
for course in course_page.select("div.search-result"):
title_selector = "div.search-result__info div.search-result__title a"
author_selector = "div.search-result__details div.search-result__author"
level_selector = "div.search-result__details div.search-result__level"
length_selector = "div.search-result__details div.search-result__length"
print({
"title": course.select_one(title_selector).text,
"author": course.select_one(author_selector).text,
"level": course.select_one(level_selector).text,
"length": course.select_one(length_selector).text,
})
# create the driver object.
driver = configure_driver()
search_keyword = "Web Scraping"
getCourses(driver, search_keyword)
# close the driver.
driver.close()
运行上面的python代码:
python pluralsight.py
您应该获得如下输出:
...
{'title': 'Web Scraping: Python Data Playbook', 'author': 'by Ian Ozsvald', 'level': 'Beginner', 'length': '1h 17m'}
{'title': 'Scraping Dynamic Web Pages with Python and Selenium', 'author': 'by Pratheerth Padman', 'level': 'Advanced', 'length': '1h 7m'}
{'title': 'Extracting Structured Data from the Web Using Scrapy', 'author': 'by Janani Ravi', 'level': 'Beginner', 'length': '1h 52m'}
...
处理 AJAX 加载和无限加载
有时,从动态网站获取内容实际上很简单,因为它们高度依赖于 API 调用。在异步加载中,大多数情况下,数据是通过发出 GET 和 POST 请求来加载的;您可以在开发人员工具的“网络”选项卡中查看这些 API 调用。
在上面的网络选项卡中,您将获得有关请求 URL、所需参数和标头信息的所有信息。
让我们看一个从英超联赛中提取球员信息的示例。确保准确提供标头和其他所需信息。如果您没有正确提供标头和其他信息,那么您可能会收到 HTTP 状态代码401、403等,而不是服务器的200响应
import requests
import json
# API url
url = "https://footballapi.pulselive.com/football/players"
# Headers required for making a GET request
# It is a good practice to provide headers with each request.
headers = {
"content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"DNT": "1",
"Origin": "https://www.premierleague.com",
"Referer": "https://www.premierleague.com/players",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
}
# Query parameters required to make get request
queryParams = {
"pageSize": 32,
"compSeasons": 274,
"altIds": True,
"page": 0,
"type": "player",
"id": -1,
"compSeasonId": 274
}
# Sending the request with url, headers, and query params
response = requests.get(url = url, headers = headers, params = queryParams)
# if response status code is 200 OK, then
if response.status_code == 200:
# load the json data
data = json.loads(response.text)
# print the required data
for player in data["content"]:
print({
"name": player["name"]["display"],
"nationalTeam": player["nationalTeam"]["country"],
"position": player["info"]["positionInfo"]
})
在转到 Selenium WebDriver 选择之前,最好先检查网络选项卡,因为与使用 webdriver 处理相比,调用 API 非常快。
如果它对您不起作用,那么您必须使用 Selenium webdriver。
蜜罐陷阱
一些网站开发人员以链接的形式设置蜜罐陷阱,而这些链接在浏览器上对普通用户是不可见的。设置蜜罐的最简单方法是将 CSS 设置为display: none。由于网络爬虫脚本的运行方式与人类不同,它可以尝试从链接中抓取信息。因此,网站会检测到抓取行为并阻止源 IP 地址。
这种检测并不容易,需要大量的编程工作才能正确完成。
验证
有时我们需要抓取私人数据,这些数据在您通过网站上的身份验证后即可使用。
对于更简单的网站,我们可以使用用户凭据发出POST请求并将其存储在 cookie 中。但是,也可能存在一些问题,例如:
- 隐藏输入:有时您需要提供一些额外的数据,如CSRF_TOKEN以及用户名和密码。
- 附加标头信息:在发出POST请求之前,您可能需要提供一些其他标头。
如果在进行身份验证POST请求时出现任何问题,您可能会收到 HTTP 状态代码401、403等,而不是200。
身份验证处理
对于身份验证,我们可以维护从登录开始就保留的内容的 cookie。我们可以通过创建可以处理此问题的会话来实现这一点。
处理身份验证的最简单方法是使用webdriver。我们可以使用Python 中的Selenium库通过webdriver实现自动化,它可以非常轻松地管理身份验证!
验证码
Captcha 是一种在计算中用来确定用户是否是人类的质询-响应测试,目前它在阻止垃圾邮件发送者方面非常流行。
当您想要抓取数据的页面上存在验证码时,抓取的基本设置将不可避免地失败,因为它无法通过验证码的障碍。要摆脱验证码,您可能需要能够解决验证码的中间件。
Cloudflare等 Web 服务可以防止机器人并提供 DDoS 保护服务,这使得机器人更难执行其任务。
处理重定向和验证码
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~