2011-01-18 8 views
13

ウェブサイトReddit.comにログインし、ページの特定の場所に移動してコメントを送信します。私はこのコードで何が間違っているかはわかりませんが、Redditサイトに変更が反映されていないという点では機能していません。Pythonを使用して機械化してフォームデータを送信し、認証する

import mechanize 
import cookielib 


def main(): 

#Browser 
br = mechanize.Browser() 


# Cookie Jar 
cj = cookielib.LWPCookieJar() 
br.set_cookiejar(cj) 

# Browser options 
br.set_handle_equiv(True) 
br.set_handle_gzip(True) 
br.set_handle_redirect(True) 
br.set_handle_referer(True) 
br.set_handle_robots(False) 

# Follows refresh 0 but not hangs on refresh > 0 
br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1) 

#Opens the site to be navigated 
r= br.open('http://www.reddit.com') 
html = r.read() 

# Select the second (index one) form 
br.select_form(nr=1) 

# User credentials 
br.form['user'] = 'DUMMYUSERNAME' 
br.form['passwd'] = 'DUMMYPASSWORD' 

# Login 
br.submit() 

#Open up comment page 
r= br.open('http://www.reddit.com/r/PoopSandwiches/comments/f47f8/testing/') 
html = r.read() 

#Text box is the 8th form on the page (which, I believe, is the text area) 
br.select_form(nr=7) 

#Change 'text' value to a testing string 
br.form['text']= "this is an automated test" 

#Submit the information 
br.submit() 

この問題は何ですか?

+0

少なくとも10秒間スリープ状態を追加してみてください。また、ブラウザのフォームを調べる( 'ソースの表示'ではなく、Chromeの「要素の検査」など)、ブラウザのフォームを調べて、ダウンロードしたHTMLと比較する必要があります。 JSによって動的にフィールドが埋め込まれている可能性があります。 – TryPyPy

+1

ところで、RedditにはAPIがありますが、うまくいかないでしょうか? – TryPyPy

+0

ええ、私は睡眠を追加しようとしましょう。私はコメントを提出するためのドキュメントがないので、APIの使い方がわかりません。 – Parseltongue

答えて

18

私は間違いなく可能な場合はAPIを使用しようと提案するだろうが、これは私のために動作します(いない削除されたあなたの例のポストのために、しかし、任意のアクティブな1用):

#!/usr/bin/env python 

import mechanize 
import cookielib 
import urllib 
import logging 
import sys 

def main(): 

    br = mechanize.Browser() 
    cj = cookielib.LWPCookieJar() 
    br.set_cookiejar(cj) 

    br.set_handle_equiv(True) 
    br.set_handle_gzip(True) 
    br.set_handle_redirect(True) 
    br.set_handle_referer(True) 
    br.set_handle_robots(False) 

    br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1) 

    r= br.open('http://www.reddit.com') 

    # Select the second (index one) form 
    br.select_form(nr=1) 

    # User credentials 
    br.form['user'] = 'user' 
    br.form['passwd'] = 'passwd' 

    # Login 
    br.submit() 

    # Open up comment page 
    posting = 'http://www.reddit.com/r/PoopSandwiches/comments/f47f8/testing/' 
    rval = 'PoopSandwiches' 
    # you can get the rval in other ways, but this will work for testing 

    r = br.open(posting) 

    # You need the 'uh' value from the first form 
    br.select_form(nr=0) 
    uh = br.form['uh'] 

    br.select_form(nr=7) 
    thing_id = br.form['thing_id'] 
    id = '#' + br.form.attrs['id'] 
    # The id that gets posted is the form id with a '#' prepended. 

    data = {'uh':uh, 'thing_id':thing_id, 'id':id, 'renderstyle':'html', 'r':rval, 'text':"Your text here!"} 
    new_data_dict = dict((k, urllib.quote(v).replace('%20', '+')) for k, v in data.iteritems()) 

    # not sure if the replace needs to happen, I did it anyway 
    new_data = 'thing_id=%(thing_id)s&text=%(text)s&id=%(id)s&r=%(r)s&uh=%(uh)s&renderstyle=%(renderstyle)s' %(new_data_dict) 

    # not sure which of these headers are really needed, but it works with all 
    # of them, so why not just include them. 
    req = mechanize.Request('http://www.reddit.com/api/comment', new_data) 
    req.add_header('Referer', posting) 
    req.add_header('Accept', ' application/json, text/javascript, */*') 
    req.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8') 
    req.add_header('X-Requested-With', 'XMLHttpRequest') 
    cj.add_cookie_header(req) 
    res = mechanize.urlopen(req) 

main() 

それは次のようになり興味深いことに、javascriptをオフにして、redditコメントがどのように処理されるかを見てください。今すぐあなたのポストを作るときに呼ばれるonsubmit関数で起こるmagicの束があります。これはuhidの値が追加される場所です。

+0

うわー。どうもありがとうございます。私は決してそれを考え出さなかったでしょう。 – Parseltongue

+0

うーん...すべてのアクティブなスレッドでこのエラーが発生しています:ControlNotFoundError:名前が 'thing_id'と一致するコントロールがありません。何か案は? – Parseltongue

+0

ハハ、いいえ。その文を誤って解釈しました。私がこのプログラムを使用しているアクティブなスレッドに関係なく、エラーを引き起こします。私が作ろうとしているのは自分のためのプログラムです。それは私が穏健な私的なサブディレクトリに関連する本のチャプターを掲示します。 – Parseltongue

関連する問題