【问题标题】:Selenium-webdriver for parsing (Ruby)用于解析的 Selenium-webdriver (Ruby)
【发布时间】:2013-08-30 06:56:16
【问题描述】:

所以,这里是website(先翻译成英文),它使用javascript显示公司信息(您需要点击“地址和电话号码”)。我是用 selenium 完成的(点击链接),现在我正在尝试使用 css 选择器收集有关这些公司(电话、地址等)的信息并保存到数据库中。但是我无法将信息正确地保存到数据库中,因为我无法将有关公司的信息保存在所需的变量中。

这是我的代码(错了):

require 'rubygems'
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :firefox
driver.get 'http://www.ypag.ru/cat/komp249/page0.html'


driver.find_elements(:css, '.p2 div a').each {|link| link.click}
driver.find_elements
(:css, '.p3 a, .firm, .p2 table tr:nth-child(1) .p, .p2 table tr:nth-child(2) .p,
p2 table tr:nth-child(3) .p, .p2 table tr:nth-child(4) .p').each {|n,r,c,k,l,m| 
name = n
region = r
field1 = c
field1 k
field1 l
field1 m }

我的目的是将每个css选择器保存在正确的变量中,可以吗? 我已经问过这个question,但是我没有地址、电话等的css选择器。

如果我应该添加其他信息,请告诉我

【问题讨论】:

  • 我不太明白你想要达到什么目的。这会运行吗?我会担心“driver.find_elements(:css, '.p2 div a').each {|link| link.click}”会抛出陈旧的对象异常
  • 请访问这个网站,也许你会明白我想要什么。"driver.find_elements(:css, '.p2 div a').each {|link| link.click}"打开页面上的所有 javascript 链接。然后我尝试使用 css 选择器选择有关公司的所有信息。之后,我想将信息保存在不同的变量中,因为如果我不这样做,信息将无法正确保存到数据库中

标签: javascript ruby parsing selenium selenium-webdriver


【解决方案1】:

第一个 findElements 返回 20 个项目,您的代码块将点击每个项目。

但是,您的第二个 findElements 从您的代码块返回 48 个项目,我不明白您的代码块试图实现什么。

'.p3 a, .firm, .p2 表 tr:nth-child(1) .p, .p2 表 tr:nth-child(2) .p, p2 table tr:nth-child(3) .p, .p2 table tr:nth-child(4) .p' css 选择器返回所有匹配的元素(“,”用作“或”分隔符)。

但是,迭代数组一次只返回一个元素。您是否认为您可以在每次迭代中访问一家公司的所有字段?如果是这样,你不能。

使用这将返回 20 个地址块;

driver.find_elements
(:css, 'div[id*='adressSelector']')

你可以迭代这些,执行 findElement 来获取你想要的字段。

【讨论】:

    【解决方案2】:

    页面的 html 不是很好 - 即没有很好的标识符来关联数据。例如,只有相对定位允许您将公司名称与地址相关联。

    下面的解决方案对文本的位置进行了假设,这很脆弱,但这是我能想到的最好的。

    require 'rubygems'
    require 'selenium-webdriver'
    
    driver = Selenium::WebDriver.for :firefox
    driver.navigate.to 'http://www.ypag.ru/cat/komp249/page0.html'
    
    # The table that contains all of the data
    # This xpath is not ideal (brittle) but I could not find a better identifier)
    table = driver.find_element(:xpath, '/html/body/table[4]/tbody/tr/td[2]/table')
    
    # Expand all of the address links
    table.find_elements(:css, 'a[href *= loadadress]').each(&:click)
    
    # Get all of the rows that contain data
    # Need to ignore blanks, ads, etc.
    data_elements = table.find_elements(:xpath, './tbody/tr').keep_if do |row|
      row.find_elements(:css, '.p3, .p, .p2').length > 0
    end
    
    # Of the rows we have, each set of three rows represents a company
    # Iterate through each set of three rows to collect data
    data_elements.each_slice(3) do |company|
      name = company[0].find_element(:css, '.p3').text
      firm = company[0].find_element(:css, '.firm').text
      firm_split = firm.split(' » ')
      country = firm_split[0]
      city = firm_split[1]
    
      description = company[1].text
    
      # Get the address values matching, using the icons to determine the rows meaning
      # Note that not every company has each detail, in which case the value will be ''
      url = ''
      email = ''
      phone = ''
      address = ''
    
      # Wait to ensure the address block has been loaded
      wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
      begin
        element = wait.until { company[2].find_element(:css, 'div[id*=adressSelector]') }
      end
    
      sub_table_data = company[2].find_elements(:css, 'div[id*=adressSelector] tr') 
      sub_table_data.each do |row|
        cells = row.find_elements(:css, 'td')
        case cells[0].find_element(:css, 'img').attribute('src')
          when /papers/
            url = cells[1].text
          when /mail/
            email = cells[1].text
          when /mobile/
            phone = cells[1].text               
          when /map/
            address = cells[1].text                     
        end
      end
    
      # Output the results (or whatever you want them for)
      puts name
      puts country
      puts city
      puts description
      puts url
      puts email
      puts phone
      puts address
      puts
    end
    

    作为一个例子,上面的代码将给出关于第一家公司的以下详细信息(注意这是来自翻译成英文的页面):

    Storm-Print
    Russia »Moscow
    Printing Services: stationery, flyers, leaflets, brochures.
    http://www.storm-print.ru
    info@storm-print.ru
    +7 (495) 101-37-62 multichannel Fax: +7 (495) 101-37-62 multichannel
    Russia "Moscow ul.Suschevsky shaft 16, page 4, 127018
    

    作为参考,公司的 html 如下所示:

    <tr>
       <td align="left" class="p3">
          <a href="http://www.msyp.ru/cat/kompaniy992511/s-779665944.html">
             <font>
                <font class="">
                   Storm-Print
                </font>
             </font>
          </a>
       </td>
       <td align="right" class="firm">
          <font>
             <font>
                 Russia >
                 Moscow 
             </font>
          </font>
       </td>
    </tr>
    <tr>
       <td align="left" colspan="2" width="100%" class="p">
          <font>
             <font class="">
                 Printing Services: stationery, flyers, leaflets, brochures. 
             </font>
          </font>
          <br>
       </td>
    </tr>
    <tr>
       <td colspan="2" align="right">
          <font>
             <font>
                Rating: 
             </font>
          </font>
          <a class="iframe2" href="reit/r.php?id=992511">
             <img src="fon/star_reit_off.png" border="0">
             <img src="fon/star_reit_off.png" border="0">
             <img src="fon/star_reit_off.png" border="0">
             <img src="fon/star_reit_off.png" border="0">
             <img src="fon/star_reit_off.png" border="0">
          </a>
       </td>
    </tr>
    <tr>
       <td colspan="2">
          <table class="p2" border="0" width="100%" cellpadding="0" cellspacing="0">
             <tbody>
                <tr>
                   <td align="left">
                      <div id="adressSelector992511">
                         <table>
                            <tbody>
                               <tr>
                                  <td>
                                     <img src="http://www.ypag.ru/fon/papers.gif" border="0">
                                  </td>
                                  <td class="p">
                                     <a href="http://www.storm-print.ru" target="_blank">
                                        <font>
                                           <font class="">
                                              http://www.storm-print.ru
                                           </font>
                                        </font>
                                     </a>
                                  </td>
                               </tr>
                               <tr>
                                  <td>
                                     <img src="http://www.ypag.ru/fon/mail.gif" border="0">
                                  </td>
                                  <td class="p">
                                     <a href="mailto:info@storm-print.ru">
                                        <font>
                                           <font class="">
                                              info@storm-print.ru
                                           </font>
                                        </font>
                                     </a>
                                  </td>
                               </tr>
                               <tr>
                                  <td>
                                     <img src="http://www.ypag.ru/fon/mobile.gif" border="0">
                                  </td>
                                  <td class="p">
                                     <font>
                                        <font class="">
                                           +7 (495) 101-37-62 multichannel Fax: +7 (495) 101-37-62 multichannel
                                        </font>
                                     </font>
                                  </td>
                               </tr>
                               <tr>
                                  <td>
                                     <img src="http://www.ypag.ru/fon/map.gif" border="0">
                                  </td>
                                  <td class="p">
                                     <font>
                                        <font class="">
                                           Russia "Moscow ul.Suschevsky shaft 16, page 4, 127018
                                        </font>
                                     </font>
                                  </td>
                               </tr>
                               <tr>
                                  <td>
                                     <img src="http://ypag.ru/fon/editdelete.png" border="0">
                                  </td>
                                  <td align="left" class="p">
                                     <a href="http://www.ypag.ru/edit_kompany.php?idkomp=992511&amp;c=3770450052" target="_blank" onclick="popupWin = window.open(this.href, 'contacts', 'location,width=600,height=500,top=0,scrollbars=yes'); popupWin.focus(); return false;">
                                        <font>
                                           <font>
                                              Report incorrect data
                                           </font>
                                        </font>
                                     </a>
                                  </td>
                               </tr>
                            </tbody>
                         </table>
                      </div>
                   </td>
                </tr>
             </tbody>
          </table>
       </td>
    </tr>
    

    【讨论】:

    • 伙计,你救了我,谢谢!也许你告诉我,我应该读什么书才能达到你的水平,因为我是新手,对我来说很难理解你的代码?
    • 而且,是否可以将公司类中的文本分成两部分:第一是国家,第二是城市?
    • 我不知道有什么好的硒书,我认为这只是你将通过经验学习的东西。但是,如果您可以选择,我建议您改用 Watir gem。它提供了一个围绕 selenium 的 API,我认为它更直观,更易于编写/阅读。
    • 是的,您可以拆分公司。 company[0].find_element(:css, '.firm').text 返回公司的字符串。您可以使用 Ruby 的标准字符串方法,在本例中为 split 在 >> 字符处将其分开。代码已更新。
    猜你喜欢
    • 2012-07-31
    • 2016-04-05
    • 2017-04-24
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多