генерировать ссылки страниц с добавочной переменной

рассмотрим ссылки

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

здесь «страница» увеличивается, если есть 115 страниц, тогда значение страницы будет 115 для последней страницы

Как узнать, какая часть ссылки увеличивается, обрабатывая 2 примера ссылок?

Мне нужно сгенерировать все 115 ссылок, используя сценарий оболочки.

Входы будут состоять из 2 ссылок на стр. 2 и стр. 3 и общего количества страниц.

Я нахожусь на оболочке bash, возможно также python

3 Solutions collect form web for “генерировать ссылки страниц с добавочной переменной”

В Python вы можете использовать SequenceMatcher из 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() вернет список троек формы (i, j, n) , где a[i:i+n] == b[j:j+n] . Используя первые два таких троек, мы строим префикс и суффикс URL-адреса, окружающего номер страницы, и повторяем диапазон URL-адресов.

Вот сценарий Perl, чтобы показать, как это возможно, используя побитовый эксклюзивный или Perl-оператор Perl ( ^ ).

Сценарий

Я назвал его 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 =~ /[^\0]/g) { $posOfDiff = $-[0]; } for (my $idx = 1; $idx <= $np; $idx++) { my $newStr = $s1; substr($newStr,$posOfDiff,1) = $idx; print "$newStr\n"; } 

Детали

Уникальной особенностью этого скрипта является использование оператора Perl ( ^ ). Сила этого подхода находится в этом фрагменте кода:

 my $mask = $s1 ^ $s2; while ($mask =~ /[^\0]/g) { $posOfDiff = $-[0]; } 

Вышеизложенное создаст маску ( $mask ), используя 2 строки. Маска XOR – это вектор, который будет содержать 0 для значений, которые соответствуют между $s1 и $s2 , и 1, где они отличаются. Вы можете добавить эту строку кода, если хотите убедиться в этом:

 my $mask = $s1 ^ $s2; printf "[$_] is 0x%02x\n", ord($_) for split //, $mask; 

Интарды маски

Этот printf будет выдавать результат следующим образом. ПРИМЕЧАНИЕ: что символы непечатаемы, это шестнадцатеричные значения. 0x00 – это шестнадцатеричное значение для нулевого символа, 0x01 – 1.

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

Значение возвращается, когда ничего, кроме 0, означает, что значения различны. Другие примеры:

 $ 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 

Прокрутка маски

Другая интересная особенность цикла while заключается в том, что он пропускает только символы $mask , которые не являются нулями ( \0 ). Таким образом, в вашем примере мы фактически выполняем цикл while 1 раз, так как существует только 1 разница между двумя строками. Если бы было 2 отличия, они выполнялись бы 2 раза. Так что это довольно эффективный способ сделать это.

Если вам нужно более убедительно, вот некоторые дополнительные строки кода, которые вы можете добавить, которые показывают цикл while в действии:

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

Эти строки отображаются только один раз:

 in the loop what we're looking for:58 

Сохранение позиции разницы

Как только совпадение найдено, тело цикла while будет выполняться, и позиция будет записана в переменной $posOfDiff . Как? Красота здесь – использование переменной, $ – [0]. Это даст нам смещение позиции последнего успешного матча.

$ – [0] – это смещение начала последнего успешного совпадения.

Это совпадение происходит в контрольной части цикла while, мы ищем символы в $mask , которые НЕ являются нулевым символом ( \0 ), поэтому наш разностный символ:

 $mask =~ /[^\0]/g 

ПРИМЕЧАНИЕ . Конечный g сообщает функции соответствия в Perl, чтобы сделать это глобально, поэтому он будет продолжать поиск совпадений, пока не исчерпает строку, $mask .

Что еще?

Остальная часть этого скрипта – довольно много шаблонов Perl, не стоит обсуждать дальше.

Рекомендации

  • Быстрый способ найти разницу между двумя строками равной длины в Perl
  • Замена секции фиксированной длины строки в Perl
  • Операторы Perl
  • Re: побитовый оператор xor – массив
  • perlvar – perldoc.perl.org

Не зная ничего о ссылках и предполагая, что изменяется только номер страницы, вот мой подход. Сначала я подумал о diff -e , но, оказывается, он просто создает сценарий замены всей строки, который бесполезен в качестве отправной точки.

Итак, вот чистое решение bash:

 #!/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" 

Он сравнивает две строки в кусках, разбивая один на числа. Просто сохраните его где-нибудь и запустите его – он самодостаточен. Рекурсивная часть существует только в том случае, если изменяющаяся числовая часть не является первой, найденной, как в вашем примере.

Чтобы сгенерировать целый ряд номеров страниц, все это помещается в цикл (принимает три аргумента: url1 url2 pagenumber, как и функция, которую он реализует). Это достаточно быстро, чтобы работать как есть, но переключение строк может быть выполнено только один раз и сохранено в виде пары префикс-суффикс между ними, в которую вы поместите свои итерирующие числа.

  • Вызов wget из make на основе шаблона
  • wget захватывает пустые файлы, которые фактически существуют
  • wget -k не конвертирует все ссылки
  • Ошибка wget -output-document = при наличии символа ~
  • Исключая некоторые php-страницы, но не другие с wget?
  • wget рекурсивный только для файлов, которые передают регулярное выражение
  • Загрузите сразу несколько URL-адресов
  • Как запретить wget загружать списки каталога Apache в разных заказах?
  • Как скачать файлы без полного URL?
  • Загрузите сайт HTTPS только через имя пользователя и пароль с помощью wget?
  • установка dropbox (для просмотра файлов)
  • Linux и Unix - лучшая ОС в мире.