One Manga Downloader v1.5

Updated

อัพเดตสคริปต์อีกรอบ ด้วยความที่รู้สึกว่าใช้แล้วไม่ค่อยได้ดังใจเท่าไหร่ เพราะเวอร์ชันที่ผ่านๆ มาใช้วิธี fetch หน้าเว็บทั้งหน้ามาดื้อๆ แล้วตัดบรรทัดที่ต้องการเพื่อหา URL ทำให้ทำงานช้าถึงช้ามาก เมื่อวันศุกร์เพิ่งค้นพบว่ามันไม่ต้องโหลดมาทั้งหน้าก็ได้ เพราะ cURL มันมี option สำหรับโหลดข้อมูลเฉพาะส่วนที่ต้องการได้ด้วย (man curl แล้วดูตรง option --range)

เมื่อเป็นเช่นนั้นเลยเอาสคริปต์เวอร์ชัน 1.3 มาแก้ตรงส่วนที่เรียก curl โดยใส่ option --range เข้าไป ปรากฏว่าทำงานได้เร็วกว่าเดิมมาก โดยเฉพาะตอนเช็ค chapter ล่าสุด เสร็จแล้วก็เซฟเป็นเวอร์ชัน 1.4

แต่มีอีกอย่างที่ทนใช้มานานเหมือนกัน คือเวลารัน onemanga.sh แบบไม่ใส่ parameter มันจะเช็ค chapter ล่าสุดให้ แล้วถามว่าจะดาวน์โหลดมั้ย ซึ่งจริงๆ มันโง่ไปหน่อย คือควรจะเช็คได้ว่า chapter ล่าสุดที่มีในเครื่องคืออะไร และ chapter ล่าสุดใน onemanga.com คืออะไร แล้วดาวน์โหลดมาให้เองโดยอัตโนมัติ

คิดได้ดังนั้นจึงนั่งแก้สคริปต์ต่อ ได้ออกมาเป็น One Manga Downloader v1.5 ตามนี้ (และเป็นเหตุให้เลขเวอร์ชันข้ามจาก 1.3 มา 1.5 เลย)

#!/bin/bash
 
base_url="http://www.onemanga.com"
base_dir="."
 
if [[ "$1" == "-d" ]]; then
    shift
 
    if [[ ! -d $1 ]]; then
        echo "Directory $1 does not exist. Created."
        mkdir $1
    fi
 
    base_dir=$1
fi
 
cd ${base_dir}
 
manga_name=$1
chapter=$2
last_chapter=$3
display_name=`echo ${manga_name} | sed "s/_/ /g"`
word_count=`echo ${display_name} | wc -w`
sort_key=`echo "${word_count} + 1" | bc`
 
if [[ "${chapter#${chapter%?}}" == "+" ]]; then
    chapter=${chapter%?}
    echo "Start downloading at chapter ${chapter}."
    latest_chapter=`curl -s --range 58000-60000 ${base_url}/${manga_name}/ | grep -i "ch-subject" | grep -v -i "chapter name" | head -1 | awk -F\/ '{print $3}'`
 
    if [[ "${latest_chapter}" == "" ]]; then
        echo "Cannot get the latest chapter of ${display_name} from onemanga.com. Aborted."
        exit
    else
        echo "Latest chapter of ${display_name} on onemanga.com is ${latest_chapter}."
    fi
 
    if [[ `echo "${chapter} <= ${latest_chapter}" | bc` -eq 1 ]]; then
        last_chapter=${latest_chapter}
 
        if [[ `echo "(${latest_chapter} - ${chapter}) > 1" | bc` -eq 1 ]]; then
            echo "The script will download ${display_name} chapter ${chapter}-${last_chapter}."
        fi
    else
        echo "Whoops, something's wrong! The chapter you specified is greater than the latest chapter on onemanga.com!?"
        exit
    fi
fi
 
if [[ "${chapter}" == "" ]]; then
    current_chapter=`ls *${manga_name}_*.cbr 2> /dev/null | sort -r -n -k ${sort_key} -t_ | head -1`
    current_chapter=`echo ${current_chapter##*_} | cut -f1 -d\.`
 
    if [[ "${current_chapter}" == "" ]]; then
        echo "Cannot find any chapter of ${display_name} on local disk. Starting at chapter 1."
        current_chapter=0
    else
        echo "Latest chapter of ${display_name} on local disk is ${current_chapter}."
    fi
 
    latest_chapter=`curl -s --range 58000-60000 ${base_url}/${manga_name}/ | grep -i "ch-subject" | grep -v -i "chapter name" | head -1 | awk -F\/ '{print $3}'`
 
    if [[ "${latest_chapter}" == "" ]]; then
        echo "Cannot get the latest chapter of ${display_name} from onemanga.com. Aborted."
        exit
    else
        echo "Latest chapter of ${display_name} on onemanga.com is ${latest_chapter}."
    fi
 
    if [[ `echo "${current_chapter} == ${latest_chapter}" | bc` -eq 1 ]]; then
        echo "You already have the latest chapter of ${manga_name}."
        exit
    elif [[ `echo "${current_chapter} < ${latest_chapter}" | bc` -eq 1 ]]; then
        chapter=`echo "$current_chapter + 1" | bc`
        last_chapter=${latest_chapter}
 
        if [[ `echo "(${latest_chapter} - ${current_chapter}) > 1" | bc` -eq 1 ]]; then
            echo "The script will download ${display_name} chapter ${chapter}-${last_chapter}."
        fi
    else
        echo "Whoops, something's wrong! The latest chapter on local disk is greater than the latest chapter on onemanga.com!?"
        exit
    fi
fi
 
if [[ "${last_chapter}" == "" ]]; then
    last_chapter=${chapter}
fi
 
while [[ `echo "${chapter} <= ${last_chapter}" | bc` -eq 1 ]]
do
    printf "Downloading ${display_name} chapter ${chapter}\n[>"
 
    next_page_chapter=${chapter}
    page_location=`curl -s --range -1500 ${base_url}/${manga_name}/${chapter}/ | grep -i "begin reading" | awk -F\" '{print $2}'`
 
    while [[ `echo "$next_page_chapter == $chapter" | bc` -eq 1 ]]
    do
        curl -s --range -2000 ${base_url}${page_location} > tmp_page
 
        image_location=`grep "class=\"manga-page\"" < tmp_page | awk -F\" '{print $4}'`
 
        if [[ "$image_location" != "" ]]; then
            printf "\b=>"
            wget -q $image_location
        fi
 
        page_location=`grep "value=\"next page\"" < tmp_page | awk -F\' '{print $2}'`
        next_page_chapter=`echo ${page_location} | cut -d\/ -f3`
    done
 
    cbr_file_name="${manga_name}_${chapter}.cbr"
    printf "\b]\nCreating ${cbr_file_name}... "
    /cygdrive/c/Program\ Files/WinRAR/Rar.exe a -inul ${cbr_file_name} *.jpg
    echo "DONE."
    rm *.jpg
 
    chapter=$next_page_chapter
done
 
rm tmp_page
 
if [[ "${base_dir}" != "." ]]; then
    cd ..
fi

วิธีใช้ก็เหมือนเดิม copy code ข้างบนไปใส่ไฟล์ ตั้งชื่ออะไรก็ได้ (ของผมตั้งเป็น onemanga.sh) แล้วเซ็ต flag ให้ execute ได้ (chmod +x ชื่อไฟล์) เป็นอันเรียบร้อย อ้อ... ถ้าไม่ได้ใช้ WinRAR แบบผม อาจต้องแก้ตรงบรรทัดท้ายๆ (~114) ให้มันทำ archive ด้วยโปรแกรมอื่นแทนนะครับ ไม่งั้นโหลดมาเท่าไหร่ก็โดนลบหมด =.=

คำสั่งในการเรียกใช้งานมีการเปลี่ยนแปลงไปพอสมควร ตามตัวอย่างข้างล่างนี้ กรุณาอ่านก่อนใช้ และสังเกตว่า manga_name คือชื่อ manga ที่อยู่ใน URL ของ onemanga.com

โหลด chapter ที่ต้องการ

onemanga.sh manga_name chapter

ตัวอย่าง:

onemanga.sh Bleach 347

โหลด chapter ในช่วงที่ต้องการ

onemanga.sh manga_name first_chapter last_chapter

ตัวอย่าง:

onemanga.sh Hajime_no_Ippo 841 844

โหลดตั้งแต่ chapter ปัจจุบันในเครื่อง จนถึง chapter ล่าสุด

onemanga.sh manga_name

ตัวอย่าง:

onemanga.sh Naruto

คำสั่งนี้มีความพิเศษนิดหน่อย คือถ้าเคยโหลด chapter ก่อนๆ มาแล้ว (เช่น มีไฟล์ Naruto_435.cbr อยู่ใน directory ที่รันสคริปต์) มันจะเช็คให้ว่าใน onemanga.com ตอนนี้เป็น chapter อะไร (สมมติว่าเป็น 437) แล้วโหลดตั้งแต่ chapter ที่ต่อจากไฟล์ล่าสุดมาให้ ในกรณีนี้ก็จะโหลดตั้งแต่ chapter 436-437 เป็นต้น

แต่ถ้าไม่มีไฟล์อยู่เลย ก็จะโหลดตั้งแต่ chapter 1 จนถึง chapter ล่าสุดมาให้

ทีนี้สมมติอยากได้ตั้งแต่ chapter 300 เป็นต้นไป ก็สามารถเลือกได้ โดยใช้คำสั่ง

โหลดตั้งแต่ chapter ที่กำหนด จนถึง chapter ล่าสุด

onemanga.sh manga_name chapter+

ตัวอย่าง:

onemanga.sh Eyeshield_21 300+

อีกอันเป็นฟีเจอร์ที่น้องที่ทำงาน request มา และผมเห็นว่ามันเวิร์กดี คือปกติเค้าจะเก็บ manga แต่ละเรื่องไว้ใน directory ของใครของมัน โดยตั้งชื่อ directory เหมือนชื่อ manga (เช่น เรื่องบากิ ก็จะอยู่ใน directory Baki_-_Son_of_Ogre/) เลยเพิ่ม option ให้สามารถระบุชื่อ directory แทนชื่อ manga ได้ (จริงๆ มันก็ชื่อเดียวกัน แต่ดาวน์โหลดเสร็จแล้วจะไปเก็บใน directory แทน) โดย option ต่างๆ สามารถใช้ได้เหมือนด้านบน

โหลดมาใส่ directory

onemanga.sh -d directory_name <other_options>

ตัวอย่าง:

onemanga.sh -d Bakuman 24 26

สุดท้ายคือ code ในสคริปต์ยังไม่ค่อยสวยงามเท่าไร แต่เท่าที่ทดสอบก็ใช้การได้ดี หากพบเห็นบั๊กช่วยแจ้งด้วย จะขอบคุณมากครับ

23 comments

Anonymous's picture
tuangd (visitor) says:

hmm ลองเอาไป install ดูแล้วเกิด error แบบนี้น่ะครับ สงสัยว่าผมทำอะไรผิดไปซักอย่าง

$ ./onemanga.sh Death_Note 61 110 ./onemanga.sh: line 2: $'\r': command not found ./onemanga.sh: line 5: $'\r': command not found ./onemanga.sh: line 73: syntax error near unexpected token elif' ./onemanga.sh: line 73: elif [[ echo "${current_chapter} &lt; ${latest_chapte '}" | bc -eq 1 ]]; then

kong's picture
kong says:

มีปัญหาตอน copy/paste ครับ (ถ้าพูดให้ถูกจริงๆ คือตอน save ไฟล์) วิธีแก้

Anonymous's picture
tuangd (visitor) says:

อืมผมลองแก้บรรทัดที่ 2 กับ 5 แล้วครับ คิดว่าคงเป็นตัวอักษรบางตัวมันเหลือมาจากการ copy แต่ที่บรรทัด 73 ยัง error เหมือนเดิมครับ ไม่แน่ใจว่ามากจากการ copy หรือเปล่าครับ

Anonymous's picture
tuangd (visitor) says:

ได้แล้วครับขอบคุณมากครับ :D

Anonymous's picture
karn (visitor) says:

ต่อไปก็เช็คว่าในเครื่องมีอะไรอยู่บ้างแล้ว update กับ onemanga อัตโนมัติซะเลยสิ

+ถ้าเขียนให้ใช้กับ mangafox ได้จะดีมาก

kong's picture
kong says:

จะให้อัพเดตอัตโนมัติก็ตั้ง cron หรือ scheduled task เอาก็ได้

mangafox เข้าไปดูแล้วไม่ไหว URL ไม่เนียน ท่าทางต้องใช้พลังมากเกิน =.=

Anonymous's picture
NoNT (visitor) says:

เวร Geek สัดว่ะ ทำ App ให้คนธรรมดาใช้หน่อยเด่ะ -_-

Anonymous's picture
karn (visitor) says:

!!request!! เนื่องจากขี้เกียจตั้ง cron เลยขอนี่แทน "-u" ให้ตรวจสอบไฟล์ปัจจุบันของทุกเรื่องที่อยู่ในโฟล์เดอร์ปัจจุบันแล้วดาวน์โหลดจนถึง chapter ล่าสุด และ "-ud" เหมือนกับข้างบนแต่ให้ตรวจสอบในแต่ละโฟล์เดอร์แทน

Anonymous's picture
Anonymous (visitor) says:

ใช้ cygwin ครับ มันบอกไม่เจอคำสั่ง bc อ่ะครับ ไม่ทราบว่าต้องแก้ไงดีอะครับ ขอบคุณครับ

kong's picture
kong says:

ต้องลงเพิ่มครับ อยู่ใน package Math

Anonymous's picture
crapcode (visitor) says:

เจ๋งมากเลยครับ ผมใช้ ผ่าน cygwin ในวิสต้าอยู่ดี ๆ มันจะหยุดทำงานไปซะอย่างนั้น แต่มาใช้ในอูบุนตูจะไหลลื่นไม่มีที่ติครับ มีใครเป็นอย่างผมบ้าง ชี้แนะทีครับ

Anonymous's picture
crapcode (visitor) says:

ลืมขอบคุณ ขอบคุณครับชอบมาก ๆ สะดวกจริง ๆ

kong's picture
kong says:

ยินดีครับ :)

Anonymous's picture
karn (visitor) says:

bug report! ตอนโหลดเรื่อง To_Aru_Kagaku_no_Choudenjibou ตอนที่ 13 มันโหลดข้ามหน้า ลองกับเรื่องอื่นแล้วไม่เป็น

Anonymous's picture
karn (visitor) says:

เขียนองแก้เอง -*-

ต้องแก้ range เพิ่มถึงใช้ได้ curl -s --range -2500 ${base_url}${page_location} > tmp_page

kong's picture
kong says:

ตามนั้น =.=

คือจริงๆ ก็ไม่รู้หรอกว่าควรตั้งเป็นเท่าไร คงต้องลองจนกว่าจะได้ค่าที่เหมาะสมกับการใช้งาน ถ้าตั้งไว้มากๆ มันก็จะโหลดข้อมูลที่ไม่จำเป็นเยอะขึ้น ทำให้โหลดเสร็จช้าหน่อย เท่านั้นเอง

Anonymous's picture
Einzelganger (visitor) says:

ของผมมันขึ้นว่า rm: cannot remove '*.jpg' : No such file or directory น่ะครับ แปลว่าอะไรหรอครับ?

kong's picture
kong says:

แล้วได้ไฟล์ .cbr ออกมาหรือเปล่าครับ ถ้าไม่ได้ แสดงว่ามันอาจจะโหลดไฟล์ไม่สำเร็จ น่าจะมีข้อความอื่นก่อนหน้านี้อีก

Anonymous's picture
Anonymous (visitor) says:

hi! I'm having problems running this script in osx. I think it may have to do with the creation of the .cbr file. It doesn't output anything except for the text "Done"

Any idea? I'm a newbie studying scripts- :(

kong's picture
kong says:

hi, if you're on OSX then I think you have to change the line that creates the .cbr file to use the archiver available on your system -- maybe "zip" will just work

try changing the line that refers to Rar.exe to something like this:

zip ${cbr_file_name} *.jpg
Anonymous's picture
Anonymous (visitor) says:

Hi Kong! I've tried what you told me, but i think there's still a small problem with the zip operation. Here's what I did:

chimera:~/Desktop/test chimera$ ./onemanga.sh -d Bakuman 24 26 Directory Bakuman does not exist. Created. Downloading Bakuman chapter 24 [] Creating Bakuman_24.zip... zip warning: name not matched: *.jpg

zip error: Nothing to do! (Bakuman_24.zip) DONE. rm: *.jpg: No such file or directory Downloading Bakuman chapter 25 [] Creating Bakuman_25.zip... zip warning: name not matched: *.jpg

zip error: Nothing to do! (Bakuman_25.zip) DONE. rm: *.jpg: No such file or directory Downloading Bakuman chapter 26 [] Creating Bakuman_26.zip... zip warning: name not matched: *.jpg

zip error: Nothing to do! (Bakuman_26.zip) DONE. rm: *.jpg: No such file or directory chimera:~/Desktop/test lance$

Any help is very much appreciated

Anonymous's picture
daemonx (visitor) says:

I found the solution kong! :) I totally forgot to notice that you used wget here, and since it is not preloaded on osx(since they favored curl instead) I wasn't actually able to download any images before resulting the above error.

So what I did was to follow your advice, replacing the reference of winrar to the zip utility in osx and install wget :)

Thanks a lot! :)

kong's picture
kong says:

Wow, that's one of many things I didn't know about OSX.

It's nice that you found the solution, and thanks for sharing the info :)

Post new comment

The content of this field is kept private and will not be shown publicly. If you have a Gravatar account, used to display your avatar.