2012-05-26 28 views
6

Tôi đang cố tạo một url để tôi có thể gửi yêu cầu đến nó bằng mô-đun urllib.Xây dựng chuỗi truy vấn bằng cách sử dụng mã vạch urlencode

Giả sử final_url tôi nên

url = "www.example.com/find.php?data=http%3A%2F%2Fwww.stackoverflow.com&search=Generate+value" 

Bây giờ để đạt được điều này tôi đã cố gắng theo cách sau:

>>> initial_url = "http://www.stackoverflow.com" 
>>> search = "Generate+value" 
>>> params = {"data":initial_url,"search":search} 
>>> query_string = urllib.urlencode(params) 
>>> query_string 
'search=Generate%2Bvalue&data=http%3A%2F%2Fwww.stackoverflow.com' 

Bây giờ nếu bạn so sánh query_string của tôi với các định dạng của final_url bạn có thể quan sát hai điều

1) Thứ tự của các tham số được đảo ngược thay vì data=()&search=search=()&data=

2) urlencode cũng được mã hóa các + trong Generate+value

Tôi tin rằng sự thay đổi đầu tiên là do các hành vi ngẫu nhiên của từ điển. Vì vậy, tôi mặc dù sử dụng OrderedDict to reverse the dictionary. As, Tôi đang sử dụng python 2.6.5 tôi đã làm

pip install ordereddict 

Nhưng tôi không thể sử dụng nó trong mã của tôi khi tôi cố gắng

>>> od = OrderedDict((('a', 'first'), ('b', 'second'))) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'OrderedDict' is not defined 

Vì vậy, câu hỏi của tôi là cách chính xác để sử dụng OrderedDict trong là những gì python 2.6.5 và cách tôi thực hiện urlencode bỏ qua + trong Generate+value.

Ngoài ra, đây có phải là cách tiếp cận chính xác để xây dựng URL.

Trả lời

15

Bạn không nên lo lắng về việc mã hóa + nó sẽ được khôi phục trên máy chủ sau khi không thoát url. Thứ tự của các tham số được đặt tên cũng không quan trọng.

Xét OrderedDict, nó không phải là Python được xây dựng trong Bạn nên nhập nó từ collections:.

from urllib import urlencode, quote 
# from urllib.parse import urlencode # python3 
from collections import OrderedDict 

initial_url = "http://www.stackoverflow.com" 
search = "Generate+value" 
query_string = urlencode(OrderedDict(data=initial_url,search=search)) 

nếu python của bạn quá cũ và không có OrderedDict trong module collections, sử dụng:

encoded = "&".join("%s=%s" % (key, quote(parameters[key], safe="+")) 
    for key in ordered(parameters.keys())) 

Dù sao thì thứ tự tham số cũng không thành vấn đề.

Lưu ý tham số safe của quote. Nó ngăn không cho + được thoát, nhưng điều đó có nghĩa là máy chủ sẽ giải thích Generate+valueGenerate value. Bạn có thể thoát theo cách thủ công + bằng cách viết %2B và đánh dấu % làm an toàn char:

+0

Tôi đã thử 'từ bộ sưu tập nhập OrderedDict' nhưng bây giờ tôi nhận được' ImportError: không thể nhập tên OrderedDict'. Tôi đang sử dụng python '2.6.5' – RanRag

+0

Nó sẽ có sẵn từ pyton 2.4. Jou nhận được gì nếu bạn thực thi 'import collections'? –

+0

Tôi có thể nhập thành công bộ sưu tập mà không có lỗi nào bị ném. Tôi mặc dù 'OrderedDict' được giới thiệu từ python 2.7 trở đi. – RanRag

3

Thứ nhất, thứ tự tham số trong yêu cầu http phải hoàn toàn không liên quan. Nếu không thì thư viện phân tích ở phía bên kia đang làm điều gì đó sai.

Thứ hai, tất nhiên, + được mã hóa. + được sử dụng làm trình giữ chỗ cho một khoảng trống trong url được mã hóa, vì vậy nếu chuỗi thô yor chứa một +, điều này phải được thoát.urlencode mong đợi một chuỗi chưa được mã hóa, bạn không thể chuyển chuỗi đó đã được mã hóa.

+0

Cảm ơn bạn đã đúng. Tôi đã không kiểm tra trước khi hỏi sai lầm của tôi. – RanRag

0

Một số ý kiến ​​về các câu hỏi và câu trả lời khác:

  1. Nếu bạn muốn giữ gìn trật tự với urllib.urlencode, nộp một chuỗi các lệnh k cặp/v thay vì lập bản đồ (dict). khi bạn vượt qua trong một dict, urlencode chỉ cần gọi foo.items() để lấy một chuỗi có thể lặp lại.

# urllib.urlencode accepts a mapping or sequence # the output of this can vary, because `items()` is called on the dict urllib.urlencode({"data": initial_url,"search": search}) # the output of this will not vary urllib.urlencode((("data", initial_url), ("search", search)))

bạn cũng có thể vượt qua trong một doseq luận secondard để điều chỉnh như thế nào giá trị iterable được xử lý.

  1. Thứ tự tham số không liên quan. mất hai url những ví dụ:

    https://example.com?foo=bar&bar=foo https://example.com?bar=foo&foo=bar

    Một máy chủ http nên xem xét thứ tự của các thông số này không thích hợp, nhưng một chức năng được thiết kế để so sánh URL sẽ không được. Để so sánh các url một cách an toàn, các tham số này sẽ cần được sắp xếp.

    Tuy nhiên, hãy xem xét các phím trùng lặp:

    https://example.com?foo=3&foo=2&foo=1

Các thông số kỹ thuật URI hỗ trợ phím trùng lặp, nhưng không giải quyết được ưu tiên hoặc đặt hàng.

Trong một ứng dụng nhất định, những thể từng gây ra kết quả khác nhau và có giá trị cũng như:

https://example.com?foo=1&foo=2&foo=3 
https://example.com?foo=1&foo=3&foo=2 
https://example.com?foo=2&foo=3&foo=1 
https://example.com?foo=2&foo=1&foo=3 
https://example.com?foo=3&foo=1&foo=2 
https://example.com?foo=3&foo=2&foo=1 
  1. Các + là ký tự dành riêng đại diện cho một không gian trong một hình thức urlencoded (vs %20 cho một phần của con đường). urllib.urlencode thoát bằng cách sử dụng urllib.quote_plus(), không phải urllib.quote(). OP rất có thể muốn chỉ làm điều này:

initial_url = "http://www.stackoverflow.com" search = "Generate value" urllib.urlencode((("data", initial_url), ("search", search)))

nào sản xuất:

data=http%3A%2F%2Fwww.stackoverflow.com&search=Generate+value

như đầu ra.

Các vấn đề liên quan