我试图从网站上获取一些信息,但没有成功。
问题是只有在点击某个按钮后才会显示数据。
我想要的信息位于此标记中:
<div id="frmContact" class="contactForm hidden"></div>
<div class="btn btn-secondary viewnumber phone-trigger" data-ga-action="header">
<a href="#" rel="nofollow">Ver telefone</a>
<i class="icon"></i>
</div>
这可能与此行有关:
<form action="/noindex/doctor-phone" id="frmPhone" method="post"><input name="__RequestVerificationToken" type="hidden" value="3uFb11EKzbTh4TWoqXk025U7jS7QoV5-od7lSgSBzdu616u82jQAHiOTl2aB3q47aRCIg2CjVCjE6R6bUAqDplAOfeM1" /><input id="entityKey" name="entityKey" type="hidden" value="12898671" /><input id="placeType" name="placeType" type="hidden" value="" /><input id="placeKey" name="placeKey" type="hidden" value="" /></form> <div id="phonePlacer"></div>
但我不知道如何正确使用此__RequestVerificationToken
。
我是否必须使用此信息向服务器发送request以获取电话信息?如果是这样,怎么做?
点击按钮后,会出现弹出窗口(我对info1到info4感兴趣):
我的代码:
page = BeautifulSoup(urllib2.urlopen('http://www.doctoralia.com.br/medico/RANDOM_PROFILE'), "html.parser")
hidden_tags = page.find_all("input", type="hidden")
for tag in hidden_tags:
print tag
输出:
<input name="__RequestVerificationToken" type="hidden" value="gPYstKvmi4xBQsV81ECf5mYe695igvq8E2QqtOgBPqtRybEP74OEbSAe8uDg8dlZCpqib94FIrUoPMnpLTC0tY7kiJE1"/>
<input id="entityKey" name="entityKey" type="hidden" value="14336768"/>
<input id="placeType" name="placeType" type="hidden" value=""/>
<input id="placeKey" name="placeKey" type="hidden" value=""/>
答案 0 :(得分:2)
正如您在“网络”标签中使用Google Chrome的开发工具时所看到的,它会向http://www.doctoralia.com.br/noindex/doctor-phone
发送一个POST请求。此POST请求受CSRF保护,因此要伪造此请求以获取数据非常困难。
由于BeautifulSoup
是HTML 解析器。您无法真正与网页进行互动。如果你真的想获得数据。您应该使用selenium
之类的工具来模拟真实的浏览器。
请记住,数据不受保护只是为了绕过。他们可能不希望数据被删除,这样做可能是违法的。
答案 1 :(得分:1)
使用requests.Session对象非常简单,您只需要从初始页面和几个表单数据中提取__RequestVerificationToken
标记。我使用完整列表的页面来获取数字和医生页面的链接,无论您决定从哪里获得数字,都适用相同的逻辑:
from bs4 import BeautifulSoup
import requests
from urlparse import urljoin
head = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"X-Requested-With": "XMLHttpRequest"}
base = "http://www.doctoralia.com.br/"
with requests.Session() as s:
r = s.get('http://www.doctoralia.com.br/medicos/especialidade/dermatologistas-1314')
page = BeautifulSoup(r.content, "html.parser")
token = page.select_one("input[name=__RequestVerificationToken]"["value"])
hidden_tags = page.select("article.media.doctor")
for tag in hidden_tags:
h3 = tag.select_one("h3")
key = h3.a["data-track-click"]
place = tag.select_one("span[data-location]")["data-location"].split("|", 1)[0]
data = {"__RequestVerificationToken": token,
"entityKey": key,
"placeKey": place}
resp = s.post("http://www.doctoralia.com.br/noindex/doctor-phone", data=data, headers=head)
soup = BeautifulSoup(resp.content,"html.parser")
print(urljoin(base,h3.a["href"]))
print(soup.select_one("li.phone").text.strip())
它会为您提供每位医生的所有链接和电话号码,当您单击按钮时,您在弹出窗口中看到的任何内容都可以解析。基本表单数据是__RequestVerificationToken
和entityKey
,placeKey
似乎不会影响帖子,但不包括它。在这种情况下,标题也不是必需的,但再次添加用户代理并不是一个好主意。您可能希望在请求之间添加休眠,这样如果您提出大量请求,就不会对服务器进行锤击。还看着robots.txt:
User-agent: *
Disallow: /noindex/
Disallow: /usuarios/
Disallow: /users/
Disallow: /utilisateurs/
Disallow: /utenti/
Disallow: /gebruikers/
Disallow: /nutzer/
Disallow: /medical-center/m/
Disallow: /consultant/m/
Disallow: /centro-medico/m/
Disallow: /medico/m/
Disallow: /centre-medical/m/
Disallow: /medicin/m/
Disallow: /centro-medico/m/
Disallow: /medico/m/
Disallow: /centri-medici/m/
Disallow: /medecin/m/
Disallow: /healthpro/m/
Disallow: /facharzt/m/
Disallow: /sanit�tszentrum/m/
Disallow: /clickfav/
Disallow: /clicktlf/
Disallow: /reservas/
Disallow: /citas/
Disallow: /medisch-centrum/m/
Disallow: /deskundige/m/
Disallow: /arzt/m/
Disallow: /klinik/m/
Disallow: /citas/
Disallow: /turnos/
Disallow: /appuntamenti/
Disallow: /appointments/
Disallow: /consultas/
Disallow: /ws/Schedules.asmx/
Disallow: /RESOURCE NOT FOUND/
Disallow: /RESOURCE+NOT+FOUND/
Disallow: /RESOURCE%20NOT%20FOUND/
Disallow: /entities/
没有用户代理限制,您正在抓取的内容不被禁止