2009-09-01 3 views
19

Я хотел бы сохранить файлы cookie с одного вызова с открытым uri и передать их следующему. Кажется, я не могу найти правильные документы для этого. Я был бы признателен, если бы вы могли сказать мне правильный способ сделать это.
ПРИМЕЧАНИЯ: w3.org не является фактическим URL, но он короче; притворяться, что печенье здесь.Ruby's open-uri and cookies

h1 = open("http://www.w3.org/") 
h2 = open("http://www.w3.org/People/Berners-Lee/", "Cookie" => h1.FixThisSpot) 

Update после 2 Найс: В то время как это не было задумано как риторический вопрос, я гарантирую, что это возможно. Обновление после перекати-валов: См. (Ответ), это возможно. Принял меня хорошо, но он работает.

+2

За то, что вы пытаетесь сделать, я бы рекомендовал использовать [Mechanize] (http://mechanize.rubyforge.org/mechanize/). Он разработан для такого рода вещей. Из описания: «Библиотека Mechanize используется для автоматизации взаимодействия с веб-сайтами. Механизация автоматически сохраняет и отправляет файлы cookie, переадресации, может следовать ссылкам и отправлять формы. Поля формы могут быть заполнены и отправлены. Механизация также отслеживает сайты, которые вы посетили как историю.« –

+0

Эта механизированная ссылка мертва, вот новая http://mechanize.rubyforge.org/ – MCB

+1

Механизируется сейчас на github: https://github.com/sparklemotion/mechanize – JESii

ответ

26

Я думал, что кто-то просто знаю, но я предполагаю, что это обычно не делается с open-uri. Вот уродливые версия, что ни проверки на неприкосновенность частной жизни, истечения срока действия, правильный домен, ни правильный путь:

h1 = open("http://www.w3.org/") 
h2 = open("http://www.w3.org/People/Berners-Lee/", 
      "Cookie" => h1.meta['set-cookie'].split('; ',2)[0]) 

Да, это работает. Нет, это не красиво, не полностью соответствует рекомендациям и не обрабатывает несколько файлов cookie (как есть).

Очевидно, что HTTP - это очень простой протокол, и open-uri позволяет вам в максимальной степени. Я предполагаю, что мне действительно нужно было знать, как получить файл cookie из запроса h1, чтобы он мог быть передан в запрос h2 (эта часть, которую я уже знал и показывал). Удивительно, что многие люди в основном чувствовали себя как ответ, предлагая мне не использовать open-uri, и только один из них показал, как получить набор файлов cookie за один запрос, переданный на следующий запрос.

1

вам нужно будет свернуть свою собственную поддержку файлов cookie, разобрав мета-заголовки при чтении и добавлении заголовка файла cookie при отправке запроса, если вы используете open-uri. Подумайте, используя httpclient http://raa.ruby-lang.org/project/httpclient/ или что-то вроде механизации вместо http://mechanize.rubyforge.org/, поскольку у них есть встроенная поддержка файлов cookie.

+0

Я боюсь, что« поддержка cookies не поддерживается » «слишком сильна в выборе слов. Я действительно ценю ссылки, но документация кажется редкой. http://mechanize.rubyforge.org/mechanize/WWW/Mechanize/CookieJar.html – dlamblin

+0

Ruby's Mechanize тесно связан с Perl's WWW :: Mechanize, в котором есть несколько хороших документов. Описание файлов cookie в документах Perl должно помочь выяснить, как работает Ruby. Прошло некоторое время с тех пор, как я использовал его, но я думаю, что он предоставит куклу cookie и будет обрабатывать их автоматически. Вы можете определить свою собственную банку, если вы хотите переключить их или вынуть или сохранить на диске для последующего повторного использования. –

12

Вам нужно добавить заголовок «Cookie».

Я не уверен, что open-uri может это сделать или нет, но это можно сделать с помощью Net :: HTTP.

# Create a new connection object. 
conn = Net::HTTP.new(site, port) 

# Get the response when we login, to set the cookie. 
# body is the encoded arguments to log in. 
resp, data = conn.post(login_path, body, {}) 
cookie = resp.response['set-cookie'] 

# Headers need to be in a hash. 
headers = { "Cookie" => cookie } 

# On a get, we don't need a body. 
resp, data = conn.get(path, headers) 
+2

Да, open-uri может отправлять дополнительные заголовки: open (url, «Cookie» => cookie) # http://www.ru by-doc.org/stdlib/libdoc/open-uri/rdoc/classes/OpenURI.html –

+0

Эта версия Net :: HTTP учитывает истечение, путь или домен cookie? – dlamblin

+0

@dlamblin Нет, намеренно нет. Сначала научитесь ползать, затем идите, затем бегите. –

2

В зависимости от того, что вы пытаетесь выполнить, зарегистрируйтесь webrat. Я знаю, что он обычно используется для тестирования, но он также может затрагивать сайты в реальном времени, и он делает много всего, что сделает ваш веб-браузер для вас, например, куки-файлы cookie между запросами и последующие переадресации.

+2

Я бы порекомендовал Mechanize вместо этого. Он попадет в живые сайты, обработает файлы cookie и последует переадресации, и, на самом деле, это было сделано для того, чтобы сделать все это. –

4

Спасибо, Мэтью Шинкель, ваш ответ был действительно полезен. Использование Net :: HTTP Я был успешным

 # Create a new connection object. 
      site = "google.com" 
      port = 80 
      conn = Net::HTTP.new(site, port) 

     # Get the response when we login, to set the cookie. 
     # body is the encoded arguments to log in. 
      resp, data = conn.post(login_path, body, {}) 
      cookie = resp.response['set-cookie'] 

     # Headers need to be in a hash. 
      headers = { "Cookie" => cookie } 

     # On a get, we don't need a body. 
      resp, data = conn.get(path, headers) 

      puts resp.body