รับ URL สุดท้ายหลังจากเปลี่ยนเส้นทาง curl


118

ฉันต้องการรับ URL สุดท้ายหลังจากการเปลี่ยนเส้นทางหน้าควรใช้ curl หรือ wget

ยกตัวอย่างเช่นhttp://google.comอาจเปลี่ยนเส้นทางไปยังhttp://www.google.com

เนื้อหานั้นง่ายต่อการรับ (เช่นcurl --max-redirs 10 http://google.com -L) แต่ฉันสนใจเฉพาะ url สุดท้าย (ในกรณีเดิมคือhttp://www.google.com )

มีวิธีใดบ้างในการทำเช่นนี้โดยใช้เครื่องมือในตัวของ Linux เท่านั้น? (บรรทัดคำสั่งเท่านั้น)

คำตอบ:


208

curlของ-wตัวเลือกและตัวแปรย่อยurl_effectiveคือสิ่งที่คุณกำลังมองหา

สิ่งที่ต้องการ

curl -Ls -o /dev/null -w %{url_effective} http://google.com

ข้อมูลเพิ่มเติม

-L ติดตามการเปลี่ยนเส้นทาง
-s โหมดเงียบ อย่าส่งออกอะไรเลย
-o FILE เขียนเอาต์พุตไปยัง <file> แทน stdout
-w FORMAT สิ่งที่จะส่งออกหลังจากเสร็จสิ้น

มากกว่า

คุณอาจต้องการเพิ่ม-I(ซึ่งเป็นตัวพิมพ์ใหญ่i) ด้วยซึ่งจะทำให้คำสั่งไม่ดาวน์โหลด "body" ใด ๆ แต่จะใช้เมธอด HEAD ด้วยซึ่งไม่ใช่คำถามที่รวมอยู่และมีความเสี่ยงที่จะเปลี่ยนแปลงสิ่งที่เซิร์ฟเวอร์ทำ บางครั้งเซิร์ฟเวอร์ตอบสนองต่อ HEAD ได้ไม่ดีแม้ว่าจะตอบสนองต่อ GET ได้ดีก็ตาม


4
คุณควรจะสามารถใช้ "-o / dev / null" ได้หากไม่ต้องการไฟล์
Gavin Mogan

1
นั่นเป็นตัวเลือกที่ยอดเยี่ยมฉันไม่เคยรู้เลยว่า curl ทำได้! มันไม่เคยทำให้ฉันประหลาดใจ:-)
Josh

1
นั่นเป็นคุณสมบัติของเชลล์มากกว่า curl
user151841

1
@DanielStenberg ที่คุณต้องการไม่-Iงั้นมันจะดาวน์โหลดไฟล์จริงๆ
Steven Penny

2
บางเว็บไซต์ยังต้องการตัวแทนผู้ใช้ที่ปลอมแปลงcurl -A ...เพื่อเปลี่ยนเส้นทางไปยังตำแหน่งที่คาดไว้
Ivan Kozik

30

ขอบคุณที่ช่วยฉัน ฉันได้ทำการปรับปรุงและรวมสิ่งนั้นไว้ในสคริปต์ตัวช่วย "finalurl":

#!/bin/bash
curl $1 -s -L -I -o /dev/null -w '%{url_effective}'
  • -o ส่งออกไปยัง /dev/null
  • -I ไม่ต้องดาวน์โหลดจริงเพียงแค่ค้นพบ URL สุดท้าย
  • -s โหมดเงียบไม่มีแถบความคืบหน้า

สิ่งนี้ทำให้สามารถเรียกคำสั่งจากสคริปต์อื่น ๆ เช่นนี้:

echo `finalurl http://someurl/`

2
ขอบคุณสำหรับแนวคิดเหล่านั้น ฉันเขียนมันใหม่สำหรับการใช้งานเทอร์มินัลในไฟล์. bashrc ของฉันเป็นฟังก์ชั่นและไม่จำเป็นต้องมีตัวเลือก terse ในไฟล์นั้นฉันจึงใช้ชื่อยาวในการจัดทำเอกสารด้วยตัวเอง:finalurl() { curl --silent --location --head --output /dev/null --write-out '%{url_effective}' -- "$@"; }
gw0

7

เป็นตัวเลือกอื่น:

$ curl -i http://google.com
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Sat, 19 Jun 2010 04:15:10 GMT
Expires: Mon, 19 Jul 2010 04:15:10 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 1; mode=block

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

แต่มันไม่ผ่านอันแรกไป


6

คุณสามารถทำได้ด้วย wget ปกติ wget --content-disposition"url" นอกจากนี้หากคุณเพิ่ม-O /dev/nullคุณจะไม่ได้บันทึกไฟล์จริงๆ

wget -O /dev/null --content-disposition example.com


เปลี่ยนจากเพียง-O /dev/null -O-Better:wget -O- --content-disposition example.com
Maxwel Leite

1
wget -O / dev / null --content-Disposition example.com และ wget -O- / dev / null --content-Disposition example.com จะสร้างเอาต์พุตมากกว่า URL ที่เปลี่ยนเส้นทางมาก curl $ 1 -s -L -I -o / dev / null -w '% {url_effective}' ใช้ได้ดีสำหรับฉัน
Eric Klien

5

ขอบคุณ. ฉันลงเอยด้วยการใช้คำแนะนำของคุณ: curl -i + grep

curl -i http://google.com -L | egrep -A 10 '301 Moved Permanently|302 Found' | grep 'Location' | awk -F': ' '{print $2}' | tail -1

ส่งคืนค่าว่างหากเว็บไซต์ไม่เปลี่ยนเส้นทาง แต่นั่นก็ดีพอสำหรับฉันเนื่องจากทำงานในการเปลี่ยนเส้นทางติดต่อกัน

อาจเป็นรถบั๊กกี้ แต่สรุปก็ใช้ได้



2

พารามิเตอร์-L (--location)และ-I (--head)ยังคงทำคำขอ HEAD ที่ไม่จำเป็นไปยัง location-url

หากคุณแน่ใจว่าจะไม่มีการเปลี่ยนเส้นทางมากกว่า 1 ครั้งคุณควรปิดการใช้งานการติดตามตำแหน่งและใช้ curl-variable% {redirect_url}

โค้ดนี้ส่งคำขอ HEAD เพียงรายการเดียวไปยัง URL ที่ระบุและใช้ redirect_url จาก location-header:

curl --head --silent --write-out "%{redirect_url}\n" --output /dev/null "https://""goo.gl/QeJeQ4"

ทดสอบความเร็ว

all_videos_link.txt - 50 ลิงก์ของ goo.gl + bit.ly ซึ่งเปลี่ยนเส้นทางไปยัง youtube

1. พร้อมติดตามสถานที่

time while read -r line; do
    curl -kIsL -w "%{url_effective}\n" -o /dev/null  $line
done < all_videos_link.txt

ผล:

real    1m40.832s
user    0m9.266s
sys     0m15.375s

2. โดยไม่ต้องติดตามสถานที่

time while read -r line; do
    curl -kIs -w "%{redirect_url}\n" -o /dev/null  $line
done < all_videos_link.txt

ผล:

real    0m51.037s
user    0m5.297s
sys     0m8.094s

ดูเหมือนจะเป็นเรื่องแปลกที่คุณจะรู้ล่วงหน้าว่าจะมีการเปลี่ยนเส้นทางเพียงครั้งเดียว ...
SamB

1

ฉันไม่แน่ใจว่าจะทำอย่างไรกับ curl แต่ libwww-perl ติดตั้งนามแฝง GET

$ GET -S -d -e http://google.com
GET http://google.com --> 301 Moved Permanently
GET http://www.google.com/ --> 302 Found
GET http://www.google.ca/ --> 200 OK
Cache-Control: private, max-age=0
Connection: close
Date: Sat, 19 Jun 2010 04:11:01 GMT
Server: gws
Content-Type: text/html; charset=ISO-8859-1
Expires: -1
Client-Date: Sat, 19 Jun 2010 04:11:01 GMT
Client-Peer: 74.125.155.105:80
Client-Response-Num: 1
Set-Cookie: PREF=ID=a1925ca9f8af11b9:TM=1276920661:LM=1276920661:S=ULFrHqOiFDDzDVFB; expires=Mon, 18-Jun-2012 04:11:01 GMT; path=/; domain=.google.ca
Title: Google
X-XSS-Protection: 1; mode=block

0

คุณสามารถลองกับมันได้หรือไม่?

#!/bin/bash 
LOCATION=`curl -I 'http://your-domain.com/url/redirect?r=something&a=values-VALUES_FILES&e=zip' | perl -n -e '/^Location: (.*)$/ && print "$1\n"'` 
echo "$LOCATION"

หมายเหตุ: เมื่อคุณรันคำสั่ง curl -I http://your-domain.comต้องใช้เครื่องหมายคำพูดเดี่ยวในคำสั่งเช่น curl -I 'http://your-domain.com'


-4

คุณสามารถใช้ grep ไม่ได้บอกคุณว่ามันเปลี่ยนเส้นทางไปที่ไหนด้วย? เพียงแค่ grep ที่ออก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.