cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Uncharted

%3CLINGO-SUB%20id%3D%22lingo-sub-400049%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3EYouTube%20API%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-400049%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2FDiscussions%2FExtracting-a-section-of-a-webpage%2Fm-p%2F248774%23U248774%22%20class%3D%22lia-mention-container-editor-message%20lia-img-icon-forum-thread%20lia-fa-icon%20lia-fa-forum%20lia-fa-thread%20lia-fa%22%20target%3D%22_blank%22%3EExtracting%20a%20section%20of%20a%20webpage%3C%2FA%3Ehas%20apparently%20got%20some%20stale%20info%3B%20the%20web%20scraping%20from%20Feb%202020%20no%20longer%20seems%20to%20work%20in%20Jul%202021.%20Well%2C%20that's%20expected%20because%20there%20is%20no%20reason%20why%20YouTube%20can't%20change%20the%20HTML%20that%20formats%20the%20web%20page.%20%3CA%20href%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F7940%22%20target%3D%22_blank%22%3E%40LNitz%3C%2FA%3E%20prompted%20me%20to%20take%20another%20look%20and%20show%20how%20to%20use%20a%20more%20official%20API%20to%20get%20the%20data%20and%20how%20to%20store%20that%20data%20into%20a%20data%20table.%3C%2FP%3E%0A%3CP%3EThe%20comments%20in%20the%20JSL%20will%20point%20you%20to%20a%20page%20where%20you%20can%20get%20an%20API%20key.%20Google%2FYouTube%20use%20the%20key%20to%20restrict%20the%20number%20of%20requests%20you%20can%20make.%20Building%20this%20code%20apparently%20used%20about%20500%2F10%2C000%20of%20my%20daily%20quota.%20I've%20run%20it%20a%20lot.%26nbsp%3B%3CA%20href%3D%22https%3A%2F%2Fconsole.cloud.google.com%2Fapis%2Fdashboard%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3Ehttps%3A%2F%2Fconsole.cloud.google.com%2Fapis%2Fdashboard%3C%2FA%3E%20.%3C%2FP%3E%0A%3CP%3EThe%20original%20question%20was%20about%20getting%20descriptions%20of%20YouTube%20videos%20into%20a%20data%20table.%20The%20answer%20downloaded%20the%20(~500Kbyte)%20web%20page%20HTML%20and%20pattern%20matched%20for%20keywords...that%20seem%20to%20have%20changed%2C%20so%20the%20matching%20no%20longer%20works.%20The%20API%20should%20be%20more%20robust.%20It%20returns%20JSON%20data%2C%20which%20is%20way%20easier%20to%20parse%20than%20HTML.%20Smaller%20too.%20The%20problem%20now%20becomes%20reading%20API%20docs%20to%20figure%20out%20how%20it%20works.%20Fortunately%20most%20questions%20can%20be%20googled.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22Video%20links%2C%20descriptions%2C%20thumbnails.%22%20style%3D%22width%3A%20999px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Video%20links%2C%20descriptions%2C%20thumbnails.%22%20style%3D%22width%3A%20999px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Video%20links%2C%20descriptions%2C%20thumbnails.%22%20style%3D%22width%3A%20999px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Video%20links%2C%20descriptions%2C%20thumbnails.%22%20style%3D%22width%3A%20999px%3B%22%3E%3Cspan%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Video%20links%2C%20descriptions%2C%20thumbnails.%22%20style%3D%22width%3A%20999px%3B%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F34066i7E7AB41F4A7B468E%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22VideoDataTable.PNG%22%20alt%3D%22Video%20links%2C%20descriptions%2C%20thumbnails.%22%20%2F%3E%3Cspan%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVideo%20links%2C%20descriptions%2C%20thumbnails.%3C%2Fspan%3E%3C%2Fspan%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVideo%20links%2C%20descriptions%2C%20thumbnails.%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVideo%20links%2C%20descriptions%2C%20thumbnails.%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVideo%20links%2C%20descriptions%2C%20thumbnails.%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVideo%20links%2C%20descriptions%2C%20thumbnails.%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EJSL%2C%20attached%2C%20also%20adds%20the%20blue%20links%20to%20the%20ID%20column.%3C%2FP%3E%0A%3CP%3EThe%20JSL%20uses%20several%20APIs%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3Echannels%20-%20find%20my%20channel%20and%20my%20channel's%20upload%20list%20ID.%3C%2FLI%3E%0A%3CLI%3EplaylistItems%20-%20the%20upload%20list%20is%20a%20playlist.%20Get%20the%20video%20IDs%20from%20that%20play%20list.%3C%2FLI%3E%0A%3CLI%3Evideos%20-%20get%20information%20about%20a%20video%20using%20its%20ID.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3EYouTube%20video%20IDs%20are%20the%20cryptic%20blue%20link%20values%20in%20the%20picture.%20The%20JSL%20is%20a%20bit%20silly%20because%20the%20information%20being%20stored%20in%20the%20data%20table%20was%20available%20from%20the%20playlistitems%2C%20but%20you%20might%20be%20starting%20with%20video%20IDs%20that%20are%20not%20in%20a%20play%20list.%3C%2FP%3E%0A%3CP%3EThere's%20a%20lot%20more%20to%20the%20API%3B%20pretty%20much%20anything%20you%20can%20do%20from%20the%20web%20interface%20(upload%2C%20delete%2C%20etc)%20can%20be%20done%20through%20the%20API.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EEdit%3A%20%3CA%20href%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F5036%22%20target%3D%22_blank%22%3E%40bryan_boone%3C%2FA%3E%26nbsp%3B%20posted%20more%20info%20in%20%3CA%20href%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2FJMP-Scripts%2FIntegrating-Google-Drive-with-JMP-using-HTTP-Request%2Fm-p%2F545688%23U545688%22%20class%3D%22lia-mention-container-editor-message%20lia-img-icon-tkb-thread%20lia-fa-icon%20lia-fa-tkb%20lia-fa-thread%20lia-fa%22%20target%3D%22_blank%22%3EIntegrating%20Google%20Drive%20with%20JMP%20using%20HTTP%20Request%3C%2FA%3E%26nbsp%3B%20--%20related%20to%20the%20keys%20you%20can%20get%20from%20the%20google%20console.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-400049%22%20slang%3D%22en-US%22%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22API.png%22%20style%3D%22width%3A%20734px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22API.png%22%20style%3D%22width%3A%20734px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22API.png%22%20style%3D%22width%3A%20734px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22API.png%22%20style%3D%22width%3A%20734px%3B%22%3E%3Cspan%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22API.png%22%20style%3D%22width%3A%20734px%3B%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F34067i3FAF23E0986E7AC2%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22API.png%22%20alt%3D%22API.png%22%20%2F%3E%3C%2Fspan%3E%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EUse%20the%20YouTube%20API%20to%20make%20a%20data%20table%20about%20videos.%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-SUB%20id%3D%22lingo-sub-454379%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3ERe%3A%20YouTube%20API%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-454379%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3E%3CP%3EThanks%20%3CA%20href%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F958%22%20target%3D%22_blank%22%3E%40ron_horne%3C%2FA%3E%26nbsp%3B%20!%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-454228%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3ERe%3A%20YouTube%20API%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-454228%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3E%3CP%3Ethank%20you%20very%20much!%20%3CA%20href%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F982%22%20target%3D%22_blank%22%3E%40Craige_Hales%3C%2FA%3E%20%2C%3C%2FP%3E%0A%3CP%3EThis%20is%20very%20useful.%20I%20have%20built%20on%20this%20to%20make%20a%20list%20of%20playlists%20of%20a%20channel%20and%20a%20list%20of%20videos%20in%20these%20playlists.%3C%2FP%3E%0A%3CP%3EThis%20task%20can%20become%20more%20complected%20when%20there%20are%20more%20than%2050%20videos%20in%20a%20playlist%2C%20more%20than%2050%20playlists%2C%20some%20videos%20are%20private%2C%20lack%20a%20description%20or%20all%20sorts%20of%20spanners%20in%20the%20works%20of%20YouTube.%3C%2FP%3E%0A%3CP%3EMy%20script%20addresses%20some%20of%20these%20issues%20and%20more%20in%20an%20attempt%20to%20make%20it%20robust.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%3E%3CCODE%20class%3D%22%20language-jsl%22%3E%0A%2F%2Fcreate%20a%20JMP%20data%20table%20with%20all%20playlists%20of%20https%3A%2F%2Fwww.youtube.com%2Fc%2FJMPSoftwareFromSAS%0A%2F%2F%20this%20script%20produces%202%20data%20tables%3A%0A%2F%2F%201)%20A%20list%20of%20playlists%20on%20a%20channel.%0A%2F%2F%202)%20A%20list%20of%20videos%20from%20all%20the%20playlists.%0A%0ANames%20Default%20To%20Here(%201%20)%3B%0A%2F%2F%20in%20order%20to%20use%20API%20tools%20from%20google%20registration%20is%20required%20and%20an%20API%20key%20is%20needed.%20%0A%2F%2F%20in%20order%20to%20get%20an%20api%20key.%0A%2F%2F%20go%20to%20https%3A%2F%2Fconsole.cloud.google.com%2F%20%0A%2F%2F%20create%20new%20project%20(YouTube%20data%20api%20V3)%20%0A%2F%2F%20create%20crdentials%20-%20YouTube%20data%20api%20V3%20-%20Public%20data.%0A%0A%2F%2F%20Define%20Google%20API%20Key%20directly%20or%20in%20a%20separate%20file%20%0Aapikey%20%3D%20%22aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnoooppp%22%3B%20%2F%2F%20directly%0A%20%0A%20%0A%2F%2F%20Define%20channel%20id%20for%20which%20to%20get%20the%20list%20of%20Playlists%20-%20get%20it%20from%20Youtube%0A%2F%2F%20Open%20(%22https%3A%2F%2Fwww.youtube.com%2Fc%2FJMPSoftwareFromSAS%22)%3B%2F%2F%20JMP%20Software%20From%20SAS%0A%2F%2F%20if%20channel%20id%20is%20not%20explicit%20search%20it%20at%20https%3A%2F%2Fcommentpicker.com%2Fyoutube-channel-id.php%20%0AChannelid%20%3D%20%22UCPOQfD32PLMVdTg-38OwjCA%22%3B%0A%0A%0A%2F%2F%20set%20up%20a%20data%20table%20for%20the%20list%20of%20playlists%20%0Adtplaylists%20%3D%20New%20Table(%20%22JMP%20Software%20From%20SAS%20-%20list%20of%20playlists%22%2C%0A%20New%20Column(%20%22Playlist%20name%22%2C%20Character%2C%20%22Nominal%22%20)%2C%0A%20New%20Column(%20%22Playlist%20description%22%2C%20Character%2C%20%22Nominal%22%20)%2C%0A%20New%20Column(%20%22Playlist%20link%22%2C%20Character%2C%20%22Nominal%22%20)%2C%0A%20New%20Column(%20%22Playlistid%22%2C%20Character%2C%20%22Nominal%22%20)%2C%20%0A%20%0A)%3B%0A%20%0A%0A%2F%2F%20this%20youtube%20api%20query%20brings%20a%20list%20of%20playlists%20from%20the%20channel%20using%20channelid%20and%20apikey%0A%2F%2F%20if%20there%20are%20more%20than%2050%20playlists%20this%20needs%20to%20be%20in%20a%20loop%0Ajsonplaylistslist%20%3D%20Parse%20JSON(%0A%20Open(%20%22https%3A%2F%2Fyoutube.googleapis.com%2Fyoutube%2Fv3%2Fplaylists%3Fpart%3Dsnippet%26amp%3BchannelId%3D%22%20%7C%7C%20Channelid%20%7C%7C%20%22%26amp%3BmaxResults%3D50%26amp%3Bkey%3D%22%20%7C%7C%20apikey%20)%0A)%3B%0A%0Anplaylists%20%3D%20jsonplaylistslist%5B%22pageInfo%22%5D%5B%22totalResults%22%5D%3B%0AShow(%20nplaylists%20)%3B%0A%0Aresultsperpage%20%3D%20N%20Items(%20jsonplaylistslist%5B%22items%22%5D%20)%3B%0AShow(%20resultsperpage%20)%3B%0A%0A%2F%2F%20extract%20the%20title%2C%20description%20and%20id%20of%20each%20list%20into%20the%20data%20table.%0AFor(%20playlistspage%20%3D%201%2C%20playlistspage%20%26lt%3B%3D%20Ceiling(%20nplaylists%20%2F%2050%20)%2C%20playlistspage%2B%2B%2C%20%0A%0A%20For(%20iplaylists%20%3D%201%2C%20iplaylists%20%26lt%3B%3D%20resultsperpage%2C%20iplaylists%2B%2B%2C%0A%20%20dtplaylists%20%26lt%3B%26lt%3B%20add%20rows(%201%20)%3B%0A%20%20dtplaylists%3APlaylist%20name%5BN%20Rows()%5D%20%3D%20jsonplaylistslist%5B%22items%22%5D%5Biplaylists%5D%5B%22snippet%22%5D%5B%22title%22%5D%3B%0A%20%20dtplaylists%3APlaylist%20description%5BN%20Rows()%5D%20%3D%20jsonplaylistslist%5B%22items%22%5D%5Biplaylists%5D%5B%22snippet%22%5D%5B%22description%22%5D%3B%0A%20%20dtplaylists%3APlaylistid%5BN%20Rows()%5D%20%3D%20jsonplaylistslist%5B%22items%22%5D%5Biplaylists%5D%5B%22id%22%5D%3B%0A%20%20dtplaylists%3APlaylist%20link%5BN%20Rows()%5D%20%3D%20%22https%3A%2F%2Fwww.youtube.com%2Fplaylist%3Flist%3D%22%20%7C%7C%20jsonplaylistslist%5B%22items%22%5D%5Biplaylists%5D%5B%22id%22%5D%3B%0A%20%20playlistid%20%3D%20jsonplaylistslist%5B%22items%22%5D%5Biplaylists%5D%5B%22id%22%5D%3B%0A%20)%3B%0A%0A%2F%2F%20inspect%20whether%20the%20list%20is%20complete%20or%20has%20a%20next%20page%20with%20more%20playlists%0A%20jsonplaylistslistkeys%20%3D%20jsonplaylistslist%20%26lt%3B%26lt%3B%20get%20keys%3B%0A%20%2F%2F%20if%20no%20nextPageToken%20exists%20-%20break%20the%20loop%0A%20If(%20Contains(%20jsonplaylistslistkeys%2C%20%22nextPageToken%22%20)%20%3D%3D%200%2C%0A%20%20Break()%0A%20)%3B%0A%20%2F%2F%20if%20nextPageToken%20is%20present%20get%20the%20next%20page%0A%20nextpagetoken%20%3D%20jsonplaylistslist%5B%22nextPageToken%22%5D%3B%0A%20jsonplaylistslist%20%3D%20Parse%20JSON(%0A%20%20Open(%0A%20%20%20%22https%3A%2F%2Fyoutube.googleapis.com%2Fyoutube%2Fv3%2Fplaylists%3Fpart%3Dsnippet%26amp%3BchannelId%3D%22%20%7C%7C%20Channelid%20%7C%7C%20%22%26amp%3BmaxResults%3D50%26amp%3BpageToken%3D%22%20%7C%7C%0A%20%20%20nextpagetoken%20%7C%7C%20%22%26amp%3Bkey%3D%22%20%7C%7C%20apikey%0A%20%20)%0A%20)%3B%0A%20%2F%2F%20set%20the%20number%20of%20internal%20loops%20according%20to%20the%20number%20of%20items.%0A%20resultsperpage%20%3D%20N%20Items(%20jsonplaylistslist%5B%22items%22%5D%20)%3B%0A%20Show(%20resultsperpage%20)%3B%0A%0A)%3B%0A%0A%0A%2F%2F%20set%20up%20a%20data%20table%20to%20host%20the%20videos%20in%20all%20play%20lists%0Adt%20%3D%20New%20Table(%20%22JMP%20Software%20From%20SAS%20-%20YouTube%20Playlist%22%2C%0A%20Set%20Cell%20Height(%20100%20)%2C%20%2F%2F%20make%20cells%20taller%20to%20show%20description%20and%20picture%0A%20New%20Column(%20%22Videoname%22%2C%20Character%2C%20%22Nominal%22%20)%2C%0A%2F%2F%20new%20column%20for%20individual%20video%20tags%0A%20New%20Column(%20%22Tags%22%2C%20Character%2C%20%22Nominal%22%2C%20Set%20Display%20Width(%20150%20)%20)%2C%0A%20New%20Column(%20%22Playlist%20name%22%2C%20Character%2C%20%22Nominal%22%20)%2C%0A%20New%20Column(%20%22Playlist%20description%22%2C%20Character%2C%20%22Nominal%22%20)%2C%0A%20New%20Column(%20%22playlist%20link%22%2C%0A%20%20Character%2C%0A%20%20%22Nominal%22%2C%0A%20%20Set%20Property(%0A%20%20%20%22Event%20Handler%22%2C%0A%20%20%20Event%20Handler(%0A%20%20%20%20Click(JSL%20Quote(Function(%20%7BthisTable%2C%20thisColumn%2C%20iRow%7D%2C%20%7B%20%7D%2C%0AWeb(%20Char(%20thisTable%3AthisColumn%5B%20iRow%20%5D%20)%20)%3B%20%2F%2F%20open%20a%20web%20page%0A)%3B)%20%20%20%20)%2C%0A%20%20%20%20Tip(JSL%20Quote(Function(%20%7BthisTable%2C%20thisColumn%2C%20iRow%7D%2C%20%2F%2F%203%20parameters%0A%7B%20%7D%2C%20%22Open%20%22%20%7C%7C%20Char(%20thisTable%3AthisColumn%5B%20iRow%20%5D%20)%20%7C%7C%20%22%20in%20your%20browser.%22%3B%20%2F%2F%20return%20the%20tool%20tip%20string%0A)%3B%20)%20%20%20%20)%2C%0A%20%20%20%20Color(JSL%20Quote(Function(%20%7BthisTable%2C%20thisColumn%2C%20iRow%7D%2C%20%2F%2F%203%20parameters%0A%7B%20%7D%2C%0ARGBColor(%22link%22)%3B)%3B%0A)%20%20%20%20)%0A%20%20%20)%0A%20%20)%2C%20%0A%0A%20)%2C%0A%20New%20Column(%20%22id%22%2C%0A%20%20Character%2C%0A%20%20%22Nominal%22%2C%0A%20%20Set%20Property(%0A%20%20%20%22Event%20Handler%22%2C%0A%20%20%20Event%20Handler(%20%2F%2F%20use%20the%20column%20properties%20GUI%20to%20create%20this%20code%0A%20%20%20%20Click(JSL%20Quote(Function(%20%7BthisTable%2C%20thisColumn%2C%20ivids%7D%2C%0A%20%20%20%20%20%2F%2F%20add%20the%20youtube%20bit%20to%20the%20link...most%20of%20this%20was%20generated%20by%20the%20GUI%0A%20%20%20%20%20Web(%20Char(%20%22https%3A%2F%2Fyoutu.be%2F%22%7C%7CthisTable%3AthisColumn%5B%20ivids%20%5D%20)%20)%3B%20%0A%20%20%20%20)%3B%20)%20%20%20%20)%2C%0A%20%20%20%20Tip(JSL%20Quote(Function(%20%7BthisTable%2C%20thisColumn%2C%20ivids%7D%2C%20%0A%20%20%20%20%20%22Open%20%22%20%7C%7C%20Char(%20thisTable%3AthisColumn%5B%20ivids%20%5D%20)%20%7C%7C%20%22%20in%20your%20browser.%22%3B%20%0A%20%20%20%20)%3B%20)%20%20%20%20)%2C%0A%20%20%20%20Color(JSL%20Quote(Function(%20%7BthisTable%2C%20thisColumn%2C%20ivids%7D%2C%0A%20%20%20%20%20RGBColor(%22link%22)%3B%0A%20%20%20%20)%3B%20)%20%20%20%20)%0A%20%20%20)%0A%20%20)%2C%20%0A%20)%2C%20%0A%0A%2F%2F%20a%20column%20for%20the%20description%20text%20%20%0A%20New%20Column(%20%22Description%22%2C%20character%2C%20%22Nominal%22%2C%20Set%20Display%20Width(%20350%20)%20)%2C%20%0A%0A%2F%2F%20a%20column%20for%20image%20link%0A%20New%20Column(%20%22Image%22%2C%20Character%2C%20%22Nominal%22%2C%20Set%20Display%20Width(%20150%20)%20)%2C%20%0A%0A)%3B%0A%0A%2F%2F%20Here%20is%20where%20we%20start%20scraping%20the%20data%20per%20video%0A%0A%2F%2F%20this%20first%20youtube%20api%20query%20is%20to%20get%20the%20channel's%20uploads%20playlist%20ID%0A%2F%2F%20Note%3A%20if%20there%20are%20less%20than%2051%20such%20videos%20this%20will%20suffice.%20otherwise%20a%20loop%20is%20required.%0AjsonChannel%20%3D%20Parse%20JSON(%0A%20Open(%20%22https%3A%2F%2Fyoutube.googleapis.com%2Fyoutube%2Fv3%2Fchannels%3Fpart%3Dsnippet%2CcontentDetails%2Cstatistics%26amp%3Bid%3D%22%20%7C%7C%20Channelid%20%7C%7C%20%22%26amp%3Bkey%3D%22%20%7C%7C%20apikey%20)%0A)%3B%0A%0A%2F%2F%20extract%20channel%20description%20for%20later%20use%0Achannel_description%20%3D%20jsonChannel%5B%22items%22%5D%5B1%5D%5B%22snippet%22%5D%5B%22description%22%5D%3B%0AShow(%20channel_description%20)%3B%0A%0AFor(%20ilist%20%3D%201%2C%20ilist%20%26lt%3B%3D%20nplaylists%2C%20ilist%2B%2B%2C%20%0A%2F%2F%20get%20the%20playlists%20one%20by%20one%0A%20currentplaylist%20%3D%20dtplaylists%3APlaylist%20id%5Bilist%5D%3B%0A%0A%2F%2F%20this%20next%20api%20query%20gets%20the%20video%20IDs%20(and%20a%20lot%20of%20other%20info%2C%20which%20will%20be%0A%2F%2F%20re-obtained%20below.%20You%20might%20have%20some%20other%20way%20to%20get%20video%20IDs%2C%20not%20from%20a%20playlist.)%0A%20jsonPlayList%20%3D%20Parse%20JSON(%0A%20%20Open(%20%22https%3A%2F%2Fwww.googleapis.com%2Fyoutube%2Fv3%2FplaylistItems%3Fpart%3Dsnippet%26amp%3BmaxResults%3D50%26amp%3BplaylistId%3D%22%20%7C%7C%20currentplaylist%20%7C%7C%20%22%26amp%3Bkey%3D%22%20%7C%7C%20apikey%20)%0A%20)%3B%0A%0A%2F%2Fextract%20plylist%20length%0A%20playlistlenghth%20%3D%20jsonPlayList%5B%22pageInfo%22%5D%5B%22totalResults%22%5D%3B%0A%20Show(%20playlistlenghth%20)%3B%0A%0A%20For(%20playlistpage%20%3D%201%2C%20playlistpage%20%26lt%3B%3D%20Ceiling(%20playlistlenghth%20%2F%2050%20)%2C%20playlistpage%2B%2B%2C%20%0A%20%0A%2F%2F%20fill%20up%20the%20table%0A%20%20nvids%20%3D%20N%20Items(%20jsonPlayList%5B%22items%22%5D%20)%3B%0A%20%20Show(%20playlistpage%2C%20nvids%20)%3B%0A%20%0A%2F%2F%20i%20presents%20video%20number%0A%20%20For(%20i%20%3D%201%2C%20i%20%26lt%3B%3D%20nvids%2C%20i%20%2B%3D%201%2C%0A%20%20%20dt%20%26lt%3B%26lt%3B%20add%20rows(%201%20)%3B%0A%20%20%20dt%3APlaylist%20name%5BN%20Row()%5D%20%3D%20dtplaylists%3APlaylist%20name%5Bilist%5D%3B%0A%20%20%20dt%3APlaylist%20description%5BN%20Row()%5D%20%3D%20dtplaylists%3APlaylist%20description%5Bilist%5D%3B%0A%20%20%20dt%3Aplaylist%20link%5BN%20Row()%5D%20%3D%20dtplaylists%3APlaylist%20link%5Bilist%5D%3B%0A%20%20%20dt%3Aid%5BN%20Row()%5D%20%3D%20jsonPlayList%5B%22items%22%5D%5Bi%5D%5B%22snippet%22%5D%5B%22resourceId%22%5D%5B%22videoId%22%5D%3B%0A%20%20%20dt%3AVideoname%5BN%20Row()%5D%20%3D%20videotitle%20%3D%20jsonPlayList%5B%22items%22%5D%5Bi%5D%5B%22snippet%22%5D%5B%22title%22%5D%3B%0A%20%20%20Show(%20videotitle%20)%3B%0A%2F%2F%20string%20together%20the%20url%20for%20the%20api%20to%20get%20info%20about%20the%20video%20id%20on%20this%20row%0A%20%20%20json%20%3D%20Open(%20%22https%3A%2F%2Fwww.googleapis.com%2Fyoutube%2Fv3%2Fvideos%3Fid%3D%22%20%7C%7C%20dt%3Aid%5BN%20Row()%5D%20%7C%7C%20%22%26amp%3Bkey%3D%22%20%7C%7C%20apikey%20%7C%7C%20%22%26amp%3Bpart%3Dsnippet%22%20)%3B%0A%0A%2F%2F%20convert%20the%20JSON%20string%20to%20an%20associative%20array%20we%20can%20index%20with%20keys%20to%20extract%20parts%20of%20interest%0A%20%20%20jsonvideo%20%3D%20Parse%20JSON(%20json%20)%3B%20%2F%2F%20make%20associative%20array%0A%0A%20%20%20%2F%2Fextract%20the%20description%20itself%20and%20set%20it%20in%20the%20data%20table%20-%20Private%20vidos%20have%20no%20description...%0A%20%20%20If(%20jsonvideo%5B%22items%22%5D%20!%3D%20%7B%7D%2C%0A%20%20%20%20If(%20Contains(%20jsonvideo%5B%22items%22%5D%5B1%5D%5B%22snippet%22%5D%2C%20%22description%22%20)%20%26gt%3B%200%2C%0A%20%20%20%20%20dt%3ADescription%5BN%20Row()%5D%20%3D%20jsonvideo%5B%22items%22%5D%5B1%5D%5B%22snippet%22%5D%5B%22description%22%5D%2C%0A%20%20%20%20%20dt%3ADescription%5BN%20Row()%5D%20%3D%20%22%22%0A%20%20%20%20)%0A%20%20%20)%3B%20%0A%0A%2F%2F%20use%20the%20%20default%20%2F%20medium%20%2F%20high%20%2F%20maxres%20%2F%20medium%20%2F%20standard%20%20%20thumb%20nail%20url%20to%20fetch%20a%20pic%20via%20open()%0A%20%20%20dt%3AImage%5BN%20Row()%5D%20%3D%20%22https%3A%2F%2Fyoutu.be%2F%22%20%7C%7C%20jsonPlayList%5B%22items%22%5D%5Bi%5D%5B%22snippet%22%5D%5B%22resourceId%22%5D%5B%22videoId%22%5D%3B%0A%0A%2F%2F%20extract%20video%20tags%0A%20%20%20If(%20jsonvideo%5B%22items%22%5D%20!%3D%20%7B%7D%2C%0A%20%20%20%20If(%20Contains(%20jsonvideo%5B%22items%22%5D%5B1%5D%5B%22snippet%22%5D%2C%20%22tags%22%20)%20%26gt%3B%200%2C%0A%20%20%20%20%20dt%3ATags%5BN%20Row()%5D%20%3D%20Substitute(%20Char(%20jsonvideo%5B%22items%22%5D%5B1%5D%5B%22snippet%22%5D%5B%22tags%22%5D%20)%2C%20%22%7B%5C!%22%22%2C%20%22%23%22%2C%20%22%2C%20%22%2C%20%22%2C%20%23%22%2C%20%22%7D%22%2C%20%22%22%2C%20%22%5C!%22%22%2C%20%22%22%20)%2C%0A%20%20%20%20%20dt%3ATags%5BN%20Row()%5D%20%3D%20%22%22%0A%20%20%20%20)%0A%20%20%20)%3B%0A%20%20%20%0A%20%20%20Wait(%200%20)%3B%20%0A%0A%20%20)%3B%0A%0A%0A%0A%2F%2F%20inspect%20whether%20the%20list%20is%20complete%20or%20has%20a%20next%20page%20with%20more%20videos.%0A%20%20playlistkeys%20%3D%20jsonPlayList%20%26lt%3B%26lt%3B%20get%20keys%3B%0A%20%20If(%20Contains(%20playlistkeys%2C%20%22nextPageToken%22%20)%20%3D%3D%200%2C%0A%20%20%20Break()%0A%20%20)%3B%0A%20%0A%20%20nextPage%20%3D%20jsonPlayList%5B%22nextPageToken%22%5D%3B%0A%20%20jsonPlayList%20%3D%20Parse%20JSON(%0A%20%20%20Open(%0A%20%20%20%20%22https%3A%2F%2Fwww.googleapis.com%2Fyoutube%2Fv3%2FplaylistItems%3Fpart%3Dsnippet%26amp%3BmaxResults%3D50%26amp%3BpageToken%3D%22%20%7C%7C%20nextPage%20%7C%7C%20%22%26amp%3BplaylistId%3D%22%20%7C%7C%0A%20%20%20%20currentplaylist%20%7C%7C%20%22%26amp%3Bkey%3D%22%20%7C%7C%20apikey%0A%20%20%20)%0A%20%20)%3B%0A%0A%20)%3B%0A%0A)%3B%0A%0Adt%20%26lt%3B%26lt%3B%20Optimize%20Display%3B%0A%0A%0A%3C%2FCODE%3E%3C%2FPRE%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-400300%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3ERe%3A%20YouTube%20API%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-400300%22%20slang%3D%22en-US%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%20mode%3D%22NONE%22%3E%3CP%3EYou%20can%20also%20search%20by%20channel%20name%2C%20rather%20than%20ID%3A%3C%2FP%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22Veritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%22%20style%3D%22width%3A%20999px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Veritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%22%20style%3D%22width%3A%20999px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Veritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%22%20style%3D%22width%3A%20999px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Veritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%22%20style%3D%22width%3A%20999px%3B%22%3E%3Cspan%20class%3D%22lia-inline-image-display-wrapper%22%20image-alt%3D%22Veritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%22%20style%3D%22width%3A%20999px%3B%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fcommunity.jmp.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F34106iD3F347CCA3C89944%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22capture2.png%22%20alt%3D%22Veritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%22%20%2F%3E%3Cspan%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVeritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%3C%2Fspan%3E%3C%2Fspan%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVeritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVeritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVeritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EVeritasium%20uses%201Veritasium%20for%20the%20actual%20channel%20name.%20There%20is%20a%20re-direct%20easter%20egg%20at%20the%20other%20one.%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20999px%3B%22%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E
Choose Language Hide Translation Bar
Craige_Hales
Super User
YouTube API

Extracting a section of a webpagehas apparently got some stale info; the web scraping from Feb 2020 no longer seems to work in Jul 2021. Well, that's expected because there is no reason why YouTube can't change the HTML that formats the web page. @LNitz prompted me to take another look and show how to use a more official API to get the data and how to store that data into a data table.

The comments in the JSL will point you to a page where you can get an API key. Google/YouTube use the key to restrict the number of requests you can make. Building this code apparently used about 500/10,000 of my daily quota. I've run it a lot. https://console.cloud.google.com/apis/dashboard .

The original question was about getting descriptions of YouTube videos into a data table. The answer downloaded the (~500Kbyte) web page HTML and pattern matched for keywords...that seem to have changed, so the matching no longer works. The API should be more robust. It returns JSON data, which is way easier to parse than HTML. Smaller too. The problem now becomes reading API docs to figure out how it works. Fortunately most questions can be googled.

Video links, descriptions, thumbnails.Video links, descriptions, thumbnails.

JSL, attached, also adds the blue links to the ID column.

The JSL uses several APIs:

  • channels - find my channel and my channel's upload list ID.
  • playlistItems - the upload list is a playlist. Get the video IDs from that play list.
  • videos - get information about a video using its ID.

YouTube video IDs are the cryptic blue link values in the picture. The JSL is a bit silly because the information being stored in the data table was available from the playlistitems, but you might be starting with video IDs that are not in a play list.

There's a lot more to the API; pretty much anything you can do from the web interface (upload, delete, etc) can be done through the API.

 

Edit: @bryan_boone  posted more info in Integrating Google Drive with JMP using HTTP Request  -- related to the keys you can get from the google console.

Last Modified: Sep 18, 2022 9:35 PM
Comments