【问题标题】:Scraping content from AJAX onclick pop-up从 AJAX onclick 弹出窗口中抓取内容
【发布时间】:2014-09-27 20:24:08
【问题描述】:

我正在尝试使用 Python:https://j2c-com.com/Euronaval14/catalogueWeb/catalogue.php?lang=gb 从此页面中转义信息。我对单击单个参展商名称时出现的弹出窗口特别感兴趣。具有挑战性的部分是它使用大量 JavaScript 进行 AJAX 调用来加载数据。

我检查了点击参展商时的网络调用,似乎 AJAX 调用转到此 URL(对于列表中的第一个参展商,“A.I.A.D. and MOD ITALY”):https://j2c-com.com/Euronaval14/catalogueWeb/ajaxSociete.php?cle=D000365D000365&rnd=0.005115277832373977

我了解cle 参数的来源(带有<span> 标签的id),但是,我不太明白rnd 参数的来源。它只是一个随机数吗?我尝试为每个请求提供一个随机数,但返回的 html 缺少弹出窗口的实际内容。

这让我相信rnd 属性不是随机数,或者我需要存在某种类型的 cookie 才能让实际数据通过请求。

到目前为止,这是我的代码,我正在使用 Requests 和 BeautifulSoup 来解析 html:

import random
import decimal
import requests
from bs4 import BeautifulSoup

#base_url = 'https://j2c-com.com/Euronaval14/catalogueWeb/catalogue.php?lang=gb'
base_url = 'https://j2c-com.com/Euronaval14/catalogueWeb/cataloguerecherche.php?listeFavoris=&typeRecherche=1&typeRechSociete=&typeSociete=&typeMarque=&typeDescriptif=&typeActivite=&choixSociete=&choixPays=&choixActivite=&choixAgent=&choixPavillon=&choixZoneExpo=&langue=gb&rnd=0.1410133063327521'


def generate_random_number(i,d):
    "Produce a random between 0 and 1, with 16 decimal digits"
    return str(decimal.Decimal('%d.%d' % (random.randint(0,i),random.randint(0,d))))



r = requests.get(base_url)
soup = BeautifulSoup(r.text)

table = soup.find('table', {'id':'tableResultat'})

trs = table.findAll('tr')


for tr in trs:
    span = tr.find('span')
    cle = span.get('id')

    url = 'https://j2c-com.com/Euronaval14/catalogueWeb/ajaxSociete.php?cle=' + cle + '&rnd=' + generate_random_number(0,9999999999999999)
    pop = requests.post(url)

    print url
    print pop.text

    break

您能否帮助我了解如何成功捕获弹出数据,或者我做错了什么?提前致谢!

【问题讨论】:

    标签: python ajax web-scraping beautifulsoup python-requests


    【解决方案1】:

    这与rnd 参数无关。完全随机,由Math.random() js函数填充。

    正如您所怀疑的,它大约是cookiesPHPSESSID cookie 对于每个后续请求都至关重要。只需启动 requests.Session() 并将其用于您提出的每个请求:

    Session 对象允许你在 要求。它还在从 会话实例。

    ...
    
    # start session
    session = requests.Session()
    
    r = session.get(base_url)
    soup = BeautifulSoup(r.text)
    
    table = soup.find('table', {'id':'tableResultat'})
    trs = table.findAll('tr')
    
    for tr in trs:
        span = tr.find('span')
        cle = span.get('id')
    
        url = 'https://j2c-com.com/Euronaval14/catalogueWeb/ajaxSociete.php?cle=' + cle + '&rnd=' + generate_random_number(0,9999999999999999)
        pop = session.post(url)  # <-- the POST request here contains cookies returned by the first GET call
    
        print url
        print pop.text
    
        break
    

    它会打印(查看 HTML 是否填满了所需的数据):

    https://j2c-com.com/Euronaval14/catalogueWeb/ajaxSociete.php?cle=D000365D000365&rnd=0.1625497943120751
    <table class='divAdresse'>
        <tr>
            <td class='ficheAdresse' valign='top'>Via Nazionale 54<br>IT-00184 - Roma<br><img
                    src='../../intranetJ2C/images/flags/IT.gif' style='margin-right:5px;'>ITALY<br><br>Phone: +39 06 488
                0247 | Fax: +39 06 482 74 76<br><br>Website: <a href='http://www.aiad.it' target='_new'>www.aiad.it</a></td>
        </tr>
    </table>
    <br>
    <b class="divMarque">Contact:</b><br>
    <font class="ficheAdresse"> Carlo Festucci - Secretary General<br>
    <a href="mailto:c.festucci@aiad.it">c.festucci@aiad.it</a></font>
    <br><br>
    <div id='divTexte' class='ficheTexte'></div>
    

    更新。

    您没有在表格中获得其他参展商的结果的原因很难解释,但这里的重点是模拟当您单击浏览器中的行时在后台调用的所有后续 ajax 请求:

    import random
    import decimal
    import requests
    from bs4 import BeautifulSoup
    
    base_url = 'https://j2c-com.com/Euronaval14/catalogueWeb/cataloguerecherche.php?listeFavoris=&typeRecherche=1&typeRechSociete=&typeSociete=&typeMarque=&typeDescriptif=&typeActivite=&choixSociete=&choixPays=&choixActivite=&choixAgent=&choixPavillon=&choixZoneExpo=&langue=gb&rnd=0.1410133063327521'
    fiche_url = 'https://j2c-com.com/Euronaval14/catalogueWeb/fiche.php'
    reload_url = 'https://j2c-com.com/Euronaval14/catalogueWeb/reload.php'
    data_url = 'https://j2c-com.com/Euronaval14/catalogueWeb/ajaxSociete.php'
    
    
    def generate_random_number(i,d):
        "Produce a random between 0 and 1, with 16 decimal digits"
        return str(decimal.Decimal('%d.%d' % (random.randint(0, i),random.randint(0, d))))
    
    
    # start session
    session = requests.Session()
    
    r = session.get(base_url)
    soup = BeautifulSoup(r.content)
    for span in soup.select('table#tableResultat tr span'):
        cle = span.get('id')
    
        session.post(reload_url)
        session.post(fiche_url, data={'page': 'page:catalogue',
                                      'pasFavori': '1',
                                      'listeFavoris': '',
                                      'cle': cle,
                                      'stand': '',
                                      'rnd': generate_random_number(0, 9999999999999999)})
        session.post(reload_url)
        pop = session.post(data_url, data={'cle': cle,
                                           'rnd': generate_random_number(0, 9999999999999999)})
    
        print pop.text
    

    打印:

    <table class='divAdresse'><tr><td class='ficheAdresse' valign='top'>Via Nazionale 54<br>IT-00184 - Roma<br><img src='../../intranetJ2C/images/flags/IT.gif' style='margin-right:5px;'>ITALY<br><br>Phone: +39 06 488 0247 | Fax: +39 06 482 74 76<br><br>Website: <a href='http://www.aiad.it' target='_new'>www.aiad.it</a></td></tr></table><br><b class="divMarque">Contact:</b><br><font class="ficheAdresse"> Carlo Festucci - Secretary General<br><a href="mailto:c.festucci@aiad.it">c.festucci@aiad.it</a></font><br><br><div id='divTexte' class='ficheTexte'></div>
    <table class='divAdresse'><tr><td class='ficheAdresse' valign='top'>An der Faehre 2<br>27809 - Lemwerder<br><img src='../../intranetJ2C/images/flags/DE.gif' style='margin-right:5px;'>GERMANY<br><br>Phone: +49 421 673 30 | Fax: +49 421 673 3115<br><br>Website: <a href='http://www.abeking.com' target='_new'>www.abeking.com</a></td></tr></table><br><b class="divMarque">Contact:</b><br><font class="ficheAdresse"> Thomas Haake - Sales Director Navy</font><br><br><div id='divTexte' class='ficheTexte'></div>
    <table class='divAdresse'><tr><td class='ficheAdresse' valign='top'>Mohamed Bin Khalifa Street (street 15)<br>PO Box 107241<br>107241 - Abu Dhabi<br><img src='../../intranetJ2C/images/flags/AE.gif' style='margin-right:5px;'>UNITED ARAB EMIRATES<br><br>Phone: +971 2 445 5551 | Fax: +971 2 445 0644</td></tr></table><br><b class="divMarque">Contact:</b><br><font class="ficheAdresse"> Pierre Baz - Business Development<br><a href="mailto:pierre.baz@abudhabimar.com">pierre.baz@abudhabimar.com</a></font><br><br><div id='divTexte' class='ficheTexte'></div>
    ...
    

    【讨论】:

    • 看来我说得太早了。我尝试使用 requests.session() 但当我检查 URL 参数中的每个唯一 cle 值时,它只发回第一个参展商的数据(上面的 HTML)。如果你从我上面的代码中删除break,当你通过for tr in trs:循环时,你会得到不同的结果吗?
    • @Abundnce10 不接受答案有点错误,因为答案有助于解决您最初遇到的问题。无论如何,这是一个有趣的挑战 - 请参阅答案的 UPD 部分。谢谢。
    • 你说得对,我的问题应该更明确。感谢您更新您的回复!
    猜你喜欢
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    相关资源
    最近更新 更多