【问题标题】:screen scraping tripadvisor with post request带有发布请求的屏幕抓取tripadvisor
【发布时间】:2013-07-25 20:55:59
【问题描述】:

我正在尝试抓取tripadvisor。假设我想删除这家特定酒店的差评:

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

我只想要“可怕”类别,并且此选择/过滤应由 html 表单控制。 我打算发送一个帖子请求以提交表单。我最初想使用 mechanize 模块中的 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)

【问题讨论】:

    标签: javascript python http-post screen-scraping


    【解决方案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,看看表单的 action field 或 chromes network tab

    打开网络选项卡,单击保留日志,单击产生结果的链接,然后查看请求以确定您应该做什么。

    【讨论】:

    • 谢谢!但问题是我不明白网络选项卡显示给我的是什么。更具体地说,我不知道在哪里寻找帖子参数。您能否详细说明或给我一个教程链接?
    • 行动= “/ SortReviews#点评”,但这指的是代码shoudl是:数据= { “comRdo”: “上”, “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#评测” “filterSegment”:“0 " "filterRating":"1"} requests.post("tripadvisor.com/SortReviews#REVIEWS",data)
    • 你可以使用官方文档developers.google.com/chrome-developer-tools/docs/network你可以在youtube上找到很多关于chrome devtools的教程,比如youtube.com/watch?v=nOEw9iiopwI如果你觉得有用,请考虑投票或接受我的回答
    【解决方案2】:

    如果您想了解网站的 POST 请求一般是如何工作的,您应该检查 Google Chrome 中的元素并切换到网络选项卡。您将能够看到您的 POST 请求通过。

    如果您单击该 POST 请求,您将获得有关您在该 POST 请求中实际发送的信息的详细信息。

    在较低级别上,一旦您检查该元素,您会发现它嵌入在另一个带有以下标记的元素中:

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

    这意味着您需要从该 onclick 方法开始搜索,因为当您单击该可怕的值时,实际发生的就是这种情况。

    如果您只想取回数据,则无需使用任何类型的庞大抓取框架。我个人建议使用 requests 和 lxml。在请求中,您应该发送此帖子请求的方式是:

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

    如果您真的想处理页面上的 javascript,那么您应该使用 SeleniumCasper 进行无头网页浏览。

    【讨论】:

      猜你喜欢
      • 2011-07-29
      • 1970-01-01
      • 2021-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      相关资源
      最近更新 更多