Perguntas sobre o comando Grep - Texto Grep da saída do programa?

Sep 03 2020

Estou tentando extrair informações do arquivo json youtube-dl e grep algumas informações para um arquivo .txt.

Exemplo de saída do youtube-dl ao baixar um vídeo.

[info] Writing video description to: /Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).description
[info] Writing video description metadata as JSON to: /Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).info.json

Meu pensamento

  1. Caminhos de arquivo Grep .json e .description para usá-los em comandos grep futuros.
  2. Execute a versão funcional do script abaixo e ele adiciona o novo texto acima do texto de descrição no arquivo .description.
  3. (Renomeie .description para .txt)

Eu prefiro esse método porque o youtube-dl só é necessário para ser executado uma vez.

Se houver outros comandos universais que funcionam no mac e no Linux como grep, que podem torná-lo simples, não vejo problema em usá-los em vez de grep.


QUESTÕES

  • Como fazer o grep nos caminhos dos arquivos e usá-los em outros comandos descritos abaixo nos exemplos de script?
  • Como executar o script abaixo, mas adicionando todas as informações acima do texto de descrição atual naquele arquivo de texto?
  • Ao obter informações do arquivo json, ele também obtém "antes e depois. Portanto, o nome do vídeo se torna:, "VIDEO NAME"mas VIDEO NAMEsó deseja .
  • Como fazer o grep dos TAGS do arquivo json? Etiquetas semelhante a este no arquivo .json: "tags": ["music", "video", "classic"]. Quer pegar "music", "video", "classic".

Exemplo de script

    txtfile="$GREP_DESCRIPTION_FROM_YOUTUBE-DL_OUTPUT" jsonfile="$GREP_JSON_FROM_YOUTUBE-DL_OUTPUT"

    echo TITLE >> $txtfile grep -o '"title": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile echo CHANNEL >> $txtfile
    grep -o '"uploader": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile echo \ >> $txtfile
    
    echo CHANNEL URL >> $txtfile grep -o '"uploader_url": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile echo UPLOAD DATE >> $txtfile
    grep -o '"upload_date": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile echo \ >> $txtfile
    
    echo TAGS >> $txtfile grep -o '"tags": *"[^"]*"' $jsonfile | grep -o '"[^"]*"$' >> $txtfile
    echo \ >> $txtfile echo URL >> $txtfile
    echo $url >> $txtfile
    echo \ >> $txtfile echo DESCRIPTION >> $txtfile

Respostas

1 Wogol Sep 04 2020 at 10:40

Obrigado Barmer! Isso respondeu a três das minhas quatro perguntas.

O que resta e não consigo descobrir é como obter a localização do arquivo json da saída do youtube-dl, fazê-lo funcionar no script e como criar um arquivo .txt no mesmo diretório, mas terminando com .txt.

Algo assim:

  1. Grep tudo depois [info] Writing video description metadata as JSON to: e isso é/Users/ACCOUNT/Downloads/Rick Astley - Never Gonna Give You Up (Video).info.json
  2. Faça aquilo $jsonfile
  3. Pegue a mesma saída do ponto 1, substitua a extensão (tudo após o último. DOT), por .txt, faça isso $txtfile

Script atualizado com jq

#! /bin/bash

    txtfile="textfile.txt"
    jsonfile="jsonfile.json"

    echo - TITLE - >> $txtfile jq -r '.title' $jsonfile >> $txtfile echo \ >> $txtfile | echo \ >> $txtfile echo - CHANNEL - >> $txtfile
    jq -r '.uploader' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - CHANNEL URL - >> $txtfile jq -r '.uploader_url' $jsonfile >> $txtfile echo \ >> $txtfile | echo \ >> $txtfile echo - UPLOAD DATE - >> $txtfile
    jq -r '.upload_date' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - URL - >> $txtfile jq -r '.webpage_url' $jsonfile >> $txtfile echo \ >> $txtfile | echo \ >> $txtfile echo - TAGS - >> $txtfile
    jq -r -c '.tags' $jsonfile >> $txtfile
    echo \ >> $txtfile | echo \ >> $txtfile
    
    echo - DESCRIPTION - >> $txtfile jq -r '.description' $jsonfile >> $txtfile
1 Reino Sep 04 2020 at 13:01
youtube-dl --help | grep "dump-json"
    -j, --dump-json                  Simulate, quiet but print JSON information.

Com esta opção, não há necessidade de baixar nenhum vídeo. Basta canalizar a saída youtube-dlpara um analisador JSON adequado. Eu recomendaria xidel .

youtube-dl -j https://www.youtube.com/watch?v=dQw4w9WgXcQ | xidel - -se '
  $json/(
    "- TITLE -",
    title,"",
    "- CHANNEL -",
    uploader,"",
    "- CHANNEL URL -",
    uploader_url,"",
    "- UPLOAD DATE -",
    upload_date,"",
    "- URL -",
    webpage_url,"",
    "- TAGS -",
    substring-before(
      substring(serialize-json(tags),2),
      "]"
    ),"",
    "- DESCRIPTION -",
    description
  )
'

Se você já baixou o vídeo e JSON ( --write-info-jsonpresumo), você pode recuperar o nome do arquivo com --get-filename:

youtube-dl --get-filename https://www.youtube.com/watch?v=dQw4w9WgXcQ
Rick Astley - Never Gonna Give You Up (Video)-dQw4w9WgXcQ.mp4

jsonfile=$(youtube-dl --get-filename https://www.youtube.com/watch?v=dQw4w9WgXcQ)

xidel -s "${jsonfile/.mp4/.info}.json" -e ' $json/(
    [...]
  )
' > "${jsonfile/.mp4/.info}.txt"

Saída do comando ou conteúdo de ' Rick Astley - Never Gonna Give You Up (Vídeo) -dQw4w9WgXcQ.info.txt ':

- TITLE -
Rick Astley - Never Gonna Give You Up (Video)

- CHANNEL -
RickAstleyVEVO

- CHANNEL URL -
http://www.youtube.com/user/RickAstleyVEVO

- UPLOAD DATE -
20091024

- URL -
https://www.youtube.com/watch?v=dQw4w9WgXcQ

- TAGS -
"the boys soundtrack", "the boys amazon prime", "Never gonna give you up the boys", "RickAstleyvevo", "vevo", "official", "Rick Roll", "video", "music video", "Rick Astley album", "rick astley official", "single", "album", "together forever", "Never Gonna Give You Up", "Whenever You Need Somebody", "pop", "rickrolled", "WRECK-IT RALPH 2", "Fortnite song Fortnite item shop Fortnite time shop today Fortnite montage", "Fortnite event", "Fortnite dance", "fortnite never gonna give you up"

- DESCRIPTION -
Rick Astley's official music video for "Never Gonna Give You Up" Listen to Rick Astley: https://RickAstley.lnk.to/_listenYD Subscribe to the official Rick As...

Na verdade, não há necessidade de youtube-dlsaber se essas informações são tudo o que você procura . Analisar o código-fonte html seria suficiente.

xidel -s https://www.youtube.com/watch?v=dQw4w9WgXcQ -e '
  "- TITLE -",
  //meta[@itemprop="name"]/@content,"",
  "- CHANNEL -",
  //span[@itemprop="author"]/link/@content,"",
  "- CHANNEL URL -",
  //span[@itemprop="author"]/link/@href,"",
  "- UPLOAD DATE -",
  //meta[@itemprop="datePublished"]/@content,"",
  "- URL -",
  //meta[@property="og:url"]/@content,"",
  "- TAGS -",
  join(
    //meta[@property="og:video:tag"]/outer-html() ! substring-before(
      substring-after(.,"content=")
      ,">"
    ),
    ", "
  ),"",
  "- DESCRIPTION -",
  //meta[@itemprop="description"]/@content
'

O html-source também possui um enorme JSON com todas as informações de que você precisa. É um pouco mais difícil de extrair, mas pode ser feito. Em comparação com as outras duas soluções, esta "fonte" não tem uma descrição de vídeo truncada:

xidel -s https://www.youtube.com/watch?v=dQw4w9WgXcQ -e '
  let $json:=json(
        //script/extract(.,"ytplayer.config = (.+?\});",1)[.]
      )/args,
      $a:=json($json/player_response)/videoDetails,
      $b:=json($json/player_response)/microformat
  return (
    "- TITLE -",
    $a/title,"", "- CHANNEL -", $a/author,"",
    "- CHANNEL URL -",
    $b//ownerProfileUrl,"", "- UPLOAD DATE -", $b//publishDate,"",
    "- URL -",
    $json/loaderUrl,"", "- TAGS -", substring-before( substring(serialize-json($a/keywords),2),
      "]"
    ),"",
    "- DESCRIPTION -",
    $a/shortDescription
  )
'
Wogol Sep 05 2020 at 09:07

Corrigido o problema falado abaixo.

Resolvido adicionando dois "no final do script no final

...
' --printed-json-format=compact >> "$textfile"

Obrigado Reino!


Obrigado. Agora tentei fazê-lo funcionar. Ele me deu alguns erros e começou com algumas soluções de problemas. Ainda sem sorte.

Este teste para ver se funciona. foldere urlvem no início do script e aqui é temporário.

    folder=/Users/ACCOUNT/Downloads/ytdl/
    url=https://www.youtube.com/watch?v=dQw4w9WgXcQ
    textfile=$(youtube-dl --get-filename -o $folder'%(title)s/%(title)s.txt' $url)
    $textfile

O resultado é:

-bash: /Users/ACCOUNT/Downloads/ytdl/Rick: No such file or directory

E se eu criar essa pasta, a saída será

-bash: /Users/ACCOUNT/Downloads/ytdl/Rick: is a directory

Mas se eu testar o script exatamente como acho que deveria ser

youtube-dl --get-filename -o /Users/ACCOUNT/Downloads/ytdl/'%(title)s/%(title)s.txt' https://www.youtube.com/watch?v=dQw4w9WgXcQ

O resultado é:

/Users/ACCOUNT/Downloads/ytdl/Rick Astley - Never Gonna Give You Up (Video)/Rick Astley - Never Gonna Give You Up (Video).txt

Exatamente como deveria ser. O que estou fazendo errado?


Este é o script xidel e como o mudei, $urle >> $textfile. Eu uso este script porque ele obtém a descrição completa.

xidel -s "$url" -e '
  let $json:=json( //script/extract(.,"ytplayer.config = (.+?\});",1)[.] )/args, $a:=json($json/player_response)/videoDetails, $b:=json($json/player_response)/microformat return ( "- TITLE -", $a/title,"",
    "- CHANNEL -",
    $a/author,"", "- CHANNEL URL -", $b//ownerProfileUrl,"",
    "- UPLOAD DATE -",
    $b//publishDate,"", "- URL -", $json/loaderUrl,"",
    "- TAGS -",
    $a/keywords,"", "- DESCRIPTION -", $a/shortDescription
  )
' --printed-json-format=compact >> $textfile