0

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

我会举一个具体的例子来说明我正在尝试做的事情,并希望它能澄清一些事情:

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

  2. 在那个网页中,我想填写如下查询:“你要去哪里”应该有纽约市以及出发和到达日期。

  3. 如果从浏览器中使用,我将获得一个下一页,其中包含我刚刚填写的查询的结果,并且我想从该网页中获取价格。

让我们假设可以从 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 data should be bytes or an iterable of bytes. 它不能是 str 类型。” 有谁知道为什么?

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

但是没有这样的网站(当我在浏览器 url 中输入完整地址时)看起来所有结果(无论您的查询是什么或您如何填写表格都无关紧要)出现在同一个网页上:hilton_web_site ...zh_CN/hi/search/findhotels/results.htm?view=LIST

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

非常感谢您的帮助

4

1 回答 1

0

这是希尔顿搜索表单的转储(我指示您如何获取但不能将其全部粘贴到评论部分,所以您可以在这里),我忘了提到您应该检查 Chrome 中的“表单数据”原始数据这是我的错..无论如何..

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

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

  • 搜索查询
  • 到达日期
  • 出发日期
  • _flexibleDates
  • 房间的数量
  • numberOfAdults%5B0%5D
  • numberOfChildren%5B0%5D
  • numberOfAdults%5B1%5D
  • numberOfChildren%5B1%5D
  • numberOfAdults%5B2%5D
  • numberOfChildren%5B2%5D
  • numberOfAdults%5B3%5D
  • numberOfChildren%5B3%5D
  • 促销代码
  • 组码
  • 公司ID
  • _travelAgentRate
  • _aaaRate
  • _aarpRate
  • _seniorRate
  • _governmentRate
  • 报价 ID
  • 书本按钮
  • 搜索类型
  • 房间钥匙启用

这就是整个东西的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 数据中的=or进行 url 编码的。&

这是您无需担心的地方,因为 urllib 会为您完成。但这让您了解 HTTP 请求的工作原理。

于 2013-10-23T09:15:34.193 回答