我正试图抓住tripadvisor。假设我想要抓住这家酒店的糟糕评论:
我只想要“可怕的”类别,这个选择/过滤应该由html表单控制。 我打算发送一个帖子请求来提交表单。我原本想在机械化模块中使用br.submit(),但后来发现它不支持javascript。所以我希望使用post请求绕过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控制控制,但奇怪的是类别或单选按钮具有相同的值'on'。 让我们在选择其中一个类别之前和之后看到控件属性:
之前:
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
所以在选择“可怕”类别之后,控件的值是“on”,如果我选择了任何其他类别,它将是相同的。当我在comRdo控件中打印出项目时:只有'id'是不同的,其他每个属性都是同样的:
<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)
答案 0 :(得分: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
你也会发现你实际上是在提交错误的网址,看看表单的动作字段或chromes网络标签
打开网络选项卡,单击保留日志,单击生成结果的链接,然后查看请求以确定应该执行的操作。
答案 1 :(得分: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})