gera links de páginas com variável de incremento

6

considere os links

https://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15 https://unix.stackexchange.com/questions/tagged/linux?page=3&sort=newest&pagesize=15 https://unix.stackexchange.com/questions/tagged/linux?page=4&sort=newest&pagesize=15

aqui 'page' está incrementando, se houver 115 páginas, o valor da página será 115 para a última página

Como saber qual parte do link está incrementando processando 2 links de exemplo?

Eu preciso gerar todos os 115 links usando o script de shell.

As entradas serão 2 links da página 2 e página 3 e o número total de páginas.

Eu estou no bash shell, o python também é possível

    
por limovala 24.09.2013 / 11:57

3 respostas

3

Em Python, você pode usar SequenceMatcher de difflib :

#!/usr/bin/env python
import difflib

url1 = "http://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15"
url2 = "http://unix.stackexchange.com/questions/tagged/linux?page=3&sort=newest&pagesize=15"

matcher = difflib.SequenceMatcher(a=url1, b=url2)
matches = matcher.get_matching_blocks()

prefix = url1[:matches[0][2]]
suffix = url2[matches[1][1]:]

for i in range(2, 116):
    print prefix + str(i) + suffix

SequenceMatcher.get_matching_blocks() retornará uma lista de triplos do formulário (i, j, n) , em que a[i:i+n] == b[j:j+n] . Usando os dois primeiros desses triplos, construímos o prefixo e o sufixo do URL que cerca o número da página e iteramos o intervalo de URLs.

    
por 24.09.2013 / 14:25
5

Aqui está um script Perl apenas para mostrar como é possível usar o operador bitwise exclusive ou (XOR) do Perl ( ^ ).

O script

Eu chamei de cmp.pl .

#!/usr/bin/perl -w

use strict;
use warnings;
# $s1 = "http://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15";
# $s2 = "http://unix.stackexchange.com/questions/tagged/linux?page=3&sort=newest&pagesize=15";
# $np = 115

my $s1 = $ARGV[0];
my $s2 = $ARGV[1];
my $np = $ARGV[2];

my $posOfDiff;

my $mask = $s1 ^ $s2;
while ($mask =~ /[^
my $mask = $s1 ^ $s2;
while ($mask =~ /[^
my $mask = $s1 ^ $s2;
printf "[$_] is 0x%02x\n", ord($_) for split //, $mask;
]/g) { $posOfDiff = $-[0]; }
]/g) { $posOfDiff = $-[0]; } for (my $idx = 1; $idx <= $np; $idx++) { my $newStr = $s1; substr($newStr,$posOfDiff,1) = $idx; print "$newStr\n"; }

Detalhes

O recurso exclusivo deste script é o uso do operador Perl ( ^ ). O poder dessa abordagem está neste snippet de código:

...
[] is 0x00
[] is 0x00
[] is 0x00
[] is 0x00
[] is 0x00
[ ] is 0x01
[] is 0x00
[] is 0x00
...

O acima irá criar uma máscara ( $mask ) usando as duas seqüências. Uma máscara XOR é um vetor que conterá um 0 para valores que correspondam entre $s1 e $s2 e um 1 em que eles diferem. Você pode adicionar esta linha de código se quiser se convencer disso:

$ perl -we '$a="ab"; $b="ac"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x01

$ perl -we '$a="ab"; $b="ad"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x06

$ perl -we '$a="ab"; $b="ae"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x07

Innards of mask

Este printf produzirá resultados como este. OBSERVAÇÃO: que os caracteres não podem ser impressos, são valores hexadecimais. O 0x00 é o valor hexadecimal para o caractere nulo, 0x01 é um 1.

while ($mask =~ /[^
in the loop
what we're looking for:58
]/g) { print "in the loop\n"; print "what we're looking for:" . $-[0] . "\n";

O valor que está sendo retornado quando algo diferente de 0 significa que os valores são diferentes. Outros exemplos:

$mask =~ /[^
#!/usr/bin/perl -w

use strict;
use warnings;
# $s1 = "http://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15";
# $s2 = "http://unix.stackexchange.com/questions/tagged/linux?page=3&sort=newest&pagesize=15";
# $np = 115

my $s1 = $ARGV[0];
my $s2 = $ARGV[1];
my $np = $ARGV[2];

my $posOfDiff;

my $mask = $s1 ^ $s2;
while ($mask =~ /[^
my $mask = $s1 ^ $s2;
while ($mask =~ /[^
my $mask = $s1 ^ $s2;
printf "[$_] is 0x%02x\n", ord($_) for split //, $mask;
]/g) { $posOfDiff = $-[0]; }
]/g) { $posOfDiff = $-[0]; } for (my $idx = 1; $idx <= $np; $idx++) { my $newStr = $s1; substr($newStr,$posOfDiff,1) = $idx; print "$newStr\n"; }
]/g

Looping através da máscara

O outro recurso interessante do loop while é que ele percorre apenas os caracteres de $mask que não são nulos ( while ). Então, no seu exemplo, na verdade, estamos apenas executando o loop while 1 vez, já que há apenas uma diferença entre as duas strings. Se houvesse 2 diferenças, executaria 2 vezes. Então, essa é uma maneira bastante eficiente de fazer isso.

Se precisar de mais convincência, veja algumas linhas adicionais de código que podem ser adicionadas que mostram o loop $posOfDiff em ação:

...
[] is 0x00
[] is 0x00
[] is 0x00
[] is 0x00
[] is 0x00
[ ] is 0x01
[] is 0x00
[] is 0x00
...

Estas linhas são exibidas apenas uma vez:

$ perl -we '$a="ab"; $b="ac"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x01

$ perl -we '$a="ab"; $b="ad"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x06

$ perl -we '$a="ab"; $b="ae"; $c=$a ^ $b; printf "[$_] is 0x%02x\n", ord($_) for split //, $c;'
[] is 0x00
[] is 0x07

Salvando a posição da diferença

Quando uma correspondência for encontrada, o corpo do loop while será executado e a posição será registrada na variável while . Como? A beleza aqui é o uso da variável $ - [0]. Isso nos dará o deslocamento da posição da última partida bem sucedida.

$-[0] is the offset of the start of the last successful match.

Esta correspondência é o que está ocorrendo na porção de controle do loop $mask , estamos procurando por caracteres em g que NÃO sejam o caractere nulo ( $mask ), daí nosso caráter de diferença:

while ($mask =~ /[^
in the loop
what we're looking for:58
]/g) { print "in the loop\n"; print "what we're looking for:" . $-[0] . "\n";

OBSERVAÇÃO: O trailing %code% informa a função de correspondência no Perl para fazer isso globalmente, portanto, ele continuará encontrando correspondências até esgotar a string, %code% .

O que mais?

O resto deste script é praticamente clichê Perl, não vale a pena discutir mais.

Referências

por 24.09.2013 / 17:07
3

Sem saber mais nada sobre os links e assumindo apenas o número de páginas, aqui está minha abordagem. Primeiro, pensei em diff -e , mas acabou por criar um script de substituição de linha inteiraed, que é inútil como ponto de partida.

Então aqui está uma solução pura:

#!/bin/bash
url1=${1:-"http://unix.stackexchange.com/questions/tagged/linux?page=2&sort=newest&pagesize=15"} 
url2=${2:-"http://unix.stackexchange.com/questions/tagged/linux?page=34&sort=newest&pagesize=15"}
pagenum=${3:-42}

function splitOnDigit() {
  prefix="${1%%[0-9]*}"
  url1="${1#$prefix}" # remainder if you strip the prefix
  url2="${2#$prefix}"
  suffix1="&${1#*&}" # remainder after the number
  suffix2="&${2#*&}"
  num="${url1%$suffix1}" # the number that we just split around
  if [[ $suffix1 == $1 ]]; then
    # if substitutions failed, we're at the end
    echo "$prefix$3"
    return
  fi

  if [[ $suffix1 == $suffix2 ]]; then
    echo "$prefix$3$suffix1"
  else
    echo -n "$prefix$num"
    splitOnDigit "$suffix1" "$suffix2" "$3"
  fi
}

splitOnDigit "$url1" "$url2" "$pagenum"

Ele compara as duas strings em partes dividindo uma nos números. Basta salvá-lo em algum lugar e executá-lo - é auto-suficiente. A parte recursiva está lá apenas no caso de a parte numérica em mudança não ser a primeira encontrada no seu exemplo.

Para gerar todo um intervalo de números de página, coloque tudo em um loop (recebe três argumentos: url1 url2 pagenumber, da mesma forma que a função implementada). É rápido o suficiente para trabalhar como está, mas o string munging pode ser feito apenas uma vez e salvo como um par de sufixo-prefixo entre o qual você colocaria seus números de iteração.

    
por 24.09.2013 / 14:07