2009-09-26 32 views
19

Tôi cần phải xóa kết quả truy vấn từ trang web .aspx.cách gửi truy vấn đến trang .aspx trong python

http://legistar.council.nyc.gov/Legislation.aspx

Url là tĩnh, vì vậy làm thế nào để tôi gửi một truy vấn đến trang này và có được kết quả? Giả sử chúng ta cần phải chọn "tất cả các năm" và "tất cả các loại" từ các trình đơn thả xuống tương ứng.

Ai đó ở đó phải biết cách thực hiện việc này.

Trả lời

25

Là một cái nhìn tổng quan, bạn sẽ cần phải thực hiện bốn nhiệm vụ chính:

  • để gửi yêu cầu (s) đến trang web,
  • để lấy phản ứng (s) từ trang web
  • để phân tích những phản ứng
  • có một số logic để lặp trong các nhiệm vụ trên, với các thông số liên quan đến việc chuyển hướng (vào các trang web "bên cạnh" trong danh sách kết quả)

Yêu cầu http và xử lý phản hồi được thực hiện với các phương thức và lớp học từ thư viện chuẩn của Python là urlliburllib2. Các phân tích của các trang html có thể được thực hiện với HTMLParser hoặc với các module khác như Beautiful Soup

Đoạn sau thư viện chuẩn của Python của chứng minh yêu cầu và nhận của một tìm kiếm tại địa điểm chỉ định trong câu hỏi.Trang web này được định hướng ASP và kết quả là chúng tôi cần đảm bảo rằng chúng tôi gửi một số trường biểu mẫu, một số trường có giá trị 'khủng khiếp' vì chúng được sử dụng bởi logic ASP để duy trì trạng thái và xác thực yêu cầu ở một mức độ nào đó. Thực sự gửi. Các yêu cầu phải được gửi với phương thức http POST http POST vì đây là những gì được mong đợi từ ứng dụng ASP này. Khó khăn chính là xác định trường biểu mẫu và các giá trị liên quan mà ASP mong đợi (việc nhận các trang bằng Python là phần dễ dàng).

Mã này là chức năng hoặc chính xác hơn, là chức năng, cho đến khi tôi xóa hầu hết giá trị VSTATE và có thể giới thiệu lỗi đánh máy hoặc hai bằng cách thêm nhận xét.

import urllib 
import urllib2 

uri = 'http://legistar.council.nyc.gov/Legislation.aspx' 

#the http headers are useful to simulate a particular browser (some sites deny 
#access to non-browsers (bots, etc.) 
#also needed to pass the content type. 
headers = { 
    'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.13) Gecko/2009073022 Firefox/3.0.13', 
    'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml; q=0.9,*/*; q=0.8', 
    'Content-Type': 'application/x-www-form-urlencoded' 
} 

# we group the form fields and their values in a list (any 
# iterable, actually) of name-value tuples. This helps 
# with clarity and also makes it easy to later encoding of them. 

formFields = (
    # the viewstate is actualy 800+ characters in length! I truncated it 
    # for this sample code. It can be lifted from the first page 
    # obtained from the site. It may be ok to hardcode this value, or 
    # it may have to be refreshed each time/each day, by essentially 
    # running an extra page request and parse, for this specific value. 
    (r'__VSTATE', r'7TzretNIlrZiKb7EOB3AQE ... ...2qd6g5xD8CGXm5EftXtNPt+H8B'), 

    # following are more of these ASP form fields 
    (r'__VIEWSTATE', r''), 
    (r'__EVENTVALIDATION', r'/wEWDwL+raDpAgKnpt8nAs3q+pQOAs3q/pQOAs3qgpUOAs3qhpUOAoPE36ANAve684YCAoOs79EIAoOs89EIAoOs99EIAoOs39EIAoOs49EIAoOs09EIAoSs99EI6IQ74SEV9n4XbtWm1rEbB6Ic3/M='), 
    (r'ctl00_RadScriptManager1_HiddenField', ''), 
    (r'ctl00_tabTop_ClientState', ''), 
    (r'ctl00_ContentPlaceHolder1_menuMain_ClientState', ''), 
    (r'ctl00_ContentPlaceHolder1_gridMain_ClientState', ''), 

    #but then we come to fields of interest: the search 
    #criteria the collections to search from etc. 
                 # Check boxes 
    (r'ctl00$ContentPlaceHolder1$chkOptions$0', 'on'), # file number 
    (r'ctl00$ContentPlaceHolder1$chkOptions$1', 'on'), # Legislative text 
    (r'ctl00$ContentPlaceHolder1$chkOptions$2', 'on'), # attachement 
                 # etc. (not all listed) 
    (r'ctl00$ContentPlaceHolder1$txtSearch', 'york'), # Search text 
    (r'ctl00$ContentPlaceHolder1$lstYears', 'All Years'), # Years to include 
    (r'ctl00$ContentPlaceHolder1$lstTypeBasic', 'All Types'), #types to include 
    (r'ctl00$ContentPlaceHolder1$btnSearch', 'Search Legislation') # Search button itself 
) 

# these have to be encoded  
encodedFields = urllib.urlencode(formFields) 

req = urllib2.Request(uri, encodedFields, headers) 
f= urllib2.urlopen(req)  #that's the actual call to the http site. 

# *** here would normally be the in-memory parsing of f 
#  contents, but instead I store this to file 
#  this is useful during design, allowing to have a 
#  sample of what is to be parsed in a text editor, for analysis. 

try: 
    fout = open('tmp.htm', 'w') 
except: 
    print('Could not open output file\n') 

fout.writelines(f.readlines()) 
fout.close() 

Đó là về việc bắt đầu trang đầu tiên. Như đã nói ở trên, sau đó, một người sẽ cần phải phân tích cú pháp trang, tức là tìm các phần quan tâm và thu thập chúng một cách thích hợp và lưu trữ chúng vào tệp/cơ sở dữ liệu/ở bất cứ đâu. Công việc này có thể được thực hiện theo nhiều cách: sử dụng các trình phân tích cú pháp html, hoặc kiểu kỹ thuật XSLT (thực sự sau khi phân tích cú pháp html thành xml), hoặc thậm chí cho các công việc thô, biểu thức chính quy đơn giản. Ngoài ra, một trong những mục thường trích xuất là "thông tin tiếp theo", tức là một liên kết các loại, có thể được sử dụng trong một yêu cầu mới đến máy chủ để nhận các trang tiếp theo.

Điều này sẽ cung cấp cho bạn một hương vị thô sơ về những gì "dài tay" html cạo là về. Có rất nhiều cách tiếp cận khác, chẳng hạn như utilties dành riêng, tập lệnh trong trình cắm GreaseMonkey của Mozilla (FireFox), XSLT ...

+0

Nếu tôi đang sử dụng Google Chrome, thì tôi nên thay thế giá trị cho 'HTTP_USER_AGENT' như thế nào? Tôi xin lỗi nếu câu hỏi này là câm kể từ khi tôi không làm nhiều thứ web. Cảm ơn! – taocp

+0

@taocp, một cách dễ dàng để biết chuỗi 'HTTP_USER_AGENT' để sử dụng cho một trình duyệt cụ thể là truy cập http://www.all-nettools.com/toolbox/environmental-variables-test.php trang này sẽ hiển thị cho bạn các giá trị tiêu đề được trình duyệt gửi, hãy tìm "HTTP_USER_AGENT". Chuỗi thực tế phụ thuộc vào hệ điều hành và phiên bản cụ thể và bản dựng Chrome, nhưng phải giống một số 'như' Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, như Gecko) Chrome/29.0.1547.66 Safari/537.36' – mjv

+0

cảm ơn rất nhiều câu trả lời của bạn. Tôi đã thử mã của bạn với các giá trị thích hợp được đặt cho trình duyệt chrome của tôi. Tệp tmp.htm kết quả cho biết "không tìm thấy kết quả", trong khi khi tôi đặt "york" trên trang web, nó trả về rất nhiều. Bạn có biết tại sao? – taocp

0

"Giả sử chúng tôi cần chọn" tất cả các năm "và" tất cả các loại "từ trình đơn thả xuống tương ứng."

Tùy chọn này thực hiện những gì đối với URL được gửi cuối cùng.

Sau khi tất cả, số tiền đó yêu cầu HTTP được gửi qua urllib2.

Làm cách nào để thực hiện "" tất cả các năm "và" tất cả các loại "từ trình đơn thả xuống tương ứng 'bạn thực hiện như sau.

  1. Chọn ' 'tất cả các năm' và 'tất cả các loại' từ trình đơn thả xuống tương ứng'

  2. Note URL mà thực sự là đệ trình.

  3. Sử dụng URL này trong urllib2.

+0

Rõ ràng trang là một hình thức yêu cầu POST, nhưng ý tưởng là như nhau: lưu ý các điểm tên trường biểu mẫu và giá trị được liên kết với 'Tất cả các năm' và witn 'tất cả các loại' và sử dụng urlib2.Request để truy cập dữ liệu. – mjv

+0

Tôi đang sử dụng proxy gỡ lỗi web Charles để xem tất cả lưu lượng truy cập http khi tôi lướt trang web này và gửi truy vấn và url hoàn toàn tĩnh. Nó không chứa tham số nào cả. Có hình thức dữ liệu để vượt qua bằng cách nào đó - ajax, tôi đoán - nhưng tôi không biết làm thế nào để gửi dữ liệu biểu mẫu đó đến máy chủ.Tất cả có vẻ khó hiểu với tôi. Thực tế là tôi không thể gửi truy vấn bằng cách thao tác url là điều khiến tôi khó hiểu. – twneale

+0

Khi bạn nhận được kết quả tạo thành trang này, nếu bạn muốn khan hiếm nó, bạn có thể sử dụng mô-đun python HTMLParser hoặc Beautifulsoup để phân tích cú pháp trang html. Ngoài ra cạo sẽ có khả năng liên quan đến nhiều cuộc gọi urlib2 để điều hướng đến các trang kết quả tiếp theo. – mjv

4

Hầu hết các trang web ASP.NET (trang web bạn tham chiếu đi kèm) sẽ thực sự đăng truy vấn của họ về bản thân bằng cách sử dụng động từ HTTP, chứ không phải động từ GET. Đó là lý do tại sao URL không thay đổi như bạn đã lưu ý.

Điều bạn cần làm là xem HTML được tạo và nắm bắt tất cả các giá trị biểu mẫu của chúng. Hãy chắc chắn nắm bắt tất cả các giá trị biểu mẫu, vì một số trong số chúng được sử dụng để xác thực trang và không có chúng, yêu cầu POST của bạn sẽ bị từ chối.

Khác với xác thực, trang ASPX liên quan đến việc cào và đăng không khác gì các công nghệ web khác.

5

Selenium là một công cụ tuyệt vời để sử dụng cho loại tác vụ này. Bạn có thể chỉ định các giá trị biểu mẫu mà bạn muốn nhập và truy xuất html của trang phản hồi dưới dạng chuỗi trong một vài dòng mã python. Sử dụng Selenium bạn có thể không phải thực hiện công việc thủ công mô phỏng yêu cầu đăng hợp lệ và tất cả các biến ẩn của nó, như tôi đã phát hiện sau nhiều lần thử và lỗi.

+1

Bạn có thể cung cấp một số đoạn mã không? – taocp

+0

Tôi đã thành công trong việc kết nối, đăng nhập và nhấp vào liên kết bằng selenium Tôi bị kẹt ở phần mà bạn muốn lấy dữ liệu từ một trang. Vì URI vẫn giữ nguyên ngay cả sau khi nhấp vào, điều này đặt ra một vấn đề. –

4

Mã trong các câu trả lời khác hữu ích; Tôi không bao giờ có thể viết trình thu thập thông tin của tôi mà không có nó.

Một vấn đề mà tôi gặp phải là cookie. Các trang web tôi đang bò đã sử dụng cookie để đăng nhập phiên id/stuff an ninh, vì vậy tôi đã phải thêm mã để có được bánh xích của tôi để làm việc:

Thêm nhập khẩu này:

import cookielib    

Init những thứ cookie:

COOKIEFILE = 'cookies.lwp'   # the path and filename that you want to use to save your cookies in 
    cj = cookielib.LWPCookieJar()  # This is a subclass of FileCookieJar that has useful load and save methods 

Install CookieJar để nó được sử dụng như là mặc định CookieProcessor trong xử lý mở mặc định:

cj.load(COOKIEFILE) 
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) 
    urllib2.install_opener(opener) 

Để xem những gì cookie trang web được sử dụng:

print 'These are the cookies we have received so far :' 

    for index, cookie in enumerate(cj): 
     print index, ' : ', cookie   

này giúp tiết kiệm các cookie:

cj.save(COOKIEFILE)      # save the cookies 
Các vấn đề liên quan