2012-01-19 4 views
5

मैं ऐसे ऐप पर काम कर रहा हूं जिसे HTML पृष्ठों में यूआरएल (ज्यादातर HTTP यूआरएल) का विश्लेषण करने की ज़रूरत है - मेरे पास इनपुट पर कोई नियंत्रण नहीं है और इसमें से कुछ उम्मीद है, थोड़ा गन्दापाइथन में यूआरएल पार्सिंग - पथों में डबल-स्लैश को सामान्य बनाना

testUrl = 'http://www.example.com//path?foo=bar' 
urlparse.urljoin(testUrl, 
       urlparse.urlparse(testUrl).path) 
:

एक समस्या यह है मैं अक्सर सामना कर रहा हूँ जब यह उदाहरण के लिए, पार्स करने और शामिल होने यूआरएल पथ भाग में है कि डबल स्लैश की बात आती है बहुत सख्त है कि urlparse है (और संभवतः भी छोटी गाड़ी?)

अपेक्षित परिणाम http://www.example.com//path (या सामान्यीकृत एकल स्लैश के साथ भी बेहतर) के बजाय, मैं http://path के साथ समाप्त होता हूं।

बीटीडब्ल्यू कारण मैं इस तरह का कोड चला रहा हूं क्योंकि यह एकमात्र तरीका है जिसे मैंने यूआरएल के क्वेरी/खंड भाग को बंद करने के लिए अभी तक पाया है। शायद ऐसा करने का एक बेहतर तरीका है, लेकिन मुझे एक नहीं मिला।

क्या कोई इस से बचने के लिए एक तरीका सुझा सकता है, या क्या मुझे केवल एक (अपेक्षाकृत सरल, मुझे पता है) regex का उपयोग करके पथ को सामान्य बनाना चाहिए?

+0

आप "यह जानकारी/टुकड़ा हिस्सा पट्टी लिए एक ही रास्ता है" से क्या मतलब है? स्लैश को क्वेरी के साथ क्या करना है? – jknupp

+0

इसमें क्वेरी के साथ कुछ लेना देना नहीं है - कारण मैं एक यूआरएल पार्स कर रहा हूं और उसके बाद अपने रास्ते में शामिल हो रहा हूं क्योंकि मैं क्वेरी और खंड को बाहर करना चाहता हूं। अगर ऐसा करने का बेहतर तरीका था, तो मुझे इस समस्या को हल करने की आवश्यकता नहीं होगी – shevron

+2

मुझे लगता है कि urlparse सिर्फ यूआरएल के आरएफसी को सही ढंग से कार्यान्वित कर रहा है - जो निर्दिष्ट करता है कि : भाग केवल एक स्लैश (http: //tools.ietf.org/html/rfc1738) - तो आपके मामले में मैं urlparse को पास करने से पहले अतिरिक्त स्लैश को पट्टी करने की कोशिश करता हूं। – BergmannF

उत्तर

4

आप केवल क्वेरी हिस्सा बिना यूआरएल प्राप्त करना चाहते हैं, मैं urlparse मॉड्यूल को छोड़ होगा और बस कार्य करें:

testUrl.rsplit('?') 

यूआरएल वापस सूची की अनुक्रमणिका 0 पर होगा और सूचकांक पर क्वेरी 1.

दो '?' होना संभव नहीं है? एक यूआरएल में तो यह सभी यूआरएल के लिए काम करना चाहिए।

+0

यह किसी भी urlparse मुद्दों का जवाब नहीं देता है, लेकिन यह निश्चित रूप से मेरे उपयोग मामले को एक बहुत ही सरल तरीके से हल करता है। धन्यवाद! – shevron

1

यह official urlparse docs में बताया गया है कि:

तो यूआरएल एक पूर्ण यूआरएल (अर्थात, // या योजना के साथ शुरू: //) है, URL के होस्ट नाम और/या स्कीम होगी परिणाम में उपस्थित है। उदाहरण

urljoin('http://www.cwi.nl/%7Eguido/Python.html', 
...   '//www.python.org/%7Eguido') 
'http://www.python.org/%7Eguido' 

के लिए आप उस व्यवहार नहीं चाहते हैं urlsplit() और urlunsplit() के साथ यूआरएल, संभव योजना और netloc भागों को हटाने preprocess।

तो तुम कर सकते हैं:

urlparse.urljoin(testUrl, 
      urlparse.urlparse(testUrl).path.replace('//','/')) 

आउटपुट = 'http://www.example.com/path'

0

क्या यह समाधान नहीं हो सकता है?

urlparse.urlparse(testUrl).path.replace('//', '/') 
5

पथ (//path) जो अकेले समारोह confuses और एक होस्ट नाम

http://tools.ietf.org/html/rfc3986.html#section-3.3

के रूप में व्याख्या हो जाता है यूआरआई एक अधिकार घटक शामिल नहीं है, तो मान्य नहीं है, पथ दो स्लैश वर्णों ("//") से शुरू नहीं हो सकता है।

मैं विशेष रूप से इन समाधानों में से या तो पसंद नहीं है, लेकिन वे काम करते हैं:

import re 
import urlparse 

testurl = 'http://www.example.com//path?foo=bar' 

parsed = list(urlparse.urlparse(testurl)) 
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more/with one 
cleaned = urlparse.urlunparse(parsed) 

print cleaned 
# http://www.example.com/path?foo=bar 

print urlparse.urljoin(
    testurl, 
    urlparse.urlparse(cleaned).path) 

# http://www.example.com//path 

तुम क्या कर रहे आधार पर, आप कर सकता है मैन्युअल रूप से शामिल होने:

import re 
import urlparse 

testurl = 'http://www.example.com//path?foo=bar' 
parsed = list(urlparse.urlparse(testurl)) 

newurl = ["" for i in range(6)] # could urlparse another address instead 

# Copy first 3 values from 
# ['http', 'www.example.com', '//path', '', 'foo=bar', ''] 
for i in range(3): 
    newurl[i] = parsed[i] 

# Rest are blank 
for i in range(4, 6): 
    newurl[i] = '' 

print urlparse.urlunparse(newurl) 
# http://www.example.com//path 
+0

यूआरएल वास्तव में मान्य है, क्योंकि ** ** इसमें एक प्राधिकरण अनुभाग होता है - इसलिए यूआरएल '//' से शुरू हो सकता है। किसी भी मामले में भले ही यह अमान्य पार्स करने में सक्षम नहीं है लेकिन "असली दुनिया" यूआरएल सहायक हो सकता है। – shevron

+0

@ShaharEvron अच्छा बिंदु - संपादित उत्तर – dbr

0

कोशिश यह:

def http_normalize_slashes(url): 
    url = str(url) 
    segments = url.split('/') 
    correct_segments = [] 
    for segment in segments: 
     if segment != '': 
      correct_segments.append(segment) 
    first_segment = str(correct_segments[0]) 
    if first_segment.find('http') == -1: 
     correct_segments = ['http:'] + correct_segments 
    correct_segments[0] = correct_segments[0] + '/' 
    normalized_url = '/'.join(correct_segments) 
    return normalized_url 

उदाहरण यूआरएल:

print(http_normalize_slashes('http://www.example.com//path?foo=bar')) 
print(http_normalize_slashes('http:/www.example.com//path?foo=bar')) 
print(http_normalize_slashes('www.example.com//x///c//v///path?foo=bar')) 
print(http_normalize_slashes('http://////www.example.com//x///c//v///path?foo=bar')) 

वापसी करेंगे:

http://www.example.com/path?foo=bar 
http://www.example.com/path?foo=bar 
http://www.example.com/x/c/v/path?foo=bar 
http://www.example.com/x/c/v/path?foo=bar 

आशा है कि यह मदद करता है .. :)

संबंधित मुद्दे