0

tripadvisorをスクレイピングしようとしています。この特定のホテルの悪いレビューをかき集めたいとします。

http://www.tripadvisor.com/Hotel_Review-g31441-d224344-Reviews-Hilton_Garden_Inn_Bentonville-Bentonville_Arkansas.html#REVIEWS

「ひどい」カテゴリのみが必要であり、この選択/フィルタリングは html フォームで制御する必要があります。フォームを送信するために投稿リクエストを送信する予定です。私はもともと mechanize モジュールから br.submit() を使用したかったのですが、後でそれが javascript をサポートしていないことがわかりました。したがって、投稿リクエストを使用してJavaScriptをバイパスしたいと考えています。

しかし、mechanize を使用して関連するコントロールを表示すると、ラジオ ボタンの値は同じになります。これが私のコードです:

br = mechanize.Browser()
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.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]
br.open("http://www.tripadvisor.com/Hotel_Review-g31441-d224344-Reviews-Hilton_Garden_Inn_Bentonville-Bentonville_Arkansas.html#REVIEWS")

for f in br.forms():
    print f

関連するフォームとその中のコントロールは次のとおりです。

 <POST http://www.tripadvisor.com/SortReviews#REVIEWS application/x-www-form-urlencoded
   <RadioControl(segRdo=[on, on, on, on, on])>
   <RadioControl(comRdo=[on, on, on, on, on])>
   <HiddenControl(returnTo=__2F__Hotel__5F__Review__2D__g31441__2D__d224344__2D__Reviews__2D__Hilton__5F__Garden__5F__Inn__5F__Bentonville__2D__Bentonville__5F__Arkansas__2E__html#REVIEWS) (readonly)
   <HiddenControl(filterSegment=0) (readonly)>
   <HiddenControl(filterRating=1) (readonly)>>

したがって、評価は comRdo コントロールによって制御されますが、奇妙なことに、カテゴリまたはラジオ ボタンの値が同じ「オン」になっています。カテゴリの 1 つを選択する前後のコントロール プロパティを見てみましょう。

前:

control_com=br.form.find_control("comRdo","radio")
print control_com.name,control_com.value,control_com.type
comRdo [] radio

後:

(br.form.find_control("comRdo","radio")).items[4].selected=True
print control_com.name,control_com.value,control_com.type
comRdo ['on'] radio

したがって、「ひどい」カテゴリを選択した後、コントロールの値は「オン」になります。これは、他のカテゴリを選択した場合と同じです。

<Item name='on' id='com1' id='com1' type='radio' class='radio' value='on' name='comRdo'>
<Item name='on' id='com2' id='com2' type='radio' class='radio' value='on' name='comRdo'>
...

では、これはどのように機能しますか?? すべてのラジオボタンが同じ値を持っているため、サーバーはどのラジオボタンを選択したかをどのように判断できますか?? 投稿データを準備してリクエストに送信しましたが、期待どおりに動作しません。res は、フィルタリング/投稿リクエストのないものと同じ内容です

form={"comRdo":"on"}
req=mechanize.Request("http://www.tripadvisor.com/Hotel_Review-g31441-d224344-Reviews-Hilton_Garden_Inn_Bentonville-Bentonville_Arkansas.html#REVIEWS",urllib.urlencode(form))
req.add_header('Content-Type','application/x-www-form-urlencoded')
cj.add_cookie_header(req)
res=mechanize.urlopen(req)

また、他の投稿データでコードを試しました:

form={"comRdo":["on","on","on","on","on","*on"]}

また

form={"filterSegment":"0","filterRating":"1"}

誰かがこれについて私を助けてくれますか? このページは同じ値のラジオ ボタンでどのように機能しますか? プログラムでレビューをフィルタリングするにはどうすればよいですか?? 前もって感謝します!


Slater Tyranus と Diadara のおかげで、次のコードが機能しました。

form={"returnTo":"__2F__Hotel__5F__Review__2D__g31441__2D__d224344__2D__Reviews__2D__Hilton__5F__Garden__5F__Inn__5F__Bentonville__2D__Bentonville__5F__Arkansas__2E__html#REVIEWS","filterSegment":"0","filterRating":"1"}
url="http://www.tripadvisor.com/SortReviews#REVIEWS"
headers={'content-type':'application/x-www-form-urlencoded'}
r=requests.post(url,data=form)
soup=BeautifulSoup(r.content)
4

2 に答える 2

1

他の回答が指摘しているように、ネットワークタブを見て、ブラウザが行っているリクエストを把握してください。この場合、フォームには複数の要素があり、必要なページを生成するにはそれらすべてが必要です。だからあなたは使うべきです

これらすべての値

comRdo:on
returnTo:__2F__Hotel__5F__Review__2D__g31441__2D__d224344__2D__Reviews__2D__Hilton__5F__Garden__5F__Inn__5F__Bentonville__2D__Bentonville__5F__Arkansas__2E__html#REVIEWS
filterSegment:0
filterRating:1

また、実際には間違った URL に送信していることがわかります。フォームのアクション フィールドまたはクロム ネットワーク タブを見てください。

[ネットワーク] タブを開き、[ログの保存] をクリックし、結果を生成するリンクをクリックしてから、リクエストを見て何をすべきかを判断します。

于 2013-07-25T21:29:37.767 に答える
0

サイトの POST リクエストが一般的にどのように機能するかを知りたい場合は、Google Chrome の要素を調べて、ネットワーク タブに切り替える必要があります。POST リクエストが通過するのを確認できます。

その POST リクエストをクリックすると、その POST リクエストで実際に送信している情報の詳細が表示されます。

下位レベルでは、要素を調べると、次のタグを持つ別の要素に埋め込まれていることがわかります。

onclick="document.forms.REVIEW_FILTER_FORM.filterRating.value='1';document.forms.REVIEW_FILTER_FORM.submit();"

これは、その onclick メソッドで検索を開始する必要があることを意味します。これは、ひどい値をクリックしたときに実際に起こっていることだからです。

データを取り戻すことだけが目的であれば、大がかりなスクレイピング フレームワークを使用する必要はありません。個人的には、リクエストと lxml を使用することをお勧めします。リクエストでは、この投稿リクエストを送信する方法は次のとおりです。

requests.post(url, data={"filterRating":1})

実際にページ上の JavaScript を処理したい場合は、ヘッドレス Web ブラウジングにSeleniumまたはCasperを使用する必要があります。

于 2013-07-25T20:59:07.433 に答える