but how do i choose what i wanna grab? my oh my i’m crap at this.…
what variable do i use? i feel like at the beginning again…
You’ve got a long way, great. I got a basic python book, can’t remember the title, but I guess any would pretty much work.
As you’re finding out, xpath knowledge is very useful.
XPath 教程
http://www.w3schools.com/xpath/default.asp.
Be thankful it’s not regular expressions. The xpath checker, firebug and general web development tools for firefox can also be a godsend when reverse engineering a site or feed.
RSS namespaces can be a pain, but look at the feed-me plugin, it is a good example of how to deal with multiple namespaces when parsing an rss feed.
Jonny
If you can post an example rss URL and tell me what items you want to extract from it, I maybe able to take a look sometime today.
there book feel like advanced grammar explanations to someone who just learned to say “good morning”. :S they look like great tutorials, but no way i’ll find a way through there.
i need it explained in common language rather than
“child::chapter/descendant::para selects the para element descendants of the chapter element children of the context node”
thanks for your help.
i did get as far as creating the menu. and when wanting to select a certain picture subcategory, nothing happens. although the rss url is displayed correctly in the console.
here is an example link:
feed://backend.deviantart.com/rss.xml?q=boost%3Apopular+in%3Aphotography%2Fjournalism%2Fperforming+max_age%3A8h&type=deviation&offset=0
it’s just title, picture, and description.
for now, my console says this:
2/2/11 6:46:39 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] 18:46:39.328769: com.plexapp.plugins.abc : Success!
2/2/11 6:46:40 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] 18:46:40.301275: com.plexapp.plugins.abc : (Framework) Received gzipped response from http://browse.deviantart.com/photography/still/figures/
2/2/11 6:46:40 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] 18:46:40.672758: com.plexapp.plugins.abc : (Framework) Received gzipped response from http://backend.deviantart.com/rss.xml?q=boost%3Apopular+in%3Aphotography%2Fstill%2Ffigures+max_age%3A8h&type=deviation&offset=0
2/2/11 6:46:40 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] 18:46:40.678490: com.plexapp.plugins.abc : (Framework) Response OK
2/2/11 6:46:43 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] 18:46:43.408271: com.plexapp.plugins.abc : (Framework) Saved shared HTTP data
and my code says the following:
####################################################################################################<br />
def ItemPage3(sender, pageUrl):<br />
dir = MediaContainer(title2=sender.itemTitle)<br />
Log("Success!")<br />
pageUrl= pageUrl<br />
dir = MediaContainer(mediaType='items') <br />
content = XML.ElementFromURL(pageUrl, isHTML=True)<br />
image = 0<br />
for item in content.xpath('//link[@type="application/rss+xml"]'):<br />
rssfeed=item.get('href')<br />
content2=XML.ElementFromURL(rssfeed,isHTML=False)<br />
return dir<br />
you think it might be "impressive" for a first day of writing, but to be honest, i didn't write any of this. it's just copy pasting stuff together from different other plugins. i still have no idea what dir = MediaContainer(title2=sender.itemTitle) means. or even what XML is. BUT i did manage (with LOTS of help by harley) to "write" a working menu…
You are doing really well!
FYI, here is a plugin I wrote that uses RSS:
https://github.com/dbl-a/NickJr.bundle/blob/master/Contents/Code/init.py
[size=2][size=“3”][color="#000000"][size=3]
[/size][/size][/color][/size]
I also don't know what mediacpntainer can really do beside put a title I want at the top of a list. That's all I know of it. I've still been able to do what j want by copying a ton of code and logging items to see if I am doing this right. That's programming, at least from my end. Don't underestimate what you've done. You are more than halfway done in what 4 hours. Took me 2 weeks for my first plugin.
A media container is what it’s name says - a container (data structure) for media that the PMS framework knows what to do with. Your job as a plugin writer is to populate those media containers. Consider navigation through the application like a tree with the actual media elements (videos, pictures, etc) as the final leafs, and the intermedidate branch points are DirectoryItem. If you add a DirectoryItem to a media container you create another branch in that tree (a subdirectory sort of). If you add a VideoItem, for example, you’ll get the end leaf.
So, in your example you don’t actually add anything to the media container, that’s why it’s blank. It looks like in your loop you need to add a DirectoryItem with the title, thumb etc. extracted as values from item, much the same way you extract the rss URL. The directory item itself will delegate to a Function (like you already did at the top level menu) and you’ll pass the rssfeed value as a parameter to that function. The function itself will then parse that feed and extract out the actual media items and add them to the media container created and returned by the function.
Jonny
xpath is a language for specifying places in an XML file, which is a tree structure. Start with the simple syntax:
/tag
- will get all nodes named tag at the root of the tree
//tag
- will get all nodes named tag anywhere in the tree
//tag//free
- will find all nodes named free that occur anywhere under nodes named tag, also anywhere in the tree
The
//link[@type="application/rss+xml"]
syntax is a predicate language that allows you the further select the nodes returned. This one says within nodes with tag called link only pick those with an attribute type with the specific value of application/rss+xml.
This is the xpath you’ll use 90% of the time. The rest you can learn later ![]()
Jonny
Well, well, well, just stumbled upon this... Nice to see my name referenced, so I'll return the favor by again acknowledging the great help Jonny and Dbl_A provided me (I might ask for more as I continue learning and expanding my skills ;)
But I feel your pain, Pooploser: I'm a rheumatologist myself. Defended my PhD just when Plex 9 came out and now I'm well into my postdoctoral fellowship. Wife, 1 year old son and house to "maintain" as well ;)
But this is actually fun and so I tend to find the time to do it in between all the other duties... How? Well, right now for example, I'm down with the flu (or something equally annoying) :P I guess this is just life: There's SO much exiting stuff to do, and if you have the continued motivation you'll accomplish all/most of what you desire eventually ;)
Happy coding!
so jonny, you think i should add a mediaType=‘picture’ to the MediaContainer?
thanks very much for those explanations, they help a lot.
and then i have to make it take the info & pic from the RSS. i don’t know which the commands are here though.
writing
for item in content.xpath(’//link[@type=“application/rss+xml”]’):
rssfeed=item.get(‘href’)
will make it find the right rss url. but this is where i am stuck. making it display the images from the rssfeed.
most plugins working with RSS have a “RSS_FEED=” at the top, but i am not sure how to use that in my case, as every subcategory will have its own rss url, i can’t make them all reference the one on top.
it must be something very easy, to make it read the description & pictures from the rss feeds, but i don’t know what i have to write to make it do that.
thanks very much to everyone and i can only fully agree to what MTI wrote 
That just controls the way the media is displayed on the screen. Look at another picture plugin to see what they use.
So, here you are parsing a top level category and these rssfeeds contain the actual pictures, correct? So your navigation would be Category -> Subcategory -> Actual Picutre? Read what I said about the tree, branches etc. above. For each item in this loop you will need to add a DirectoryItem to the MediaContainer. That creates the sub-category branch. You do this the same way you did for the top level branch except the function is refers to will be responsible for parsing the rss feed. You pass the rss feed URL extracted from your category loop as a parameter to that function. In that function you loop through the rss entries and add PhotoItem objects to the media container.
There are many, many examples of plugins doing this, since that's the basic way they are all written.
Jonny
You make it reference the "rssfeed" that you set in your above code.
The RSS_FEED at the top are just constants for the plugin (they don't change). Whereas, your variable "rssfeed" takes on different values.
you are using this line of code elsewhere in your plug:
dir.Append(Function(DirectoryItem(ItemPage3, title), pageUrl = titleUrl))
This line basically tells Plex to "Append" a "DirectoryItem" named "title" on the menu. (the rest says: "when this menu item is selected, run the ItemPage3 function and pass it the value of pageUrl, which in this case is titleUrl.")
follow?
yap, i follow. gracias amigo
what are the words to make it get the title & the picture from the rss page? and where would i put those two?
in that line i wrote above it finds the correct link as we know, where and what exactly do i write to get the pictures visible inside the plugin?
oh and jonny…i’m trying to look at all the other plugins but so far none of them uses the rss reference the same way i’m intending, or at least i can’t see it…
however as a how-to tutorial they are great to look at 
Look at the RssFeedItems function starting on line 318 of the feed-me plugin. It shows how to parse an rss feed whose URL is passed in as a parameter and add the enclosed media items to the media container. It even has a case for PhotoItems. Note that the specific properties you extract may have different names in your feed as photo rss feeds aren’t as standardized as audio and video feeds.
Jonny
i’m trying to use this now:
dir.Append(PhotoItem(media, title=title, subtitle=subtitle, summary=description, thumb=media))
but console gives me this answer:
2/2/11 11:08:19 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] Traceback (most recent call last):
2/2/11 11:08:19 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] File “/Users/Milos/Library/Application Support/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions/1/Python/bootstrap.py”, line 45, in
2/2/11 11:08:19 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] if len(sys.argv) >= 2: PMS.Plugin.__run(sys.argv[-1])
2/2/11 11:08:19 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] File “/Users/Milos/Library/Application Support/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions/1/Python/PMS/Plugin.py”, line 309, in __run
2/2/11 11:08:19 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] import Code as _plugin
2/2/11 11:08:19 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] File “/Users/Milos/Library/Application Support/Plex Media Server/Plug-ins/ABC (US).bundle/Contents/Code/init.py”, line 90
2/2/11 11:08:19 PM [0x0-0x59059].com.plexapp.plexmediaserver[796] dir.Append(PhotoItem(media, title=title, subtitle=subtitle, summary=description, thumb=media))
(i used the ABC bundle and edited from there)
the FULL code so far:
# PMS plugin framework<br />
import re, string, datetime<br />
from PMS import *<br />
<br />
##################################################################################################ABC<br />
PLUGIN_PREFIX = "/photos/deviantart"<br />
<br />
DEVIANTART_URL = "http://www.deviantart.com/"<br />
DEVIANTART_CATEGORIES = "http://www.deviantart.com"<br />
<br />
FEED = "feed"<br />
DEBUG = False<br />
abcart ="art-default.png"<br />
abcthumb ="icon-default.png"<br />
<br />
####################################################################################################<br />
<br />
def Start():<br />
Plugin.AddPrefixHandler(PLUGIN_PREFIX, MainMenu, "Deviant Art","icon-default.jpg", "art-default.jpg")<br />
Plugin.AddViewGroup("InfoList", viewMode="InfoList", mediaType="items")<br />
<br />
MediaContainer.art =R(abcart)<br />
DirectoryItem.thumb =R(abcthumb)<br />
<br />
####################################################################################################<br />
#def MainMenu():<br />
# dir = MediaContainer(mediaType='items') <br />
# dir.Append(Function(DirectoryItem(all_shows, "Categories"), pageUrl = DEVIANTART_CATEGORIES))<br />
# return dir<br />
<br />
####################################################################################################<br />
def MainMenu():<br />
pageUrl= DEVIANTART_CATEGORIES<br />
dir = MediaContainer(mediaType='items')<br />
content = XML.ElementFromURL(pageUrl, True)<br />
Log(content.xpath('//div[@class="sliding-menu "]/ul/li/ul/li/a'))<br />
for item in content.xpath('//div[@class="sliding-menu "]/ul/li/ul/li/a'):<br />
Log(item)<br />
title=item.text <br />
titleUrl = item.get('href') <br />
<br />
Log(title)<br />
Log(titleUrl)<br />
dir.Append(Function(DirectoryItem(ItemPage, title), pageUrl = titleUrl))<br />
return dir<br />
####################################################################################################<br />
def ItemPage(sender, pageUrl):<br />
dir = MediaContainer(title2=sender.itemTitle)<br />
Log("Success!")<br />
pageUrl= pageUrl<br />
dir = MediaContainer(mediaType='items')<br />
content = XML.ElementFromURL(pageUrl, True)<br />
Log(content.xpath('//div[@class="sliding-menu "]/ul/li/ul/li/a'))<br />
for item in content.xpath('//div[@class="sliding-menu "]/ul/li/ul/li/a'):<br />
Log(item)<br />
title=item.text <br />
titleUrl = item.get('href') <br />
<br />
Log(title)<br />
Log(titleUrl)<br />
dir.Append(Function(DirectoryItem(ItemPage2, title), pageUrl = titleUrl))<br />
return dir<br />
####################################################################################################<br />
def ItemPage2(sender, pageUrl):<br />
dir = MediaContainer(title2=sender.itemTitle)<br />
Log("Success!")<br />
pageUrl= pageUrl<br />
dir = MediaContainer(mediaType='items')<br />
content = XML.ElementFromURL(pageUrl, True)<br />
Log(content.xpath('//div[@class="sliding-menu "]/ul/li/ul/li/a'))<br />
for item in content.xpath('//div[@class="sliding-menu "]/ul/li/ul/li/a'):<br />
Log(item)<br />
title=item.text <br />
titleUrl = item.get('href') <br />
<br />
Log(title)<br />
Log(titleUrl)<br />
dir.Append(Function(DirectoryItem(RssFeedItems, title), pageUrl = titleUrl))<br />
return dir<br />
####################################################################################################<br />
def RssFeedItems(sender, pageUrl):<br />
dir = MediaContainer(title2=sender.itemTitle)<br />
Log("Success!")<br />
pageUrl= pageUrl<br />
dir = MediaContainer(mediaType='items') <br />
content = XML.ElementFromURL(pageUrl, isHTML=True)<br />
image = 0<br />
for item in content.xpath('//link[@type="application/rss+xml"]'):<br />
rssfeed = item.get('href')<br />
dir.Append(PhotoItem(rssfeed, title, subtitle=subtitle, summary=description, thumb=media))<br />
return dir<br />
Not sure how many levels there are in your hierarchy but the final level should be something like this. The exact xpath predicates and XML attribute names will depend on your specific feed.
<br />
####################################################################################################<br />
def ItemPage2(sender, pageUrl):<br />
dir = MediaContainer(title2=sender.itemTitle)<br />
Log("Success!")<br />
dir = MediaContainer(mediaType='items')<br />
content = XML.ElementFromURL(pageUrl, True)<br />
Log(content.xpath('//div[@class="sliding-menu "]/ul/li/ul/li/a'))<br />
for item in content.xpath('//link[@type="application/rss+xml"]'):<br />
rssfeed = item.get('href')<br />
title = item.get('title')<br />
dir.Append(Function(DirectoryItem(RssFeedItems, title), pageUrl = rssfeed ))<br />
return dir<br />
####################################################################################################<br />
def RssFeedItems(sender, pageUrl):<br />
dir = MediaContainer(title2=sender.itemTitle)<br />
Log("Success!")<br />
pageUrl= pageUrl<br />
dir = MediaContainer(mediaType='items') <br />
content = XML.ElementFromURL(pageUrl)<br />
for item in content.xpath('//item'):<br />
title = item.get('title')<br />
description= item.get('description')<br />
subtitle= item.get('subtitle')<br />
photoUrl= item.get('photoUrl')<br />
dir.Append(PhotoItem(photoUrl, title, subtitle=subtitle, summary=description))<br />
return dir<br />
that gives me:
2/3/11 12:08:02 AM [0x0-0x16d16d].com.plexapp.plexmediaserver[4075] title = item.get(‘title’)
2/3/11 12:08:02 AM [0x0-0x16d16d].com.plexapp.plexmediaserver[4075] ^
2/3/11 12:08:02 AM [0x0-0x16d16d].com.plexapp.plexmediaserver[4075] IndentationError: unexpected indent