如何用BeautifulSoup4提取<script>标签中的内容?
问题描述
编写网站解析器时,使用BeautifulSoup4无法获取<script>标签内的俄语文本,输出为空字符串。需要提取91个这类脚本块中的任务文本并存入数据库。
示例HTML结构:
<tr> <td class="egeno"><span>1</span></td> <td class="topicview"> <script> document.write( '(№ 4840) ' ); document.write( changeImageFilePath('На рисунке схема дорог Н-ского района изображена в виде графа, в таблице содержатся сведения о длине этих дорог в километрах. <br/><img src="4840.gif">Так как таблицу и схему рисовали независимо друг от друга, нумерация населённых пунктов в таблице никак не связана с буквенными обозначениями на графе. Известно, что длина дороги ЗЕ равна 15 км. Определите длину дороги БГ. В ответе запишите целое число – длину дороги в километрах.') ); </script> </td> </tr> <tr> <td class="egeno"><span>1</span></td> <td class="topicview"> <script> document.write( '(№ 4839) ' ); document.write( changeImageFilePath('На рисунке схема дорог Н-ского района изображена в виде графа, в таблице содержатся сведения о длине этих дорог в километрах. <br/><img src="4839.gif">Так как таблицу и схему рисовали независимо друг от друга, нумерация населённых пунктов в таблице никак не связана с буквенными обозначениями на графе. Известно, что длина дороги ЗЕ равна 15 км. Определите длину дороги БГ. В ответе запишите целое число – длину дороги в километрах.') ); </script> </td> </tr>
现有代码:
import requests from bs4 import BeautifulSoup import os, sqlite3 import re import json i = 1 task1_hrefs = soup.find_all(class_='topicview') print(task1_hrefs) for task in task1_hrefs: task_text = task.text print(i, "", f"{task_text}")
解决方案
问题出在.text属性会返回标签渲染后的文本内容,而<script>标签的内容是JavaScript代码,不会被BeautifulSoup渲染,所以需要直接提取脚本的原始内容,再用正则匹配目标文本。
修改后的代码
import requests from bs4 import BeautifulSoup import re import sqlite3 # 假设已完成页面请求与解析 # response = requests.get('目标URL') # soup = BeautifulSoup(response.text, 'html.parser') task_containers = soup.find_all(class_='topicview') # 初始化数据库连接 conn = sqlite3.connect('tasks.db') cursor = conn.cursor() # 创建任务表(不存在则创建) cursor.execute('''CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, task_content TEXT)''') for idx, container in enumerate(task_containers, 1): # 定位当前容器内的<script>标签 script_tag = container.find('script') if not script_tag or not script_tag.string: continue # 获取脚本的原始文本内容 script_content = script_tag.string.strip() # 提取任务编号 number_pattern = re.compile(r'document\.write\(\s*\'\(№ (\d+)\)\s*\'\s*\);') number_match = number_pattern.search(script_content) # 提取俄文任务文本(匹配changeImageFilePath括号内的内容,支持多行) text_pattern = re.compile(r'changeImageFilePath\(\s*\'(.*?)\'\s*\);', re.DOTALL) text_match = text_pattern.search(script_content) if number_match and text_match: task_number = number_match.group(1) raw_text = text_match.group(1) # 清理HTML标签与实体,优化文本格式 cleaned_text = raw_text.replace('<br/>', '\n').replace('"', '"') full_task = f"(№ {task_number}) {cleaned_text}" print(idx, full_task) # 将任务文本存入数据库 cursor.execute('INSERT INTO tasks (task_content) VALUES (?)', (full_task,)) # 提交数据库操作并关闭连接 conn.commit() conn.close()
关键说明
- 提取脚本内容:使用
script_tag.string获取<script>标签内的原始代码(若脚本包含多个文本节点,可改用''.join(script_tag.strings))。 - 正则匹配:
- 用正则提取
document.write中的任务编号 - 启用
re.DOTALL参数,让正则表达式的.匹配换行符,适配多行的任务文本
- 用正则提取
- 文本清理:替换HTML标签(如
<br/>)和实体(如"),让文本更易读 - 数据库存储:通过SQLite3将处理后的文本批量存入数据库,确保数据持久化
内容的提问来源于stack exchange,提问作者Cocos
相关产品推荐
相关产品推荐

