4

次のリンクを機械化する際に問題が発生しました。これが私が目指していることの抜粋です:

for link in mech.links(url_regex='/test/'):
    mech.follow_link(link)

    // Do some processing on that link

    mech.back()

機械化の例によると、これは問題なく機能するはずです。しかし、そうではありません。.back()を呼び出しても、アクセスするリンクがさらにある場合でも、ループは終了します。mech.follow_link(link)とmech.back()をコメントアウトして、print link.textに置き換えると、50個ほどのリンクがすべて出力されます。ただし...mech.follow_linkのコメントを解除するとすぐに、最初のfollow_linkの直後にループが終了します。back()は機能しており、mech.title()を印刷してから、mech.back()を呼び出してmech.title()をもう一度印刷すると、最初のタイトル、次に「戻る」ページのタイトルが明確に表示されます。私は本当に混乱しています、そしてこれはそれがドキュメントで行われている方法です。何が起こっているのかわからない。

4

3 に答える 3

3

海賊、私は同意します。これは起こってはならないことです。あなたは、wwwsearch.sourceforge.net/mechanize/ のドキュメント ページに記載されていることとほとんど同じことを行っています。私はあなたと同様のコードを試しましたが、最初の反復後に停止した同じ結果が得られました。

ただし、回避策を見つけました。つまり、リンク URL を links() からリストに保存し、そのリストから各 URL をたどります。

from mechanize import Browser
br = Browser()
linklist = []
br.open(your_page_here)
for link in br.links(url_regex='/test/'): linklist.append(link.url)
for url in linklist:
    br.open(url)
    print br.title()

それは醜いので、そうする必要はありませんが、うまくいくようです。

私はこのようなバグの機械化にはあまり興奮していません (そして、機械化が 2 つの送信ボタンをうまく処理できなかったという問題もありました)、インストールは非常に簡単で、移植性が高く、オフラインで実行でき (単純な cron ジョブを介して) 簡単に比較できますSelenium (seleniumhq dot org) のような他のテスト フレームワークに変換できます。これは見栄えは良いですが、実際にセットアップして使用するにはもっと複雑なようです。

于 2009-11-07T01:34:11.627 に答える
1

リンク リストを保存するよりもはるかに簡単な回避策は、単純に 2 つ目の Browser オブジェクトを取得することです。これは、「実際の」ブラウザで 2 番目のタブを開くのと同じと見なすことができます。認証も必要な場合は、ブラウザー インスタンス間で Cookie jar を共有する必要があります。

import mechanize
import cookielib

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

br.open("http://yoursite.com/login")
br.select_form(nr=0)
br["username"] = "..."   # The hash keys are the names of the form fields
br["password"] = "..."
br.submit()    # This will save the authentication cookie to the shared cookie jar!
br.open("http://yoursite.com/page-to-parse")

for link in br.links(url_regex="/link_text"):
    req = br.click_link(url=link.url)
    html = br2.open(req).read()

最初のインスタンスから要求オブジェクトを取得し、2 番目のインスタンスでそれを送信する必要があることに注意してください。これは、「実際の」ブラウザで「新しいウィンドウ/タブで開く」コマンドと同等です。

于 2012-09-15T10:26:23.300 に答える
0

ページにアクセスするたびに、 links() イテレータがその新しいページのリンクにリセットされます。したがって、別の変数に保存する必要がありlinks = mech.links()ます. これは mechanize.Browser のバグではなく、ステートフル オブジェクトを持つことの副作用です。links = list(mech.links())print >>sys.stderr, '# links: %d' % len(links)

これで遊んでいるときに気づいたもう 1 つの問題は、元のページ コンテンツの設定に使用されていた場合は使用されないため、最初から設定されていないmech.back()場合は使用できないことです。その場合、最初のリクエストを明示的に何かに設定する必要があります: 。それ以外の場合は を取得します。mech.requestmech.set_response()mech.request = mechanize.Request('about://config')BrowserStateError: already at start of history

完全を期すために、私が行ったように誰かが Google 検索からここに来ている場合は、ヘッダーmechanize.make_responseを少なくとも to に設定するか、(('content-type', 'text/html'),)or mech.viewing_htmlwill still Falseand mech.links()will raiseに設定してBrowserStateError("not viewing HTML")ください。

于 2015-01-27T06:24:20.927 に答える