在python中填充一个奇怪的webform

时间:2013-10-23 07:56:54

标签: python html

我正在尝试构建一个填充webform然后从结果网站中提取数据的简单程序,它应该非常简单,经过简短的网络研究(主要来自这个网站)我得出的结论是python将是我的最佳选择。(使用urllib)

我会给出一个我想要做的具体例子,并希望它能澄清一些事情:

  1. 假设我想要一个自动脚本来获取酒店的价格,网站将是: 希尔顿网站

  2. 在该网页中,我想按如下方式填写查询:“你要去哪里”应该有N.Y.C以及出发和到达日期。

  3. 如果在浏览器中使用,我会得到一个下一页,其中包含我刚刚填写的查询结果,我希望从该网页中获取价格。

  4. 让我们假设可以从html源代码中完成数据的抓取。

    嗯,这就是我的想法(很一般的描述......)

    import urllib
    import urllib.request
    
    url = 'http://www3.hilton.com/en/index.html'
    query_args = { 'searchQuery':' New York, NY ', 'arrivalDate':'31 Oct 2013' ,                         'departureDate': '04 Nov 2013' }
    print (query_args)
    data = urllib.parse.urlencode(query_args)
    print (data)
    request = urllib.request.Request(url);
    response = urllib.request.urlopen(request,data)
    html = response.read()
    print (html)
    
    1. 首先,当我发送请求时,我收到以下错误:“TypeError:POST数据应该是字节或可迭代的字节。它不能是str类型。”有谁知道为什么?

    2. 如果我做对了,我会认为我会接受以下网站的回复。 hilton_website最后有urlencode片段(searchQuery = + New + York%2C + NY& arrivalDate = 31 + Oct + 2013& departureDate = 04 + Nov + 2013)

    3. 但是没有这样的网站(当我输入浏览器网址的完整地址时) 它看起来像所有结果(无论你的查询是什么或填写表格无关紧要)出现在同一网页上:hilton_web_site ... en_US / hi / search / findhotels / results.htm?view = LIST < / p>

      那么我做错了什么?我认为填写网络表单的方式。

      非常感谢您的帮助

1 个答案:

答案 0 :(得分:0)

这是一个hiltons搜索表单的转储(其中,我指示你如何获取,但不能将它全部粘贴在评论部分,所以这里你去),我忘了提到你应该检查“表单数据”原始数据在Chrome tho这是我的坏..无论如何..

RAW数据(这样您就可以了解POST请求的工作原理)

请求标头

POST /en_US/hi/search/findhotels/index.htm?WT.bid=Home,,,find_button HTTP/1.1
Host: www3.hilton.com
Connection: keep-alive
Content-Length: 475
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://www3.hilton.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://www3.hilton.com/en/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: mmcore.tst=0.626; ClrCSTO=T; ClrSSID=1382526492268-11812; ClrOSSID=1382526492268-11812; ClrSCD=1382526492268; mmid=-1914085652%7CAQAAAAq0Q+DZtwkAAA%3D%3D; mmcore.pd=-1914085652%7CAQAAAAq0Q+DZtwkAAA%3D%3D; mmcore.srv=ldnvwcgus01; K3R7=3U24QMiCUbjeh65LoEI31TTjisY8czr4zkIUe06gsA4A5lc0bIKrEhQ; GWSESSIONID=qYDpSnSLNFnJ5CrJrwlSWW7CNBHL7vXSMndGmnxghGns1rLjt2lX!-1490734837; __atuvc=1%7C43; mm_pc_HHonorsPoints=false; mm_pers_storage=loggedin%3Ano%7CStayDuration%3A1-2%20nights%7CDaysToBooking%3A0-1%7CSatStay%3Ano%7CChildren%3Ano%7CBrand%3Ahi%7CHHonorsPoints%3Afalse%7CFlexDates%3Afalse%7CPromoCode%3Ano%7Cproperties8%3Ano%7Chotelcode%3Ano; WT_FPC=id=6f7c5181-8354-430b-b943-9bb95bf2c75c:lv=1382490515002:ss=1382490495203

表格数据

searchQuery=N.Y.C&arrivalDate=23+Oct+2013&departureDate=24+Oct+2013&_flexibleDates=on&numberOfRooms=1&numberOfAdults%5B0%5D=1&numberOfChildren%5B0%5D=0&numberOfAdults%5B1%5D=1&numberOfChildren%5B1%5D=0&numberOfAdults%5B2%5D=1&numberOfChildren%5B2%5D=0&numberOfAdults%5B3%5D=1&numberOfChildren%5B3%5D=0&promoCode=&groupCode=&corporateId=&_travelAgentRate=on&_aaaRate=on&_aarpRate=on&_seniorRate=on&_governmentRate=on&offerId=&bookButton=false&searchType=ALL&roomKeyEnable=true

这些是您需要与每个搜索查询一起发送的键(而不是值):

  • SEARCHQUERY
  • arrivalDate
  • departureDate
  • _flexibleDates
  • numberOfRooms
  • numberOfAdults%5B0%5D
  • numberOfChildren%5B0%5D
  • numberOfAdults%5B1%5D
  • numberOfChildren%5B1%5D
  • numberOfAdults%5B2%5D
  • numberOfChildren%5B2%5D
  • numberOfAdults%5B3%5D
  • numberOfChildren%5B3%5D
  • 促销码
  • groupCode
  • corporateId
  • _travelAgentRate
  • _aaaRate
  • _aarpRate
  • _seniorRate
  • _governmentRate
  • OFFERID
  • bookButton
  • 检索类别
  • roomKeyEnable

这就是整个事物的python构建:

from socket import *
s = socket()

POST = 'searchQuery=N.Y.C&arrivalDate=23+Oct+2013&departureDate=......'

header = ''
header += 'POST /en_US/hi/search/findhotels/index.htm?WT.bid=Home,,,find_button HTTP/1.1\r\n'
header += 'Host: www3.hilton.com\r\n'
header += 'Connection: keep-alive\r\n'
header += 'Content-Length: ' + str(len(POST)) + '\r\n'
header += 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n'
header += 'Origin: http://www3.hilton.com\r\n'
header += 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) \r\n'
header += 'Chrome/30.0.1599.101 Safari/537.36\r\n'
header += 'Content-Type: application/x-www-form-urlencoded\r\n'
header += 'Referer: http://www3.hilton.com/en/index.html\r\n'
header += 'Accept-Encoding: gzip,deflate,sdch\r\n'
header += 'Accept-Language: en-US,en;q=0.8\r\n'
header += '\r\n'

s.connect(('www3.hilton.com', 80))
s.send(header+POST)
print(s.recv(8192))

这会给你你想要的东西。 请注意,我遗漏了标题中的cookie字段..通常服务器并不关心它,因为它是一种古老的技术,服务器通常假设如果没有给出cookie,只需给客户端新的和假设它是第一次访问,甚至是第二次访问(从技术角度来看,它是真实的第一页)。

另请注意:

POST变量中的所有数据都必须按以下方式进行URL编码:每对urlencode(key)=urlencode(val)&。请注意我没有对此原始POST数据中的=&进行网址编码。

这是您不必担心的地方,因为urllib为您做到了。但是,这可以让您了解HTTP请求的工作方式。