动态网站图片抓取进阶:利用Google CSE API绕过前端渲染限制

动态网站图片抓取进阶:利用Google CSE API绕过前端渲染限制

本教程旨在解决动态加载图片网站(如Dermnet)的爬取难题。当传统爬虫工具(BeautifulSoup、Selenium)因JavaScript动态渲染而失效时,通过浏览器开发者工具深入分析网络请求,直接定位并利用网站后台调用的Google Custom Search API接口,获取结构化的JSON数据,从而高效、精准地提取目标图片信息,并探讨分页处理策略。

传统爬取方法的局限性

在进行网页数据抓取时,开发者通常会首先考虑使用beautifulsoup或selenium等工具。然而,面对现代网站日益复杂的动态加载机制,这些工具可能会遇到瓶颈。

BeautifulSoup的限制: BeautifulSoup是一个强大的HTML/XML解析库,但它只能处理静态HTML内容。对于通过JavaScript在页面加载后动态生成或插入的内容,BeautifulSoup无法执行这些JavaScript代码,因此也无法“看到”这些动态加载的数据。例如,Dermnet网站的图片并非直接嵌入在初始HTML中,而是通过JavaScript调用外部API后才渲染到页面上。Selenium的局限性: Selenium通过模拟真实浏览器行为,可以执行JavaScript并等待页面内容加载。这对于许多动态网站是有效的。然而,在某些情况下,如Dermnet网站,图片数据是通过Google Custom Search API(CSE API)直接获取的JSON数据,然后由前端JavaScript解析并渲染。虽然Selenium最终能看到渲染后的图片,但直接从API获取JSON数据通常更高效、更稳定,并且能提供更结构化的原始数据,避免了从复杂的DOM结构中提取信息的麻烦。此外,运行Selenium需要启动浏览器实例,资源消耗相对较高。

当发现BeautifulSoup无法找到目标元素,或者Selenium虽然能加载页面但效率低下时,就需要考虑更深层次的解决方案。

解决方案:深入分析网络请求

解决动态加载内容爬取问题的关键在于理解其背后的数据加载机制。大多数动态内容都是通过前端JavaScript向后端API发送请求并获取数据。通过浏览器开发者工具,我们可以“窥探”这些幕后的API调用。

1. 开发者工具的应用

打开目标网站(例如Dermnet的搜索结果页),按下F12键或右键点击页面选择“检查”打开开发者工具。导航到“网络 (Network)”标签页。

2. 定位API请求

在“网络”标签页中,重新加载页面或执行触发图片加载的操作(如滚动、点击搜索)。你会看到一系列的网络请求。我们需要仔细观察这些请求,寻找与图片数据相关的API调用。

立即学习“前端免费学习笔记(深入)”;

筛选请求: 可以使用过滤器(例如,按“XHR”或“JS”类型过滤)来缩小范围。识别关键URL: 在Dermnet的案例中,通过观察发现存在一个指向https://cse.google.com/cse/element/v1?的请求。这个URL明显与Google Custom Search Engine相关。检查请求详情: 点击这个请求,查看其“标头 (Headers)”和“响应 (Response)”标签页。请求URL和参数: 在“标头”中,可以找到完整的请求URL及其携带的查询参数。这些参数至关重要,它们定义了搜索的关键词、返回结果的数量、搜索类型(图片)、自定义搜索ID等。例如:q=basal%20cell%20carcinoma%20dermoscopy (查询词), searchtype=image (搜索类型), num=16 (结果数量), cx=015036873904746004277:nz7deehiccq (自定义搜索ID)。响应数据结构: 在“响应”标签页中,你会看到API返回的数据。对于Dermnet,它返回的是一个JSONP(JSON with Padding)格式的字符串,通常以一个回调函数名包裹着JSON对象,例如google.search.cse.api10440({…})。这个JSON对象内部包含一个results字段,其中包含了所有图片的详细信息(如图片URL、标题、缩略图URL等)。

3. 处理分页

在“网络”标签页中,尝试点击网站上的“下一页”按钮或滚动加载更多内容。观察API请求的URL参数如何变化。通常,会有一个参数(如start、page或offset)用于控制分页。例如,如果第一页从start=1开始,每页显示16张图片,那么第二页可能从start=17开始。

实现步骤与示例代码

一旦我们定位了API请求并理解了其参数和响应结构,就可以使用HTTP客户端库(如Python的requests)直接调用API来获取数据。

1. 构建请求URL与参数

根据开发者工具中观察到的信息,构建API请求的URL和参数字典。

import requestsimport jsonimport re # For parsing JSONPdef fetch_dermnet_images_from_api(query_term, start_index=1, num_results=16):    """    从Dermnet网站的Google CSE API抓取图片信息。    :param query_term: 搜索关键词。    :param start_index: 结果的起始索引(用于分页)。    :param num_results: 每页返回结果的数量。    :return: 包含图片信息的列表。    """    base_url = "https://cse.google.com/cse/element/v1"    # 根据网络请求观察到的参数构建    params = {        "rsz": "large",        "num": num_results,        "hl": "en",        "source": "gcsc",        "gss": ".com",        "cselibv": "8e77c7877b8339e2", # 注意: 此参数可能随时间变化,需定期检查        "searchtype": "image",        "cx": "015036873904746004277:nz7deehiccq",        "q": query_term,        "safe": "off",        "start": start_index, # 分页参数        "exp": "csqr,cc,bf",        "callback": "google.search.cse.api10440" # 保持此参数以获取JSONP格式    }    # 模拟浏览器User-Agent,避免被识别为爬虫    headers = {        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124124 Safari/537.36"    }    images_data = []    try:        response = requests.get(base_url, params=params, headers=headers, timeout=10)        response.raise_for_status() # 如果请求失败(HTTP状态码非200),则抛出异常        # 解析JSONP响应        # 响应格式通常为 google.search.cse.apiXXXXX({...JSON_CONTENT...})        jsonp_content = response.text        match = re.search(r'^w+((.*))$', jsonp_content, re.DOTALL)        if match:            json_str = match.group(1)            data = json.loads(json_str)            if "results" in data:                for item in data["results"]:                    if "image" in item:                        images_data.append({                            "title": item.get("title", "No Title"),                            "url": item["image"].get("src", ""),                            "thumbnail_url": item["image"].get("thumbnailSrc", ""),                            "width": item["image"].get("width", 0),                            "height": item["image"].get("height", 0)                        })        else:            print(f"Error: Could not parse JSONP response for query '{query_term}'.")            print(f"Raw response start: {jsonp_content[:200]}...")    except requests.exceptions.RequestException as e:        print(f"Network or HTTP error for query '{query_term}': {e}")    except json.JSONDecodeError as e:        print(f"JSON decoding error for query '{query_term}': {e}")    except Exception as e:        print(f"An unexpected error occurred for query '{query_term}': {e}")    return images_data# 示例用法:if __name__ == "__main__":    search_query = "basal cell carcinoma dermoscopy"    print(f"--- 抓取第一页 '{search_query}' 的图片 ---")    first_page_images = fetch_dermnet_images_from_api(search_query, start_index=1, num_results=16)    if first_page_images:        print(f"第一页共找到 {len(first_page_images)} 张图片。")        for i, img in enumerate(first_page_images[:3]): # 只打印前3张示例            print(f"  {i+1}. 标题: {img['title']}, URL: {img['url']}")    else:        print("未找到第一页图片或发生错误。")    print(f"n--- 抓取第二页 '{search_query}' 的图片 ---")    # 假设每页16张,第二页从索引17开始    second_page_images = fetch_dermnet_images_from_api(search_query, start_index=17, num_results=16)    if second_page_images:        print(f"第二页共找到 {len(second_page_images)} 张图片。")        for i, img in enumerate(second_page_images[:3]): # 只打印前3张示例            print(f"  {i+1}. 标题: {img['title']}, URL: {img['url']}")    else:        print("未找到第二页图片或发生错误。")

2. 代码解释

base_url 和 params: base_url是Google CSE API的端点。params字典包含了所有从开发者工具中观察到的查询参数。q是搜索关键词,start用于控制分页(结果的起始索引),num是每页返回的结果数量。headers: 模拟User-Agent是一个良好的实践,可以减少被网站识别为爬虫的风险。requests.get(): 发送HTTP GET请求到API端点。response.raise_for_status(): 检查HTTP响应状态码,如果不是2xx,则抛出HTTPError。JSONP解析: 由于API返回的是JSONP格式(以函数调用包裹JSON),我们使用正则表达式re.search(r’^w+((.*))$’, jsonp_content, re.DOTALL)来提取括号内的纯JSON字符串,然后使用json.loads()进行解析。数据提取: 解析后的data字典中,results字段是一个列表,包含了每张图片的详细信息。我们遍历这个列表,提取出title、url和thumbnail_url等关键信息。分页处理: 通过循环调用fetch_dermnet_images_from_api函数,并递增start_index参数(例如,start_index = current_page * num_results + 1),即可实现多页数据的抓取。

注意事项

在进行API抓取时,需要考虑以下几点以确保爬虫的稳定性和合规性:

API参数的动态性: 某些API参数(如cselibv、cse_tok)可能是动态生成的或有时效性。如果爬虫突然失效,首先应检查这些参数是否已改变,可能需要重新通过开发者工具获取最新的值。User-Agent: 始终建议在请求中设置User-Agent头,模拟主流浏览器,以降低被服务器识别为爬虫并拒绝访问的风险。频率限制(Rate Limiting): API通常会有调用频率限制。频繁或过快的请求可能导致IP被临时或永久封禁。应加入适当的延迟(time.sleep())并实现重试机制。错误处理: 编写健壮的代码,处理各种可能的错误,如网络连接失败、HTTP错误状态码、JSON解析失败等。robots.txt: 在抓取任何网站之前,请务必检查其robots.txt文件(例如https://dermnetnz.org/robots.txt),了解网站的爬取规则,尊重网站的意愿。法律与道德: 确保您的爬取行为符合当地法律法规,不侵犯版权、隐私权或其他合法权益。对于抓取到的图片,应明确其使用限制,避免未经授权的商业用途。

总结

当传统的网页爬取方法在面对JavaScript动态加载内容的网站时遇到困难,通过深入分析浏览器开发者工具中的网络请求,直接定位并利用网站后端调用的API接口,是一种更高效、更稳定的解决方案。这种方法不仅能绕过前端渲染的复杂性,直接获取结构化的数据,还能更好地处理分页等场景。掌握这一技能,是成为一名高级爬虫工程师的重要一步。

以上就是动态网站图片抓取进阶:利用Google CSE API绕过前端渲染限制的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1522169.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
解决React Hook中TypeScript接口与状态更新的类型不兼容问题
上一篇 2025年12月20日 14:49:12
如何用WebCodecs实现浏览器的硬解码视频播放器?
下一篇 2025年12月20日 14:49:21

相关推荐

  • Java中如何生成测试数据 掌握Faker库

    Java中如何生成测试数据 掌握Faker库Java中如何生成测试数据 掌握Faker库Java中如何生成测试数据 掌握Faker库Java中如何生成测试数据 掌握Faker库

    在java中生成测试数据最方便的方法是使用faker库。1. faker是一个强大的java库,用于生成姓名、地址、电话号码等多种类型的伪造数据;2. 使用时需先在maven或gradle中添加对应依赖;3. 初始化faker实例后,可调用其方法快速生成各类数据;4. 支持自定义生成规则及设置不同l…

    2026年8月26日 用户投稿
    000
  • 如何实现API接口的Token认证机制?

    如何实现api接口的token认证机制?通过以下步骤实现:1. 使用jwt库生成和验证token,包含用户id和过期时间;2. 确保使用https传输token,并安全存储token和密钥;3. 设置合理的token过期时间并引入刷新token机制;4. 优化性能通过缓存token验证结果和使用分布…

    2026年8月26日
    000
  • win10怎么恢复成经典的windows照片查看器_Win10恢复传统照片查看器方法

    可通过注册表文件导入、手动编辑注册表或使用批处理命令三种方法恢复Windows 10中经典的Windows照片查看器功能,操作后右键图片选择该查看器并设为默认即可正常使用。 如果您发现Windows 10系统中默认的图片查看工具不再是您习惯使用的经典Windows照片查看器,可以通过修改系统设置或注…

    2026年8月26日
    000
  • Word怎么设置悬挂缩进_Word段落悬挂缩进排版技巧

    通过标尺拖动、段落对话框设置或修改样式可实现Word中首行左对齐其余行右缩进的悬挂缩进效果,适用于参考文献等排版场景。 如果您在使用Word编辑文档时希望实现段落中首行保持左对齐,而其余行向右缩进的效果,可以通过设置悬挂缩进来实现。这种排版方式常用于参考文献、项目列表等需要突出首行内容的场景。 本文…

    2026年8月26日
    100
  • VSCode字体颜色怎么调_VSCode编辑器语法高亮和主题色自定义教程

    调整VSCode字体颜色需通过修改主题或编辑settings.json文件,核心是利用workbench.colorCustomizations和editor.tokenColorCustomizations配置项,结合Developer: Inspect Editor Tokens and Sco…

    2026年8月26日
    200
  • win8自带截图工具怎么用 win8系统自带截图工具使用技巧

    如果您需要在Windows 8系统中截取屏幕画面,但不确定如何操作,可以使用系统自带的截图工具来完成。以下是多种使用方法和技巧: 本文运行环境:联想ThinkPad T14,Windows 8.1。 一、通过开始菜单启动截图工具 此方法适用于所有用户,通过系统搜索功能定位“截图工具”应用,适合不熟悉…

    2026年8月26日
    000
  • 文件上传与云存储(OSS/COS)集成方案

    要将文件上传与云存储集成,需使用云存储sdk上传文件并考虑安全性、性能优化和错误处理。1)使用阿里云oss或腾讯云cos的sdk上传文件。2)确保数据传输安全,使用https和acl。3)优化大文件上传,使用分片上传方法。4)处理上传错误,实现重试和错误捕获机制。 你想知道如何将文件上传与云存储(如…

    2026年8月26日
    100
  • [cmd]Windows下创建符号链接使用命令mklink

    mklink命令在windows系统中用于创建符号链接,属于cmd的内置命令。我们可以通过打开命令提示符来查看mklink的具体用法和语法说明。首先点击“搜索”图标 12,输入“cmd”或“命令提示符”,然后选择“以管理员身份运行”启动命令行工具。接着输入 mklink 并回车,即可显示该命令的详细…

    2026年8月26日
    000
  • 惠普无线网卡驱动怎么安装 一招解决驱动问题

    惠普无线网卡驱动怎么安装 一招解决驱动问题惠普无线网卡驱动怎么安装 一招解决驱动问题惠普无线网卡驱动怎么安装 一招解决驱动问题惠普无线网卡驱动怎么安装 一招解决驱动问题

    在使用惠普(hp)笔记本电脑时,不少用户会遇到无法连接无线网络的问题,其中最常见的原因就是无线网卡驱动未安装或出现异常。尤其是在重装系统后,驱动丢失的情况更为普遍。那么,该如何安装惠普无线网卡驱动呢?下面将介绍几种简单有效的安装方式。 一、无线网卡驱动是什么? 无线网卡驱动相当于操作系统与无线网卡之…

    2026年8月26日 用户投稿
    000
  • Java中jmap的作用 解析堆转储

    Java中jmap的作用 解析堆转储Java中jmap的作用 解析堆转储Java中jmap的作用 解析堆转储Java中jmap的作用 解析堆转储

    jmap通过命令jmap -dump:live,format=b,file=文件名.hprof 进程id生成堆转储文件,具体步骤为:1.使用jps获取java进程id;2.执行带live参数的jmap命令以仅导出存活对象,减少文件体积;3.通过分析工具如eclipse mat、visualvm或ap…

    2026年8月26日 用户投稿
    000
  • 电脑主机内存频率与时序详解,帮助用户了解内存性能指标及调整方法

    电脑主机内存频率与时序详解,帮助用户了解内存性能指标及调整方法电脑主机内存频率与时序详解,帮助用户了解内存性能指标及调整方法电脑主机内存频率与时序详解,帮助用户了解内存性能指标及调整方法电脑主机内存频率与时序详解,帮助用户了解内存性能指标及调整方法

    内存性能要看频率与时序的平衡。频率决定数据传输速度上限,但实际表现受时序影响,高频内存若时序过松,延迟可能与低频内存相近;选择内存应先看主板支持频率,搭配合适cpu平台,同频选cl值更低的产品;时序以cl值为核心,数值越低延迟越小,游戏场景更受益于低时序,而多任务处理则更依赖高频带来的带宽优势;调整…

    2026年8月26日 用户投稿
    000
  • 如何为Composer插件提供灵活且结构化的配置?使用cweagans/composer-configurable-plugin轻松实现!

    可以通过一下地址学习composer:学习地址 一、 composer插件配置的痛点 想象一下,你正在开发一个很棒的Composer插件,或者在使用一个第三方插件,它需要在不同的项目或部署环境中表现出不同的行为。为了实现这种灵活性,你的插件需要一些配置参数。那么问题来了:这些配置应该放在哪里?如何管…

    用户投稿 2026年8月26日
    000
  • iPhone16如何设置返回导航键

    一、打开设置界面 在手机主屏上找到标有“设置”的应用图标,轻触进入。这里是管理iPhone各项功能的核心区域。 二、进入系统管理菜单 在设置列表中向下滑动,定位到“系统”选项并点击进入。该菜单集中了与设备基础操作相关的配置功能。 三、查找导航功能设置 在“系统”页面中,寻找名为“导航”的功能入口。该…

    2026年8月26日
    000
  • 80 PLUS 认证等级背后的真相:转换效率与纹波测试

    80 PLUS认证衡量电源转换效率,等级越高效率越高,从白牌到钛金牌及新增红宝石标准,要求逐步提升,其中红宝石在50%负载下效率需达96.5%以上;高效率降低能耗与发热,延长硬件寿命。同时,纹波测试评估输出稳定性,+12V纹波应低于120mV,优质电源纹波更低,确保系统稳定运行。高效与低纹波结合,提…

    2026年8月26日
    000
  • win10系统Exploit protection不能更改的解决方法

    在win10系统里,部分用户反馈无法正常调整“exploit protection”的设置,这可能与对比游戏性能有关,特别是在csgo游戏中需要覆盖系统配置时,却遇到了“显示由管理员进行管理”的提示,导致无法修改相关选项。这种情况通常是由用户权限不足引起的。为了解决这个问题,建议切换到具有管理员权限…

    2026年8月26日
    000
  • Java中堆内存和栈内存的区别及内存管理机制

    Java中堆内存和栈内存的区别及内存管理机制Java中堆内存和栈内存的区别及内存管理机制Java中堆内存和栈内存的区别及内存管理机制Java中堆内存和栈内存的区别及内存管理机制

    堆内存用于存储对象实例,栈内存用于方法调用和局部变量。1. 堆内存由垃圾回收器管理,线程共享,生命周期长,适合存储动态分配的对象;2. 栈内存自动管理,线程私有,生命周期短,适合存储局部变量和方法调用帧;3. 区分两者是为了优化内存管理和性能;4. 堆溢出可通过分析内存泄漏、优化代码、增加堆内存等解…

    2026年8月26日 用户投稿
    100
  • 电脑主机启动不起来怎么回事 五种解决方法

    电脑主机启动不起来怎么回事 五种解决方法电脑主机启动不起来怎么回事 五种解决方法电脑主机启动不起来怎么回事 五种解决方法电脑主机启动不起来怎么回事 五种解决方法

    电脑按下电源键后毫无反应或无法正常启动,确实让人感到困扰。那么,电脑主机无法启动的原因究竟是什么?本文将为你梳理常见的故障表现,深入分析可能原因,并提供五种实用的解决方法,助你快速排查问题,恢复电脑正常使用。 一、电脑主机无法启动的常见现象 “无法启动”这一问题在实际中可能表现为多种情况,主要包括:…

    2026年8月26日 用户投稿
    200
  • 如何区分哪些人是Microsoft社区工作人员

    在 Microsoft 的互动平台内,每位员工及合作方的头像旁以及姓名下方都会明确标注对应的徽章标识(如下所示): 版主 – 主导特定社区板块的 Microsoft 官方人员或其授权代表。MVP – 凭借对社区的技术贡献与热情获得认可的 Microsoft 最有价值专家。志愿…

    2026年8月26日
    000
  • Java中反射机制的优缺点及适用场景探讨

    Java中反射机制的优缺点及适用场景探讨Java中反射机制的优缺点及适用场景探讨Java中反射机制的优缺点及适用场景探讨Java中反射机制的优缺点及适用场景探讨

    反射是一种让程序在运行时动态获取类信息并操作类或对象的能力,它使程序能够检查、修改类的结构并调用其方法和属性。优势包括:1. 提供动态性与灵活性;2. 支持框架设计如spring的依赖注入;3. 实现插件系统的动态加载;4. 构建动态代理以执行额外操作;5. 开发通用工具处理各种类型对象。劣势有:1…

    2026年8月26日 用户投稿
    000
  • 系统文件损坏怎么修复 4步搞定

    系统文件损坏怎么修复 4步搞定系统文件损坏怎么修复 4步搞定系统文件损坏怎么修复 4步搞定系统文件损坏怎么修复 4步搞定

    在使用电脑时,系统文件损坏是不少用户经常遇到的困扰。这类问题可能引发程序异常关闭、系统蓝屏,甚至导致系统无法启动。别担心,下面为大家整理了几种实用的修复方式,一起来了解一下吧~ 一、使用系统自带的SFC(系统文件检查器)进行修复 SFC是Windows系统内置的诊断工具,能够自动检测并修复受损的系统…

    2026年8月26日 用户投稿
    000

发表回复

登录后才能评论
关注微信