404 aldıktan sonra 'wget'i nasıl durdurursunuz?


12

Küme ayracı genişletmeyi kullanıyorsanız wget, sıralı olarak numaralandırılmış görüntüleri kolaylıkla getirebilirsiniz:

$ wget 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'

Bu numaralandırılmış ilk 10 dosya getirir 90.jpgiçin 99.jpgsadece para cezası, ancak 100.jpgve sonrası bir dönüş 404: Dosya bulunamadı (Sadece sunucuda depolanan 100 fotoğraf var) hatası. {00..200}100 olmayan dosya ile daha geniş bir aralık kullanırsanız, bu varolmayan dosyalar daha çok "sorun" haline gelir , betiğin yürütme süresini artırır ve hatta hafif bir yük (veya en azından rahatsızlık) olabilir sunucu.

wgetİlk 404 hatasını aldıktan sonra durmanın bir yolu var mı ? (veya daha iyisi, üst üste iki, başka bir nedenden dolayı aralıkta eksik bir dosya olması durumunda) Cevabın küme ayracı genişletmesini kullanmasına gerek yoktur; döngüler de iyidir.


1
Gerçek zamanlı bir senaryoda, durumu öğrenmek için her URL'ye basmak isteyebilirsiniz. endeksleri 1, 2 or even n failuresbildiğinizde doğru yol değildir [begin .. end]. İçinde [1..200]yalnızca 100 görüntü olduğunu bildiğinizde aralığı neden belirlersiniz [1..100]? Sanırım parallelsüreci hızlandırmak için eşzamanlı istekler için GNU deneyebilirsiniz .
SparKot

1
@SparKot key Anahtar sunucuda sadece 100 görüntü olduğunu bilmiyorum, ben komut dosyası sonunda nerede olduğunu anlayana kadar dizi mümkün olduğunca çok görüntü indirmek istiyorum.
IQAndreas

Yanıtlar:


9

Bir döngüden memnunsanız:

for url in 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'
do
    wget "$url" || break
done

Bu, wgetgenişlemenizdeki her URL için başarısız olana kadar ve daha sonra breakdöngü dışında çalışır.

Arka arkaya iki arıza istiyorsanız, biraz daha karmaşık hale gelir:

for url in 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'
do
    if wget "$url"
    then
        failed=
    elif [ "$failed" ]
    then
        break
    else
        failed=yes
    fi
done

Bunu biraz yerine &&ve ||yerine küçültebilirsiniz if, ama oldukça çirkinleşir.

Bunu yapmak için wgetyerleşik bir şey olduğuna inanmıyorum .


elifİkinci örneği daha açık hale getirmek için kullanılmasını önerebilir miyim ? Belki böyle bir şey? gist.github.com/IQAndreas/84cae3f0193b67691ff2 ( s'lerithen s ile aynı satıra koymak dahil değil, yalnızca bir ekstra satır ekler if)
IQAndreas

Yeterince adil. Tek satırlık çeviri şimdi o kadar basit değil, ama yine de çok iyi değil.
Michael Homer

9

$?Değişkeni, wget'in dönüş kodunu almak için kullanabilirsiniz . Sıfır değilse, bir hata oluştuğu anlamına gelir ve bir eşik değere ulaşıncaya kadar hesaplarsınız, o zaman döngüden kopabilir.

Kafamın üstünde böyle bir şey

#!/bin/bash

threshold=0
for x in {90..110}; do
    wget 'http://www.iqandreas.com/sample-images/100-100-color/'$x'.jpg'
    wgetreturn=$?
    if [[ $wgetreturn -ne 0 ]]; then
        threshold=$(($threshold+$wgetreturn))
        if [[ $threshold -eq 16 ]]; then
                break
        fi
    fi
done

For döngüsü biraz temizlenebilir, ancak genel fikri anlayabilirsiniz.

Değişen $threshold -eq 16için -eq 24bu döngü içinde iki kez başarısız olursa ancak arka arkaya iki kez olmaz, dinerdi önce 3 kez başarısız olacağını anlamına geleceğini, olurdu.

Bunun 16ve 24kullanılmasının nedeni , dönüş kodlarının toplamıdır.
wget 8, sunucudan gelen bir hataya karşılık gelen bir yanıt kodu aldığında dönüş koduyla yanıt verir ve bu nedenle 162 hatadan sonraki toplam değerdir.

Arızalar yalnızca art arda iki kez meydana geldiğinde wgetdurma, başarılı olduğunda eşiği sıfırlayarak , yani dönüş kodu 0 olduğunda yapılabilir.


Wget dönüş kodlarının bir listesini burada bulabilirsiniz - http://www.gnu.org/software/wget/manual/html_node/Exit-Status.html


2
O cevap çıkarılabilir olmasına rağmen, açıkça bir 404 hata çıkış kodu döndürür işaret etmek isteyebilirsiniz 8, bu nedenle sihirli numaralar arasında 16ve 24.
IQAndreas

1
Cevabımı güncelledim
Lawrence

1
İçin teşekkürler $?! Çok kullanışlı!
neverMind9

2

GNU Parallel ile bu çalışmalıdır:

parallel --halt 1 wget ::: 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'

20140722 sürümünden itibaren neredeyse "arka arkaya iki" olabilir - başarısızlık: --halt 2% işlerin% 2 başarısız olmasına izin verir:

parallel --halt 2% wget ::: 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'

1

IMO, wgetçıkış koduna / durumuna odaklanmak bazı kullanım durumları için çok naif olabilir, bu yüzden bazı ayrıntılı kararlar için HTTP Durum Kodu'nu da dikkate alan bir kod.

wget, komutun -S/--server-responseHTTP Yanıt Üstbilgilerini yazdırmak için kullanabileceğimiz bir bayrak sağlar STDERR.

#!/bin/bash

set -eu

error_max=2
error_count=0

urls=( 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg' )

for url in "${urls[@]}"; do
  set +e
  http_status=$( wget --server-response -c "$url" 2>&1 )
  exit_status=$?
  http_status=$( awk '/HTTP\//{ print $2 }' <<<"$http_status" | tail -n 1 )

  if (( http_status >= 400 )); then
    # Considering only HTTP Status errors
    case "$http_status" in
      # Define your actions for each 4XX Status Code below
      410) : Gone
        ;;
      416) : Requested Range Not Satisfiable
        error_count=0  # Reset error_count in case of `wget -c`
        ;;
      403) : Forbidden
        ;&
      404) : Not Found
        ;&
      *)     (( error_count++ ))
        ;;
    esac
  elif (( http_status >= 300 )); then
     # We're unlikely to reach here in case of 1XX, 3XX in $http_status
     # but ..
     exit_status=0
  elif (( http_status >= 200 )); then
     # 2XX in $http_status considered successful
     exit_status=0
  elif (( exit_status > 0 )); then

    # Where wget's exit status is one of
    # 1   Generic error code.
    # 2   Parse error 
    #     - when parsing command-line options, the .wgetrc or .netrc...
    # 3   File I/O error.
    # 4   Network failure.
    # 5   SSL verification failure.
    # 6   Username/password authentication failure.
    # 7   Protocol errors.

    (( error_count++ ))
  fi

  echo "$url -> http_status: $http_status, exit_status=$exit_status, error_count=$error_count" >&2

  if (( error_count >= error_max )); then
    echo "error_count $error_count >= $error_max, bailing out .." >&2
    exit "$exit_status"
  fi

done

-1

Python'da şunları yapabilirsiniz:

from subprocess import *

def main():
    for i in range(90, 110):
       try :
          url = "url/"+str(i)
          check_output(["wget", url])
       except CalledProcessError:
          print "Wget returned none zero output, quiting"
          sys.exit(0)

Https://docs.python.org/2/library/subprocess.html Daha fazlasını yapmak istiyorsanız, alt işlem belgelerine göz atın.


check_outputEtrafında wgetbir sihir tespit etmedikçe 404- Burada yeterli kontroller olduğuna inanmıyorum ve bu yüzden soruyu gerçekten cevaplamıyor.
shalomb

Öyle, belgeleri okuyun. Çıkışı stdout veya stderr cinsinden kontrol eder. wget
404'ler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.