网页内容抓取进阶:解析JavaScript动态加载的数据

网页内容抓取进阶:解析JavaScript动态加载的数据

本教程旨在解决使用BeautifulSoup直接解析HTML元素时,无法获取到通过JavaScript动态加载内容的常见问题。我们将深入探讨当目标文本被嵌入到标签内的JavaScript变量(如window.__INITIAL_STATE__)中时,如何结合使用requests库、正则表达式json模块来准确提取所需数据,并最终利用BeautifulSoup对提取出的HTML片段进行清洗,从而实现更高效、更精准的网页内容抓取。

传统HTML解析的局限性

在进行网页数据抓取时,我们经常会遇到内容无法通过简单的html标签选择器获取的情况。例如,当尝试使用beautifulsoup的find_all(‘p’)方法来提取段落文本时,可能会发现返回的文本为空,或者只获取到不相关的部分,甚至出现nameerror: name ‘text’ is not defined这样的错误。这通常是因为目标内容并非直接存在于页面的静态html结构中,而是通过javascript在页面加载后动态注入的。

以提供的案例为例,尽管页面HTML中存在

标签,但我们真正想要的文章标题和摘要文本并未直接包含在这些可见的

标签内。相反,它们被封装在一个名为window.__INITIAL_STATE__的JavaScript变量中,以JSON格式存储在页面的标签内部。

原始尝试代码示例:

import requests from bs4 import BeautifulSoupURL = "https://habr.com/ru/hubs/gamedev/articles/"page = requests.get(URL).contentsoup = BeautifulSoup(page, "html.parser")post = soup.find("article", class_="tm-articles-list__item")# 这里的discription可能为空或不包含所需内容discription = post.find_all('p')for post_text in discription:    text = post_text.get_text()# 如果discription为空,text变量将不会被定义,导致NameErrorprint(text)

这种方法在面对动态加载内容时会失效,因为BeautifulSoup只能解析requests.get()获取到的原始HTML文本,而不能执行JavaScript来渲染页面。

识别动态加载内容

要判断目标内容是否为动态加载,可以通过以下步骤:

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

  1. 查看页面源代码: 在浏览器中右键点击页面,选择“查看页面源代码”(或“View Page Source”)。搜索你想要抓取的内容,如果找不到,或者只找到一些占位符,那么很可能就是动态加载的。
  2. 检查开发者具的网络请求: 打开浏览器的开发者工具(F12),切换到“网络”(Network)选项卡。刷新页面,观察是否有XHR(XMLHttpRequest)或Fetch请求加载了包含目标数据的新数据。
  3. 检查标签: 在页面源代码中搜索标签,尤其是那些看起来包含大量JSON数据或定义了全局JavaScript变量的脚本块。例如,window.__INITIAL_STATE__就是一个常见的模式,许多现代前端框架(如React、Vue等)会用它来初始化页面状态。

    在我们的案例中,通过检查页面源代码,可以发现文章的标题和摘要信息被封装在window.__INITIAL_STATE__这个JavaScript对象中。

    解决方案:正则表达式与JSON解析

    当内容被嵌入到JavaScript变量中时,我们需要采用一种混合策略:

    1. 使用requests获取页面的原始HTML文本。
    2. 使用正则表达式从HTML文本中提取包含目标数据的JavaScript变量内容。
    3. 将提取出的JavaScript变量内容解析为JSON对象。
    4. 在JSON对象中导航,找到并提取所需的数据。
    5. 如果提取出的数据仍包含HTML标签,可再次使用BeautifulSoup进行清洗。

      步骤一:获取页面原始文本

      首先,我们需要获取完整的页面文本,而不仅仅是BeautifulSoup解析后的DOM结构。requests.get(URL).text可以获取到包含JavaScript代码的原始字符串。

      步骤二:使用正则表达式提取JavaScript变量

      为了从原始文本中精确地提取window.__INITIAL_STATE__变量的值,我们可以使用正则表达式。观察目标变量的结构,它通常以window.__INITIAL_STATE__=开头,并以特定的字符序列(如}}后跟分号)结束。

      import re# ... (其他导入)page = requests.get(URL).text# 使用正则表达式匹配并提取window.__INITIAL_STATE__变量的内容# 注意:(.*)}}; 捕获了从等号后到第一个}};之间的所有内容data_match = re.search(r"window.__INITIAL_STATE__=(.*}});", page)if data_match:    data_str = data_match.group(1)else:    print("未找到 window.__INITIAL_STATE__ 数据。")    exit()

      这里的正则表达式r”window.__INITIAL_STATE__=(.*}});”的含义是:

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 15:18:22
下一篇 2025年12月14日 15:18:34

相关推荐

发表回复

登录后才能评论
关注微信