使用Beautiful Soup正确提取网页文本:进阶教程

使用Beautiful Soup正确提取网页文本:进阶教程
最新回答
谁?

2022-11-05 14:03:13

使用Beautiful Soup正确提取网页文本的进阶方法主要针对存储在<script>标签内或动态加载的数据,需结合正则表达式、JSON解析及模拟请求等技术实现高效提取。 以下是具体操作步骤与注意事项:

一、分析网页结构
  1. 定位目标文本存储方式

    直接嵌入HTML标签:如<p>、<div>中的文本可直接用BeautifulSoup.get_text()提取。

    存储在<script>标签内:需通过正则匹配JavaScript变量或JSON对象。

    动态加载内容:需分析AJAX请求的URL及参数,模拟请求获取数据。

  2. 示例:检查<script>标签内容使用浏览器开发者工具(F12)查看网页源代码,搜索关键词(如window.__INITIAL_STATE__)确认数据位置。

二、提取<script>标签中的数据

场景:目标文本存储在JavaScript变量(如JSON对象)中。步骤

  1. 用正则表达式匹配变量内容

    示例代码:import reimport jsonfrom bs4 import BeautifulSouphtml = """<script>window.__INITIAL_STATE__ = {"articles":[{"title":"Example","content":"<p>Text</p>"}]};</script>"""soup = BeautifulSoup(html, 'html.parser')script_tag = soup.find('script', text=re.compile('window.__INITIAL_STATE__'))match = re.search(r'window.__INITIAL_STATE__s*=s*({.*?})s*;', script_tag.string)json_data = json.loads(match.group(1))print(json_data['articles'][0]['title']) # 输出: Example

    关键点

    re.search匹配window.__INITIAL_STATE__ = {...};结构,提取{}内的JSON字符串。

    json.loads()将字符串转为Python字典,便于后续操作。

  2. 处理嵌套HTML文本

    若JSON中包含HTML标签(如<p>),需用BeautifulSoup进一步解析:from bs4 import BeautifulSouphtml_content = json_data['articles'][0]['content']text = BeautifulSoup(html_content, 'html.parser').get_text(separator=' ', strip=True)print(text) # 输出: Text(去除标签后)

三、处理动态加载内容

场景:内容通过AJAX请求动态生成,初始HTML中不存在。步骤

  1. 分析网络请求

    在浏览器开发者工具的Network选项卡中,筛选XHR请求,找到返回目标数据的接口URL。

    记录请求方法(GET/POST)、请求头(如User-Agent、Cookie)及参数。

  2. 模拟请求获取数据

    使用requests库发送请求,解析返回的JSON或HTML:import requestsurl = "

    https://api.example.com/data"
    # 替换为实际AJAX接口headers = { "User-Agent": "Mozilla/5.0", "Referer": "
    https://example.com"
    }response = requests.get(url, headers=headers)data = response.json() # 若返回JSONprint(data['key']) # 根据实际结构提取字段

  3. 处理分页或加密参数

    若请求需分页参数(如page=2)或签名(如token),需通过逆向分析或观察请求规律生成参数。

四、注意事项
  1. 网页结构变化

    网站更新可能导致选择器或正则表达式失效,需定期维护代码。

    建议:使用灵活的选择器(如CSS类名而非绝对路径),或通过异常处理增强鲁棒性。

  2. 反爬虫机制

    常见措施:限制访问频率、验证码、IP封禁。

    应对方法

    设置合理的请求间隔(如time.sleep(2))。

    添加请求头(如User-Agent、Referer)。

    使用代理IP池(如requests.get(url, proxies={"http": "

    http://1.1.1.1"
    }))。

    遵守robots.txt协议(检查目标网站是否允许爬取)。

  3. 数据清洗

    去除多余内容

    使用re.sub删除特殊字符(如n、t):text = re.sub(r's+', ' ', text).strip()

    过滤无关标签(如广告、脚本):for script in soup(['script', 'style', 'noscript']): script.decompose()

  4. 性能优化

    对大规模爬取,建议使用异步请求库(如aiohttp)或分布式框架(如Scrapy)。

    缓存已爬取页面,避免重复请求。

五、完整案例:提取Habr网站文章标题与内容import reimport jsonimport requestsfrom bs4 import BeautifulSoup# 1. 获取页面HTMLurl = "
https://habr.com/ru/hubs/gamedev/articles/"headers
= {"User-Agent": "Mozilla/5.0"}response = requests.get(url, headers=headers)html = response.text# 2. 提取window.__INITIAL_STATE__数据soup = BeautifulSoup(html, 'html.parser')script_tag = soup.find('script', text=re.compile('window.__INITIAL_STATE__'))match = re.search(r'window.__INITIAL_STATE__s*=s*({.*?})s*;', script_tag.string)json_data = json.loads(match.group(1))# 3. 解析文章标题与内容for article in json_data["articlesList"]["articlesList"].values(): title = article["titleHtml"] content_html = article["leadData"]["textHtml"] content_text = BeautifulSoup(content_html, 'html.parser').get_text(separator=' ', strip=True) print(f"标题: {title}n内容: {content_text[:100]}...n") # 仅打印前100字符

关键点

  • 通过正则匹配<script>中的JSON数据,避免直接解析复杂HTML。
  • 使用BeautifulSoup清洗内容中的HTML标签,保留纯文本。
  • 添加请求头模拟浏览器访问,降低被封禁风险。

通过以上方法,可高效提取存储在<script>标签或动态加载的网页文本,同时应对反爬虫与数据清洗挑战。