问题
我有以下问题:我需要使用以下link搜索有关公司的一些信息。
我需要做的是search by entity name
,search type
是“开头”下拉值。我还希望在Display number of items to view
部分中看到每页的“所有项目”。例如,如果我在“输入名称”文本框中输入“google”,则脚本应返回名称以“google”开头的公司列表(尽管这只是我想要做的事情的起点) )
问题: 我应该如何使用Python来做到这一点?我找到了以下帖子:Using Python to ask a web page to run a search
我在第一个答案中尝试了这个例子,代码放在下面:
from bs4 import BeautifulSoup as BS
import requests
protein='Q9D880'
text = requests.get('http://www.uniprot.org/uniprot/' + protein).text
soup = BS(text)
MGI = soup.find(name='a', onclick="UniProt.analytics('DR-lines', 'click', 'DR-MGI');").text
MGI = MGI[4:]
print protein +' - ' + MGI
上述代码有效,因为UniPort
网站包含analytics
,其中包含这些参数。但是,我使用的网站没有这个。
我也尝试过与此主题中第一个答案相同的事情:how to submit query to .aspx page in python
但是,第一个答案中提供的示例代码在我的机器(带有Python 2.7的Ubuntu 12.4)上不起作用。由于我正在处理不同的aspx网站,我也不清楚应该有哪些值。
我如何使用Python以某些标准开始搜索(不确定这是正确的网络术语,可能是提交表单吗?)?
我来自C ++背景,并没有做任何网络内容。我也在学习Python。非常感谢任何帮助。
首次编辑:
在@Kabie的帮助下,我收集了以下代码(试图了解它是如何工作的):
import requests
from lxml import etree
URL = 'http://corp.sec.state.ma.us/CorpWeb/CorpSearch/CorpSearch.aspx'
#With get_fields(), we fetched all <input>s from the form.
def get_fields():
res = requests.get(URL)
if res.ok:
page = etree.HTML(res.text)
fields = page.xpath('//form[@id="Form1"]//input')
return { e.attrib['name']: e.attrib.get('value', '') for e in fields }
#hard code some selects from the Form
def query(data):
formdata = get_fields()
formdata.update({
'ctl00$MainContent$ddRecordsPerPage':'25',
}) # Hardcode some <select> value
formdata.update(data)
res = requests.post(URL, formdata)
if res.ok:
page = etree.HTML(res.text)
return page.xpath('//table[@id="MainContent_SearchControl_grdSearchResultsEntity"]//tr')
def search_by_entity_name(entity_name, entity_search_type='B'):
return query({
'ctl00$MainContent$CorpSearch':'rdoByEntityName',
'ctl00$MainContent$txtEntityName': entity_name,
'ctl00$MainContent$ddBeginsWithEntityName': entity_search_type,
})
result = search_by_entity_name('google')
上面的代码放在一个名为query.py
的脚本中。我收到以下错误:
追踪(最近一次通话): 文件“query.py”,第39行,在 result = search_by_entity_name('google')
在search_by_entity_name中文件“query.py”,第36行 'ctl00 $ MainContent $ ddBeginsWithEntityName':entity_search_type,
文件“query.py”,第21行,在查询中 formdata.update({
AttributeError:'NoneType'对象没有属性'update'
在我看来搜索不成功?为什么呢?
答案 0 :(得分:4)
您可以检查页面以找出需要发布的所有字段。 Chrome DevTools
有a nice tutorial。 FireFox上的FireBug
或Opera上的DragonFly
等其他工具也会在我推荐DevTools
时完成工作。
发布查询后。在Network
面板中,您可以看到实际发送的表单数据。在这种情况下:
__EVENTTARGET:
__EVENTARGUMENT:
__LASTFOCUS:
__VIEWSTATE:5UILUho/L3O0HOt9WrIfldHD4Ym6KBWkQYI1GgarbgHeAdzM9zyNbcH0PdP6xtKurlJKneju0/aAJxqKYjiIzo/7h7UhLrfsGul1Wq4T0+BroiT+Y4QVML66jsyaUNaM6KNOAK2CSzaphvSojEe1BV9JVGPYWIhvx0ddgfi7FXKIwdh682cgo4GHmilS7TWcbKxMoQvm9FgKY0NFp7HsggGvG/acqfGUJuw0KaYeWZy0pWKEy+Dntb4Y0TGwLqoJxFNQyOqvKVxnV1MJ0OZ4Nuxo5JHmkeknh4dpjJEwui01zK1WDuBHHsyOmE98t2YMQXXTcE7pnbbZaer2LSFNzCtrjzBmZT8xzCkKHYXI31BxPBEhALcSrbJ/QXeqA7Xrqn9UyCuTcN0Czy0ZRPd2wabNR3DgE+cCYF4KMGUjMUIP+No2nqCvsIAKmg8w6Il8OAEGJMAKA01MTMONKK4BH/OAzLMgH75AdGat2pvp1zHVG6wyA4SqumIH//TqJWFh5+MwNyZxN2zZQ5dBfs3b0hVhq0cL3tvumTfb4lr/xpL3rOvaRiatU+sQqgLUn0/RzeKNefjS3pCwUo8CTbTKaSW1IpWPgP/qmCsuIovXz82EkczLiwhEZsBp3SVdQMqtAVcYJzrcHs0x4jcTAWYZUejvtMXxolAnGLdl/0NJeMgz4WB9tTMeETMJAjKHp2YNhHtFS9/C1o+Hxyex32QxIRKHSBlJ37aisZLxYmxs69squmUlcsHheyI5YMfm0SnS0FwES5JqWGm2f5Bh+1G9fFWmGf2QeA6cX/hdiRTZ7VnuFGrdrJVdbteWwaYQuPdekms2YVapwuoNzkS/A+un14rix4bBULMdzij25BkXpDhm3atovNHzETdvz5FsXjKnPlno0gH7la/tkM8iOdQwqbeh7sG+/wKPqPmUk0Cl0kCHNvMCZhrcgQgpIOOgvI2Fp+PoB7mPdb80T2sTJLlV7Oe2ZqMWsYxphsHMXVlXXeju3kWfpY+Ed/D8VGWniE/eoBhhqyOC2+gaWA2tcOyiDPDCoovazwKGWz5B+FN1OTep5VgoHDqoAm2wk1C3o0zJ9a9IuYoATWI1yd2ffQvx6uvZQXcMvTIbhbVJL+ki4yNRLfVjVnPrpUMjafsnjIw2KLYnR0rio8DWIJhpSm13iDj/KSfAjfk4TMSA6HjhhEBXIDN/ShQAHyrKeFVsXhtH5TXSecY6dxU+Xwk7iNn2dhTILa6S/Gmm06bB4nx5Zw8XhYIEI/eucPOAN3HagCp7KaSdzZvrnjbshmP8hJPhnFhlXdJ+OSYDWuThFUypthTxb5NXH3yQk1+50SN872TtQsKwzhJvSIJExMbpucnVmd+V2c680TD4gIcqWVHLIP3+arrePtg0YQiVTa1TNzNXemDyZzTUBecPynkRnIs0dFLSrz8c6HbIGCrLleWyoB7xicUg39pW7KTsIqWh7P0yOiHgGeHqrN95cRAYcQTOhA==
__SCROLLPOSITIONX:0
__SCROLLPOSITIONY:106
__VIEWSTATEENCRYPTED:
__EVENTVALIDATION:g2V3UVCVCwSFKN2X8P+O2SsBNGyKX00cyeXvPVmP5dZSjIwZephKx8278dZoeJsa1CkMIloC0D51U0i4Ai0xD6TrYCpKluZSRSphPZQtAq17ivJrqP1QDoxPfOhFvrMiMQZZKOea7Gi/pLDHx42wy20UdyzLHJOAmV02MZ2fzami616O0NpOY8GQz1S5IhEKizo+NZPb87FgC5XSZdXCiqqoChoflvt1nfhtXFGmbOQgIP8ud9lQ94w3w2qwKJ3bqN5nRXVf5S53G7Lt+Du78nefwJfKK92BSgtJSCMJ/m39ykr7EuMDjauo2KHIp2N5IVzGPdSsiOZH86EBzmYbEw==
ctl00$MainContent$hdnApplyMasterPageWitoutSidebar:0
ctl00$MainContent$hdn1:0
ctl00$MainContent$CorpSearch:rdoByEntityName
ctl00$MainContent$txtEntityName:GO
ctl00$MainContent$ddBeginsWithEntityName:M
ctl00$MainContent$ddBeginsWithIndividual:B
ctl00$MainContent$txtFirstName:
ctl00$MainContent$txtMiddleName:
ctl00$MainContent$txtLastName:
ctl00$MainContent$txtIdentificationNumber:
ctl00$MainContent$txtFilingNumber:
ctl00$MainContent$ddRecordsPerPage:25
ctl00$MainContent$btnSearch:Search Corporations
ctl00$MainContent$hdnW:1920
ctl00$MainContent$hdnH:1053
ctl00$MainContent$SearchControl$hdnRecordsPerPage:
我发布的内容是Begin with 'GO'
。此网站是使用WebForms
构建的,因此有长__VIEWSTATE
和__EVENTVALIDATION
个字段。我们也需要发送它们。
现在我们准备进行查询了。首先,我们需要获得一个空白表格。下面的代码是用Python 3.3编写的,我认为它们应该仍然适用于2.x。
import requests
from lxml import etree
URL = 'http://corp.sec.state.ma.us/CorpWeb/CorpSearch/CorpSearch.aspx'
def get_fields():
res = requests.get(URL)
if res.ok:
page = etree.HTML(res.text)
fields = page.xpath('//form[@id="Form1"]//input')
return { e.attrib['name']: e.attrib.get('value', '') for e in fields }
使用get_fields()
,我们从表单中获取了所有<input>
个。请注意,还有<select>
个,我只会对它们进行硬编码。
def query(data):
formdata = get_fields()
formdata.update({
'ctl00$MainContent$ddRecordsPerPage':'25',
}) # Hardcode some <select> value
formdata.update(data)
res = requests.post(URL, formdata)
if res.ok:
page = etree.HTML(res.text)
return page.xpath('//table[@id="MainContent_SearchControl_grdSearchResultsEntity"]//tr')
现在我们有一个通用的query
函数,让我们为特定的函数创建一个包装器。
def search_by_entity_name(entity_name, entity_search_type='B'):
return query({
'ctl00$MainContent$CorpSearch':'rdoByEntityName',
'ctl00$MainContent$txtEntityName': entity_name,
'ctl00$MainContent$ddBeginsWithEntityName': entity_search_type,
})
此特定示例网站使用一组<radio>
来确定要使用的字段,因此这里需要'ctl00$MainContent$CorpSearch':'rdoByEntityName'
。你可以自己制作search_by_individual_name
等其他人。
有时,网站需要更多信息来验证查询。到那时,您可以添加一些custom headers,例如Origin
,Referer
,User-Agent
来模仿浏览器。
如果网站使用JavaScript生成表单,则需要的不仅仅是requests
。 PhantomJS
是制作浏览器脚本的好工具。如果您想在Python中执行此操作,可以将PyQt
与qtwebkit
一起使用。
<强>更新强>:
看来网站阻止我们的Python脚本在昨天之后访问它。所以我们不得不假装成浏览器。如上所述,我们可以添加自定义标头。我们首先在标题中添加User-Agent
字段,看看发生了什么。
res = requests.get(URL, headers={
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36',
})
现在...... res.ok
返回True
!
因此,我们只需要在res = requests.get(URL)
中的get_fields()
和res = requests.post(URL, formdata)
中的query()
中添加此标头。以防万一,将'Referer':URL
添加到后者的标题中:
res = requests.post(URL, formdata, headers={
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36',
'Referer':URL,
})