Skip to main content
 首页 » 编程设计

python之用于 python 中动态表单的 Web Scraper

2024年08月25日42thcjp

我正在尝试填写此网站的表格http://www.marutisuzuki.com/Maruti-Price.aspx .

它由三个下拉列表组成。一是汽车型号,二是州,三是城市。前两个是静态的,第三个,城市是根据州的值动态生成的,有一个运行的 onclick java 脚本事件,它获取州中相应城市的值。

我熟悉 python 中的 mechanize 模块。我遇到了几个链接,告诉我无法在 Mechanize 中处理动态内容。但是这个链接http://toddhayton.com/2014/12/08/form-handling-with-mechanize-and-beautifulsoup/在“动态添加项目”部分指出我可以使用 mechanize 来处理动态内容,但我不理解其中的这行代码

item = Item(br.form.find_control(name='searchAuxCountryID'),{'contents': '3', 'value': '3', 'label': 3})

这行代码中的“Item”对应的是表单中的city字段。我遇到了 selenium 模块,它可以帮助我处理动态下拉列表。但是我无法在其文档或任何关于如何使用它的好博客中找到任何内容。

有人可以建议我如何为不同的型号、州和城市提交此表格吗?任何有关如何解决此问题的链接将不胜感激。关于如何提交表单的 python 示例代码将很有帮助。提前致谢。

请您参考如下方法:

如果您在开发人员工具中查看发送到该站点的请求,您会看到在您选择状态后立即发送了一个 POST。发回的响应具有填充了城市下拉列表中的值的表单。

因此,要在您的脚本中复制它,您需要如下内容:

  • 打开页面
  • 选择表格
  • 为模型和状态选择值
  • 提交表格
  • 从发回的回复中选择表单
  • 为城市选择值(现在应该填充)
  • 提交表格
  • 解析结果表的响应

这看起来像:

#!/usr/bin/env python                                                                                                                                                                 
 
import re 
import mechanize 
 
from bs4 import BeautifulSoup 
 
def select_form(form): 
    return form.attrs.get('id', None) == 'form1' 
 
def get_state_items(browser): 
    browser.select_form(predicate=select_form) 
    ctl = browser.form.find_control('ctl00$ContentPlaceHolder1$ddlState') 
    state_items = ctl.get_items() 
    return state_items[1:] 
 
def get_city_items(browser): 
    browser.select_form(predicate=select_form) 
    ctl = browser.form.find_control('ctl00$ContentPlaceHolder1$ddlCity') 
    city_items = ctl.get_items() 
    return city_items[1:] 
 
br = mechanize.Browser() 
br.open('http://www.marutisuzuki.com/Maruti-Price.aspx')     
br.select_form(predicate=select_form) 
br.form['ctl00$ContentPlaceHolder1$ddlmodel'] = ['AK'] # model = Maruti Suzuki Alto K10                                                                                               
 
for state in get_state_items(br): 
    # 1 - Submit form for state.name to get cities for this state                                                                                                                     
    br.select_form(predicate=select_form) 
    br.form['ctl00$ContentPlaceHolder1$ddlState'] = [ state.name ] 
    br.submit() 
 
    # 2 - Now the city dropdown is filled for state.name                                                                                                                              
    for city in get_city_items(br): 
        br.select_form(predicate=select_form) 
        br.form['ctl00$ContentPlaceHolder1$ddlCity'] = [ city.name ] 
        br.submit() 
 
        s = BeautifulSoup(br.response().read()) 
        t = s.find('table', id='ContentPlaceHolder1_dtDealer') 
        r = re.compile(r'^ContentPlaceHolder1_dtDealer_lblName_\d+$') 
 
        header_printed = False 
        for p in t.findAll('span', id=r): 
            tr = p.findParent('tr') 
            td = tr.findAll('td') 
 
            if header_printed is False: 
                str = '%s, %s' % (city.attrs['label'], state.attrs['label']) 
                print str 
                print '-' * len(str) 
                header_printed = True 
 
            print ' '.join(['%s' % x.text.strip() for x in td])