请求协助调试Kodi插件Python脚本以适配新网站爬取需求
解决不规范HTML结构的Kodi插件爬取问题
碰到标签混乱、完全不按规范来的网站确实头疼——毕竟大部分爬虫教程都是基于清晰的class、id或者层级结构来写的。不过别慌,针对这种野路子网站,我们可以换几种思路来定位元素,再结合你的现有代码调整,就能搞定那4个字段的爬取了。
一、定位不规范HTML元素的核心技巧
先给你几个实用的方法,不管网站结构多乱,总能找到突破口:
- 靠文本内容+标签层级定位:如果元素有固定的文本(比如“播放音频”“第X集”),可以先找到包含这段文本的标签,再通过
find_parent()、find_next_sibling()去拿它附近的目标内容。比如你要找音频链接,先找到写着“收听”的按钮,再找它的父容器里的<a>标签。 - CSS选择器的“硬定位”:BeautifulSoup支持CSS选择器,比如用
select("div > p:nth-of-type(3)")直接选某个div下的第三个p标签,不管它有没有class。这种方法适合结构固定但没有标识的情况。 - 正则匹配属性值:如果目标元素的属性(比如href、src)有规律(比如都包含“episode”或者“.mp3”),可以用正则来筛选,比如
find_all("a", href=re.compile(r"\.mp3$"))就能抓所有音频链接。 - 暴力遍历DOM树:实在没辙的时候,就从根节点开始逐层遍历,比如先抓所有
<div>标签,然后循环每个div,检查里面有没有你要的内容——虽然笨,但对付混乱结构特别有效。
二、结合你的代码修改示例
假设你要爬的4个字段是标题、音频链接、封面图、发布日期,我给你改一下核心的parse_page和build_song_list函数,你可以根据目标网站的实际结构调整细节:
首先,别忘了导入正则模块:
import re
然后重写parse_page函数,这里的选择器都是示例,你需要对照目标网站的HTML结构修改:
def parse_page(page): episodes = {} index = 1 # 先找到所有可能的剧集容器(比如目标网站里每个剧集都在一个无class的div里) for episode_block in page.find_all("div"): # 1. 定位标题:假设标题在h3标签里,文本带“第X集”字样 title_tag = episode_block.find("h3", text=re.compile(r"第\d+集")) if not title_tag: continue # 不是我们要的剧集块,跳过 title = title_tag.get_text(strip=True) # 2. 定位音频链接:找href以.mp3结尾的a标签 audio_link_tag = episode_block.find("a", href=re.compile(r"\.mp3$")) if not audio_link_tag: continue audio_url = audio_link_tag["href"] # 处理相对链接,补全域名 if not audio_url.startswith(("http://", "https://")): audio_url = f"https://目标网站域名{audio_url}" # 3. 定位封面图:找src里包含“cover”的img标签 cover_tag = episode_block.find("img", src=re.compile(r"cover")) cover_url = cover_tag["src"] if cover_tag else "" if cover_url and not cover_url.startswith(("http://", "https://")): cover_url = f"https://目标网站域名{cover_url}" # 4. 定位发布日期:找文本格式为YYYY-MM-DD的span标签 date_tag = episode_block.find("span", text=re.compile(r"\d{4}-\d{2}-\d{2}")) publish_date = date_tag.get_text(strip=True) if date_tag else "" # 把字段存入字典 episodes[index] = { "title": title, "audio_url": audio_url, "cover_url": cover_url, "publish_date": publish_date } index += 1 return episodes
接着调整build_song_list函数,适配新的字段:
def build_song_list(episodes): episode_list = [] for idx in episodes: ep = episodes[idx] # 用标题作为列表项显示文本,封面作为缩略图 li = xbmcgui.ListItem(label=ep['title'], thumbnailImage=ep['cover_url']) li.setProperty('fanart_image', ep['cover_url']) li.setProperty('IsPlayable', 'true') # 可选:把发布日期添加到列表项的信息里,Kodi会显示出来 li.setInfo('music', {'title': ep['title'], 'date': ep['publish_date']}) # 构建播放用的插件链接 url = build_url({'mode': 'stream', 'url': ep['audio_url'], 'title': ep['title']}) episode_list.append((url, li, False)) # 把列表添加到Kodi的目录里 xbmcplugin.addDirectoryItems(addon_handle, episode_list, len(episode_list)) xbmcplugin.setContent(addon_handle, 'episodes') # 改成剧集类型更贴合内容 xbmcplugin.endOfDirectory(addon_handle)
三、调试小技巧
- 保存页面到本地:在
get_page函数里,把请求到的HTML保存成文件,比如:
然后用浏览器打开这个本地文件,右键“检查元素”,慢慢找你要的字段所在的位置,比直接看线上源码方便多了。def get_page(url): response = requests.get(url) with open("target_page.html", "w", encoding="utf-8") as f: f.write(response.text) return BeautifulSoup(response.text, 'html.parser') - 分步测试:先单独运行
parse_page函数,打印每个字段的结果,确认能正确抓取后,再整合到Kodi插件里调试,避免一起出问题不好排查。 - 灵活调整选择器:如果某个标签的位置偶尔变动,别死磕一个选择器,比如可以先抓所有
<a>标签,然后循环检查每个a的href是不是音频链接,总能找到规律。
内容的提问来源于stack exchange,提问作者leopheard
相关产品推荐
相关产品推荐

