最近我想把我的油管视频的RSS引入到我的其他网站,比如OurCoders里。这本来应该不难。本来OurCoders的代码里面就包含了magpierss,这是一个古老的PHP RSS解析库,但是一直都可以用。
但是今天发现,magpirerss解析不出来,这是因为Youtube的RSS其实跟规范不完全统一,不够合法。之前即使magpirerss可以解析的时候,有些部分的解析也是不完全对的,我还需要写代码来调整解析后的结果。
今天又解析不出来了,于是我干脆想换一个新的RSS解析器吧,毕竟这个都10多年没更新的,有些Bug也没人解决。于是我找到了rss-php。安装rss-php,很容易,它支持composer。安装方法是:
composer require dg/rss-php
使用方法也很简单:
$rss = Feed::loadRss($url);
echo 'Title: ', $rss->title;
echo 'Description: ', $rss->description;
echo 'Link: ', $rss->url;
foreach ($rss->item as $item) {
echo 'Title: ', $item->title;
echo 'Link: ', $item->url;
echo 'Timestamp: ', $item->timestamp;
echo 'Description ', $item->description;
echo 'HTML encoded content: ', $item->{'content:encoded'};
}
但是可怕的是换了rss-php还是无法解析。我就想干脆单独自己写解析Youtube RSS的代码吧。
下面是YoutubeRSS的例子:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" xmlns:media="http://search.yahoo.com/mrss/" xmlns="http://www.w3.org/2005/Atom">
<link rel="self" href="http://www.youtube.com/feeds/videos.xml?channel_id=UCdhngtoCb1xRmJQqkS5DpfA"/>
<id>yt:channel:dhngtoCb1xRmJQqkS5DpfA</id>
<yt:channelId>dhngtoCb1xRmJQqkS5DpfA</yt:channelId>
<title>Tinyfool的胡说八道</title>
<link rel="alternate" href="https://www.youtube.com/channel/UCdhngtoCb1xRmJQqkS5DpfA"/>
<author>
<name>Tinyfool的胡说八道</name>
<uri>https://www.youtube.com/channel/UCdhngtoCb1xRmJQqkS5DpfA</uri>
</author>
<published>2019-03-26T02:06:01+00:00</published>
<entry>
<id>yt:video:0u_rS0CfhFc</id>
<yt:videoId>0u_rS0CfhFc</yt:videoId>
<yt:channelId>UCdhngtoCb1xRmJQqkS5DpfA</yt:channelId>
<title>军事是不是科技大发展的原动力?老范、徐凯和Tinyfool三人谈</title>
<link rel="alternate" href="https://www.youtube.com/watch?v=0u_rS0CfhFc"/>
<author>
<name>Tinyfool的胡说八道</name>
<uri>https://www.youtube.com/channel/UCdhngtoCb1xRmJQqkS5DpfA</uri>
</author>
<published>2024-01-23T00:40:00+00:00</published>
<updated>2024-01-23T00:40:00+00:00</updated>
<media:group>
<media:title>军事是不是科技大发展的原动力?老范、徐凯和Tinyfool三人谈</media:title>
<media:content url="https://www.youtube.com/v/0u_rS0CfhFc?version=3" type="application/x-shockwave-flash" width="640" height="390"/>
<media:thumbnail url="https://i1.ytimg.com/vi/0u_rS0CfhFc/hqdefault.jpg" width="480" height="360"/>
<media:description>成为此频道的会员即可获享以下福利:
https://www.youtube.com/channel/UCdhngtoCb1xRmJQqkS5DpfA/join
本视频字幕使用TinyStudio生成 https://tinystudio.ai/</media:description>
<media:community>
<media:starRating count="54" average="5.00" min="1" max="5"/>
<media:statistics views="2065"/>
</media:community>
</media:group>
</entry>
<entry>
<id>yt:video:kj8b3sJ_gJE</id>
<yt:videoId>kj8b3sJ_gJE</yt:videoId>
<yt:channelId>UCdhngtoCb1xRmJQqkS5DpfA</yt:channelId>
<title>老范采访我,问我为啥要做游戏</title>
<link rel="alternate" href="https://www.youtube.com/watch?v=kj8b3sJ_gJE"/>
<author>
<name>Tinyfool的胡说八道</name>
<uri>https://www.youtube.com/channel/UCdhngtoCb1xRmJQqkS5DpfA</uri>
</author>
<published>2024-01-21T01:00:20+00:00</published>
<updated>2024-01-21T01:00:20+00:00</updated>
<media:group>
<media:title>老范采访我,问我为啥要做游戏</media:title>
<media:content url="https://www.youtube.com/v/kj8b3sJ_gJE?version=3" type="application/x-shockwave-flash" width="640" height="390"/>
<media:thumbnail url="https://i4.ytimg.com/vi/kj8b3sJ_gJE/hqdefault.jpg" width="480" height="360"/>
<media:description>成为此频道的会员即可获享以下福利:
https://www.youtube.com/channel/UCdhngtoCb1xRmJQqkS5DpfA/join
本视频字幕使用TinyStudio生成 https://tinystudio.ai/</media:description>
<media:community>
<media:starRating count="54" average="5.00" min="1" max="5"/>
<media:statistics views="2452"/>
</media:community>
</media:group>
</entry>
</feed>
但是写起来好麻烦啊。对啊,我们有 ChatGPT,万事不决问ChatGPT,于是我写下了如下的Prompt:
如下的xml,我希望读取每个entry
的id,title,link,published,updated,media:thumbnail,media:description等信息,用PHP如何获得
ChatGPT回复道:
使用SimpleXML扩展可以轻松地解析这样的XML。但请注意,由于XML具有命名空间,因此需要在处理元素和属性时指定它们。以下是如何用SimpleXML读取每个<entry>的id,title,link,published,updated,media:thumbnail,media:description等信息:
<?php
$xmlString = '...'; // 这里放你的原始XML字符串
$xml = simplexml_load_string($xmlString);
$xml->registerXPathNamespace('media', 'http://search.yahoo.com/mrss/');
$xml->registerXPathNamespace('yt', 'http://www.youtube.com/xml/schemas/2015');
foreach ($xml->entry as $entry) {
$id = (string)$entry->id; // 或者使用 $entry->children('yt', true)->videoId
$title = (string)$entry->title;
$link = (string)$entry->link->attributes()->href;
$published = (string)$entry->published;
$updated = (string)$entry->updated;
// 获取媒体信息
$mediaGroup = $entry->children('media', true)->group;
$mediaThumbnail = (string)$mediaGroup->thumbnail->attributes()->url;
$mediaDescription = (string)$mediaGroup->description;
// 输出信息
echo "ID: $id\n";
echo "Title: $title\n";
echo "Link: $link\n";
echo "Published on: $published\n";
echo "Updated on: $updated\n";
echo "Thumbnail: $mediaThumbnail\n";
echo "Description: $mediaDescription\n";
echo "----------------------\n";
}
?>
这段代码首先加载了XML字符串到$xml变量。然后,我们使用registerXPathNamespace()函数来注册XML中使用的命名空间。这对于正确解析media:和yt:前缀的元素至关重要。接着,代码遍历了<entry>标签中的每一个条目,提取和打印了所需的信息。 请注意,由于含有冒号(:)的XML元素属于名称空间,我们需要使用children()方法来访问它们。SimpleXML中的attributes()方法被用于获取元素的属性。 这段代码提供了一个基本的框架,可能需要根据实际XML结构或者特定需求进行适当的调整。同时,确保输入的XML字符串是完整和有效的,这里出于示例缩短了字符串内容。
问题解决了