Я пытаюсь получить данные о здоровье из хранилища данных о здравоохранении Бразилии. Я пытаюсь получить количество посещений врача по поводу тревоги/депрессии за каждый месяц за период с 2018 по 2024 год, для каждого пола (М/Ж) и для 22 различных возрастных групп. У меня есть список кодов A/D (54), и я хочу узнать, сколько посещений было у каждого кода отдельно. У меня есть кадр данных, в котором каждая строка представляет собой одну комбинацию этих переменных (54 кода X 2 пола X 22 возрастных группы X 7 лет):
Для каждой строки в кадре данных я меняю настройки, затем очищаю полученную таблицу HTML и сохраняю ее как файл Excel. У меня есть этот код, чтобы открыть веб-браузер в автономном режиме и выбрать некоторые общие настройки:
url = "https://sisab.saude.gov.br/paginas/acessoRestrito/relatorio/federal/saude/RelSauProducao.xhtml"
DRIVER_PATH = '/home/kvemuri/.local/share/binman_chromedriver/linux64/128.0.6613.119/chromedriver'
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
driver = webdriver.Chrome(executable_path=DRIVER_PATH,options=options)
#driver.quit()
# Open browser and navigate to SISAB website.
#DRIVER_PATH = '/home/kvemuri/.local/share/binman_chromedriver/linux64/127.0.6533.119/chromedriver'
#driver = webdriver.Chrome(executable_path=DRIVER_PATH)
#url = "https://sisab.saude.gov.br/paginas/acessoRestrito/relatorio/federal/saude/RelSauProducao.xhtml"
driver.get(url)
# Set type of service - Individual
driver.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set column to month (Competencia)
driver.find_element(By.XPATH,'//*[@id="selectLinha"]/optgroup[1]/option[6]').click()
# Set Type of team
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click()
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[2]/a/label/input').click()
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[5]/a/label/input').click()
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[9]/a/label/input').click()
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click()
# Set place of service
driver.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click()
driver.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/ul/li[2]/a/label/input').click()
driver.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click()
# Set type of service - Individual
driver.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set type of attendance - select all
driver.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click()
driver.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/ul/li[1]/a/label').click()
driver.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click()
# Set type of professional
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click()
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[12]/a/label').click()
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[19]/a/label').click()
driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click()
# Select 'years' button for age
driver.find_element(By.XPATH,'//*[@id="tpIdade:2"]').click()
Моя проблема в том, что выполнение каждой строки занимает около 20 секунд, а при ~ 17000 строк это означает, что для завершения выполнения всех строк потребуется более 3 дней, если нет проблем.
Я пытаюсь выяснить, есть ли способ распараллелить его с Dask. Я не уверен, нужно ли мне использовать Dask.dataframe, dask.delayed или оба, и как я буду их использовать. Я ищу подсказки о том, как это сделать, и буду признателен за любую помощь.
Большое спасибо!! Обновление 2024 г. -11-07
Я воспользовался предложением @EuanG и попробовал библиотеку concurrent.futures для распараллеливания кода. Вот мой обновленный код:
import pandas as pd
import numpy as np
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from bs4 import BeautifulSoup
from itertools import compress
import time
from concurrent.futures import ThreadPoolExecutor, wait
def get_driver(headless):
options = webdriver.ChromeOptions()
if headless:
options.add_argument("--headless=new")
# initialize driver
driver = webdriver.Chrome(executable_path=DRIVER_PATH,options=options)
#driver.get(URL)
return driver
def browserSettings(browser):
base_url = "https://sisab.saude.gov.br/paginas/acessoRestrito/relatorio/federal/saude/RelSauProducao.xhtml"
#time.sleep(3)
browser.get(base_url)
# Set type of service - Individual
browser.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set column to month (Competencia)
browser.find_element(By.XPATH,'//*[@id="selectLinha"]/optgroup[1]/option[6]').click()
# Set Type of team
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click()
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[2]/a/label/input').click()
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[5]/a/label/input').click()
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[9]/a/label/input').click()
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click()
# Set place of service
browser.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click()
browser.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/ul/li[2]/a/label/input').click()
browser.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click()
# Set type of service - Individual
browser.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set type of attendance - select all
browser.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click()
browser.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/ul/li[1]/a/label').click()
browser.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click()
# Set type of professional
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click()
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[12]/a/label').click()
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[19]/a/label').click()
browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click()
# Select 'years' button for age
browser.find_element(By.XPATH,'//*[@id="tpIdade:2"]').click()
noRun = []
Anx_Dep_dict = {}
futures = []
if __name__ == '__main__':
# scrape and crawl
with ThreadPoolExecutor(max_workers = 3) as executor:
for number in range(0,combns.shape[0]):
futures.append(
executor.submit(run_process, headless = True, df = combns, number = number)
)
wait(futures)
Хотя это, кажется, работает хорошо, я столкнулся с проблемой пропуска некоторых строк, по-видимому, случайно. Я не уверен, как исправить или диагностировать эту проблему. Есть рекомендации?
Еще раз спасибо!
Я пытаюсь получить данные о здоровье из хранилища данных о здравоохранении Бразилии. Я пытаюсь получить количество посещений врача по поводу тревоги/депрессии за каждый месяц за период с 2018 по 2024 год, для каждого пола (М/Ж) и для 22 различных возрастных групп. У меня есть список кодов A/D (54), и я хочу узнать, сколько посещений было у каждого кода отдельно. У меня есть кадр данных, в котором каждая строка представляет собой одну комбинацию этих переменных (54 кода X 2 пола X 22 возрастных группы X 7 лет): [code]combns = pd.read_csv("/.../data/Anxiety_Depression_combinations.csv")
code year sex codeType agelower ageupper 0 F32 2018 2 CID 0 200 1 F320 2018 2 CID 0 200 2 F321 2018 2 CID 0 200 3 F322 2018 2 CID 0 200 4 F323 2018 2 CID 0 200 ... ... ... ... ... ... ... 16627 P01 2024 3 CIAP 100 200 16628 P02 2024 3 CIAP 100 200 16629 P74 2024 3 CIAP 100 200 16630 P79 2024 3 CIAP 100 200 16631 P82 2024 3 CIAP 100 200 16632 rows × 6 columns [/code] Для каждой строки в кадре данных я меняю настройки, затем очищаю полученную таблицу HTML и сохраняю ее как файл Excel. У меня есть этот код, чтобы открыть веб-браузер в автономном режиме и выбрать некоторые общие настройки: [code]url = "https://sisab.saude.gov.br/paginas/acessoRestrito/relatorio/federal/saude/RelSauProducao.xhtml" DRIVER_PATH = '/home/kvemuri/.local/share/binman_chromedriver/linux64/128.0.6613.119/chromedriver' options = webdriver.ChromeOptions() options.add_argument("--headless=new") driver = webdriver.Chrome(executable_path=DRIVER_PATH,options=options) #driver.quit()
# Open browser and navigate to SISAB website. #DRIVER_PATH = '/home/kvemuri/.local/share/binman_chromedriver/linux64/127.0.6533.119/chromedriver' #driver = webdriver.Chrome(executable_path=DRIVER_PATH) #url = "https://sisab.saude.gov.br/paginas/acessoRestrito/relatorio/federal/saude/RelSauProducao.xhtml" driver.get(url) # Set type of service - Individual driver.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set column to month (Competencia) driver.find_element(By.XPATH,'//*[@id="selectLinha"]/optgroup[1]/option[6]').click()
# Set Type of team driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click() driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[2]/a/label/input').click() driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[5]/a/label/input').click() driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[9]/a/label/input').click() driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click()
# Set place of service driver.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click() driver.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/ul/li[2]/a/label/input').click() driver.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click()
# Set type of service - Individual driver.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set type of attendance - select all driver.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click() driver.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/ul/li[1]/a/label').click() driver.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click()
# Set type of professional driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click() driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[12]/a/label').click() driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[19]/a/label').click() driver.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click()
# Select 'years' button for age driver.find_element(By.XPATH,'//*[@id="tpIdade:2"]').click() [/code] У меня есть следующие функции: [code]def createXpathPattern(code,codeType): if codeType == 'CID': codeXpath = '//*[@id="cid-{}-1"]'.format(code) #code = code else: codeXpath = '//*[@id="cid-{}-4"]'.format(code)
"""Selects the upper and lower age limit in years, and the sex for which data is to be output"""
#Set lower age limit agelim1 = driver.find_element(By.XPATH,'//*[@id="idadeInicio"]') agelim1.clear() agelim1.send_keys(str(agelower))
#Set uper age limit agelim2 = driver.find_element(By.XPATH,'//*[@id="idadeFim"]') agelim2.clear() agelim2.send_keys(str(ageupper))
def setSex(sex = 1): # Set Sex sexXpath = '//*[@id="filtrosCaracteristicaUsuario"]/div/ul/li[{}]/a/label'.format(sex) driver.find_element(By.XPATH,'//*[@id="filtrosCaracteristicaUsuario"]/div/button/span').click() #//*[@id="filtrosCaracteristicaUsuario"]/div/button driver.find_element(By.XPATH,sexXpath).click() # //*[@id="filtrosCaracteristicaUsuario"]/div/ul/li[2]/a/label/input driver.find_element(By.XPATH,'//*[@id="filtrosCaracteristicaUsuario"]/div/button/span').click()
# Get list of all months in the months column in the webpage monthBoxes = driver.find_elements(By.CSS_SELECTOR,"#competencia > div > ul > li > a> label > input") yearMonth = [] for i in range(len(monthBoxes)): yearMonth.append(monthBoxes[i].get_attribute("value"))
def getMonthsforYear(year): year = str(year) boolMonth = [year in i for i in yearMonth] return(list(compress(yearMonth,boolMonth)))
def ClickMonthCheckbox(monthsList): driver.find_element(By.XPATH,'//*[@id="competencia"]/div/button/span').click() for month in monthsList: monthIdx = str(yearMonth.index(month) + 1) monthxpath = '//*[@id="competencia"]/div/ul/li[{}]/a/label/input'.format(monthIdx) driver.find_element(By.XPATH,monthxpath).click()
try: print("Scraping code {}, year {}, for {} in age range {} to {}".format(code,str(year),sexL,str(agelower),str(ageupper)))
table_dt = SetParametersAndGetTable(agemin = agelower,agemax = ageupper,sex = sex,year = year, code = code, codeType = codeType) table_dt.to_excel(table_name,index = False,header = True) Anx_Dep_dict[anx_dep_key] = table_dt except: notRun = {'Code':code,'codeType':codeType,'Year':year,'Sex':sex,'agelower':agelower,'ageupper':ageupper} noRun.append(notRun) [/code] А затем примените функцию ApplyRows() к каждой строке кадра данных комбинаций. [code]noRun = [] Anx_Dep_dict = {} combns.apply(ApplyRows, axis = 1) [/code] Моя проблема в том, что выполнение каждой строки занимает около 20 секунд, а при ~ 17000 строк это означает, что для завершения выполнения всех строк потребуется более 3 дней, если нет проблем. Я пытаюсь выяснить, есть ли способ распараллелить его с Dask. Я не уверен, нужно ли мне использовать Dask.dataframe, dask.delayed или оба, и как я буду их использовать. Я ищу подсказки о том, как это сделать, и буду признателен за любую помощь. Большое спасибо!! [b]Обновление 2024 г. -11-07[/b] Я воспользовался предложением @EuanG и попробовал библиотеку concurrent.futures для распараллеливания кода. Вот мой обновленный код: [code]import pandas as pd import numpy as np from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from bs4 import BeautifulSoup from itertools import compress import time from concurrent.futures import ThreadPoolExecutor, wait
def browserSettings(browser): base_url = "https://sisab.saude.gov.br/paginas/acessoRestrito/relatorio/federal/saude/RelSauProducao.xhtml" #time.sleep(3) browser.get(base_url) # Set type of service - Individual browser.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set column to month (Competencia) browser.find_element(By.XPATH,'//*[@id="selectLinha"]/optgroup[1]/option[6]').click()
# Set Type of team browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click() browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[2]/a/label/input').click() browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[5]/a/label/input').click() browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]/ul/li[9]/a/label/input').click() browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[1]').click()
# Set place of service browser.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click() browser.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/ul/li[2]/a/label/input').click() browser.find_element(By.XPATH,'//*[@id="filtrosLocalTipoEstabelecimento"]/div/button').click()
# Set type of service - Individual browser.find_element(By.ID,"tpProducao").send_keys('Atendimento Individual')
# Set type of attendance - select all browser.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click() browser.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/ul/li[1]/a/label').click() browser.find_element(By.XPATH,'//*[@id="divTipoAtendimento"]/div/button/span').click()
# Set type of professional browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click() browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[12]/a/label').click() browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/ul/li[19]/a/label').click() browser.find_element(By.XPATH,'//*[@id="filtroEquipeProf"]/div[2]/button/span').click()
# function to set age group and sex def setAgeLimit(agelower, ageupper,browser):
"""Selects the upper and lower age limit in years, and the sex for which data is to be output"""
#Set lower age limit agelim1 = browser.find_element(By.XPATH,'//*[@id="idadeInicio"]') agelim1.clear() agelim1.send_keys(str(agelower))
#Set uper age limit agelim2 = browser.find_element(By.XPATH,'//*[@id="idadeFim"]') agelim2.clear() agelim2.send_keys(str(ageupper))
def setSex(browser,sex = 1): # Set Sex sexXpath = '//*[@id="filtrosCaracteristicaUsuario"]/div/ul/li[{}]/a/label'.format(sex) browser.find_element(By.XPATH,'//*[@id="filtrosCaracteristicaUsuario"]/div/button/span').click() #//*[@id="filtrosCaracteristicaUsuario"]/div/button browser.find_element(By.XPATH,sexXpath).click() # //*[@id="filtrosCaracteristicaUsuario"]/div/ul/li[2]/a/label/input browser.find_element(By.XPATH,'//*[@id="filtrosCaracteristicaUsuario"]/div/button/span').click()
# Get list of all months in the months column in the webpage #monthBoxes = driver.find_elements(By.CSS_SELECTOR,"#competencia > div > ul > li > a> label > input") #yearMonth = [] #for i in range(len(monthBoxes)): # yearMonth.append(monthBoxes[i].get_attribute("value"))
def GetYearMonth(browser): monthBoxes = browser.find_elements(By.CSS_SELECTOR,"#competencia > div > ul > li > a> label > input") yearMonth = [] for i in range(len(monthBoxes)): yearMonth.append(monthBoxes[i].get_attribute("value")) return(yearMonth)
def getMonthsforYear(year,browser): yearMonth = GetYearMonth(browser = browser) year = str(year) boolMonth = [year in i for i in yearMonth] return(list(compress(yearMonth,boolMonth)))
table_dt = getRowArgs(df = df, rownum = number,browser = Browser) Browser.close() return(table_dt) [/code] Наконец, запустите код в несколько потоков: [code]noRun = [] Anx_Dep_dict = {} futures = []
if __name__ == '__main__': # scrape and crawl with ThreadPoolExecutor(max_workers = 3) as executor: for number in range(0,combns.shape[0]): futures.append( executor.submit(run_process, headless = True, df = combns, number = number) )
wait(futures) [/code] Хотя это, кажется, работает хорошо, я столкнулся с проблемой пропуска некоторых строк, по-видимому, случайно. Я не уверен, как исправить или диагностировать эту проблему. Есть рекомендации? Еще раз спасибо!
Я попробовал парсинг веб-страниц со ссылкой на
Просто скопировал и вставил код на сайт, но получаю ошибку на втором шаге.
import requests
from bs4 import BeautifulSoup
#Used headers/agent because the request was timed out and asking for an agent....
Я пытаюсь получить данные о здоровье из хранилища данных о здравоохранении Бразилии. Я пытаюсь получить количество посещений врача по поводу тревоги/депрессии за каждый месяц за период с 2018 по 2024 год, для каждого пола (М/Ж) и для 22 различных...
Я пытаюсь получить данные о здоровье из хранилища данных о здравоохранении Бразилии. Я пытаюсь получить количество посещений врача по поводу тревоги/депрессии за каждый месяц за период с 2018 по 2024 год, для каждого пола (М/Ж) и для 22 различных...
Я хочу очистить каталог на сайте ассоциации, членом которой я являюсь. Я знаю, как программировать на Python, а также использую в помощь искусственный интеллект, который дал мне программу в конце этой страницы. Я вижу, что Selenium подключается к...
Я пытаюсь написать скрипт на Python, который использует селен для получения некоторой информации с этого сайта. Похоже, Cloudfare блокирует скрипт, потому что это бот. Здесь я публикую часть кода:
from selenium import webdriver
from...