为什么Selenium仅获取页面上第一个工具提示的文本?

时间:2019-07-23 03:45:22

标签: python selenium web-scraping action webdriverwait

作为使用Python,Selenium和BeautifulSoup构建的更大的Webscraper的一部分,我试图获取此页面上所有工具提示的文本:https://www.legis.state.pa.us/CFDocs/Legis/BS/bs_action.cfm?SessId=20190&Sponsors=S|44|0|Katie%20J.%20Muth

我当前的代码成功获取了所有链接并在每个链接上进行了鼠标操作-运行时,我看到每个工具提示都连续弹出。但是,它仅输出第一个工具提示的文本。我不知道为什么!我以为在两次鼠标悬停之间可能只需要更长的等待时间,但上升时间可能高达20秒,但这并不能解决问题。

代码如下:

 bill_links = soup.find_all('a', {'id': re.compile('Bill')})
 summaries = []
 bill_numbers = [link.text.strip() for link in bill_links]

 for link in bill_links:
   billid = link.get('id')
   action = ActionChains(driver)
   action.move_to_element(driver.find_element_by_id(billid)).perform()
   time.sleep(5)
   summary = driver.find_element_by_class_name("ToolTip-BillSummary-ShortTitle").text
   print(summary)
   summaries = summaries + [summary]
   action.reset_actions()

同样,第一个print(summary)命令成功返回了第一个工具提示的文本(“修正1968年1月17日的行为的法案...”),但是随后的每个print(summary)命令仅返回一个空白。

我对编程很陌生,如果有明显答案,就此道歉。

3 个答案:

答案 0 :(得分:2)

tl; dr:

不需要硒。如果从字面上看是如图所示的工具提示(不是全文),则可以使用bs4并复制页面使用的javascript函数。在每个票据清单的a标签旁边的脚本标签中找到函数调用的参数。我从适当的字符串中将它们进行正则表达式传递给我们的用户定义函数(该函数复制了jquery函数)

enter image description here

您可以看到关联的呼叫AddBillSummaryTooltip('#Bill_1',2019,0,'S','B','0012');


工具提示:

import requests
from bs4 import BeautifulSoup as bs
import re

def add_bill_summary_tooltip(s, session_year, session_ind, bill_body, bill_type, bill_no):
    url = g_server_url + '/cfdocs/cfc/GenAsm.cfc?returnformat=plain'
    data = { 'method' : 'GetBillSummaryTooltip',
            'SessionYear' : session_year,
            'SessionInd' : session_ind,
            'BillBody' : bill_body,
            'BillType' : bill_type,
            'BillNo' : bill_no,
            'IsAjaxRequest' : '1'
            }

    r = s.get(url, params = data)
    soup = bs(r.content, 'lxml')
    tooltip = soup.select_one('.ToolTip-BillSummary-ShortTitle')
    if tooltip is not None:
        tooltip = tooltip.text.strip()
    return tooltip

g_server_url = "https://www.legis.state.pa.us"

#add_bill_summary_tooltip('#Bill_1',2019,0,'S','B','0012')
with requests.Session() as s:
    r = s.get('https://www.legis.state.pa.us/CFDocs/Legis/BS/bs_action.cfm?SessId=20190&Sponsors=S|44|0|Katie%20J.%20Muth')
    soup = bs(r.content, 'lxml')
    tooltips = {item.select_one('a').text:item.select_one('script').text[:-1] for item in soup.select('.DataTable td:has(a)')}
    p = re.compile(r"'(.*?)',(.*),(.*),'(.*)','(.*)','(.*)'")
    for bill in tooltips:
        arg1,arg2,arg3,arg4,arg5,arg6 = p.findall(tooltips[bill])[0]
        tooltips[bill] = add_bill_summary_tooltip(s, arg2, arg3,arg4,arg5,arg6)

print(tooltips)

全文:

如果要全文,则可以从首页抓取到全文页面的链接,然后循环访问每个页面并抓取全文:

import requests
from bs4 import BeautifulSoup as bs

def add_bill_summary_full(s, url): 
    r = s.get(url)
    soup = bs(r.content, 'lxml')
    summary = soup.select_one('.BillInfo-Section-Data div')
    if summary is not None:
        summary = summary.text
    return summary

g_server_url = "https://www.legis.state.pa.us"

with requests.Session() as s:
    r = s.get('https://www.legis.state.pa.us/CFDocs/Legis/BS/bs_action.cfm?SessId=20190&Sponsors=S|44|0|Katie%20J.%20Muth')
    soup = bs(r.content, 'lxml')
    full_text = {item.text:g_server_url + item['href'] for item in soup.select('.DataTable a')}
    for k,v in full_text.items():
        full_text[k] = add_bill_summary_full(s, v)

print(full_text)

这是jquery使用的源代码javascript函数

   function AddBillSummaryTooltip(element,SessionYear,SessionInd,BillBody,BillType,BillNo) {
         jQuery(element).qtip({
            content: {
                text: function(event, api) {
                    jQuery.ajax({
                        url: g_ServerURL + '/cfdocs/cfc/GenAsm.cfc?returnformat=plain',
    					data: {
    						method: 'GetBillSummaryTooltip',
    						SessionYear: SessionYear,
    						SessionInd: SessionInd,
    						BillBody: BillBody,
    						BillType: BillType,
    						BillNo: BillNo,
    						IsAjaxRequest: 1
    					}
                    })


正则表达式:

here试试。

说明:

enter image description here

答案 1 :(得分:0)

该问题可能是由于以下代码行造成的:

summary = driver.find_element_by_class_name("ToolTip-BillSummary-ShortTitle").text

您查找相应元素的条件仅受该元素的类名限制,该条件可能会为您提供元素列表,但实际上您并未指定要获取文本的元素。

要解决此问题,请改用xpath表达式(您需要使用索引变量来定位元素):

summary = driver.find_element_by_xpath("//*[@id="qtip-" + <index> + "-content"]/div/div[3]").text

答案 2 :(得分:0)

如果您使用的是,则不必使用 BeautifulSoup 。要提取页面user上所有工具提示的文本,可以使用以下解决方案:

  • 代码块:

    async
  • 控制台输出:

    set