PK!PEEpynfce/__init__.py__version__ = '0.3.1' from .nfce.nfce import get_nfce # noqa: F401 PK!pynfce/nfce/__init__.pyPK!spynfce/nfce/nfce.pyfrom requests_html import HTMLSession from ..states.states import BA, load_state_class def get_nfce(url, state=BA): """ Busca no site da SEFAZ do estado os dados da nfce Args: url (str): url extraída da leitura do QR Code da NFCe state (str): estado referente a URL Returns: nfce (obj) """ state = load_state_class(state) session = HTMLSession() response = session.get(url) return state(session).get_nfce(response) PK!pynfce/states/__init__.pyPK!""pynfce/states/ba.pyfrom .crawling import wait_random_delay, get_random_user_agent CONSULTA_DANFE = "http://nfe.sefaz.ba.gov.br/servicos/nfce/modulos/geral/NFCEC_consulta_danfe.aspx" # noqa: E501 CONSULTA_ABAS = "http://nfe.sefaz.ba.gov.br/servicos/nfce/modulos/geral/NFCEC_consulta_abas.aspx" # noqa: E501 CUSTOM_HEADERS = { "Cache-Control": "no-cache", "Origin": "http://nfe.sefaz.ba.gov.br", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3" } class Bahia: # Aba de Emitente RAZAO_SOCIAL = "#Emitente > table:nth-child(2) > \ tr.col-2 > td:nth-child(1) > span" NOME_FANTASIA = "#Emitente > table:nth-child(2) > \ tr.col-2 > td:nth-child(2) > span" CNPJ = "#Emitente > table:nth-child(2) > tr:nth-child(2) \ > td:nth-child(1) > span" MUNICIPIO = "#Emitente > table:nth-child(2) \ > tr:nth-child(4) > td:nth-child(1) > span" BAIRRO = "#Emitente > table:nth-child(2) \ > tr:nth-child(3) > td:nth-child(1) > span" ENDERECO = "#Emitente > table:nth-child(2) \ > tr:nth-child(2) > td:nth-child(2) > span" CEP = "#Emitente > table:nth-child(2) > \ tr:nth-child(3) > td:nth-child(2) > span" # Aba principal da NFE MODELO = "#NFe > table:nth-child(2) > tr > td:nth-child(1) > span" SERIE = "#NFe > table:nth-child(2) > tr > td:nth-child(2) > span" NUMERO = "#NFe > table:nth-child(2) > tr > td:nth-child(3) > span" VALOR = "#NFe > table:nth-child(2) > tr > td:nth-child(6) > span" CHAVE_ACESSO = "#lbl_chave_acesso" # Aba de produtos DESCRICOES = "#Prod > div > table > tr > td > table.toggle > tr \ > td.fixo-prod-serv-descricao > span" QTDS = "#Prod > div > table > tr > td > table.toggle > tr \ > td.fixo-prod-serv-qtd > span" UNIDADES_COMERCIAIS = "#Prod > div > table > tr > td > table.toggle > tr \ > td.fixo-prod-serv-uc > span" VALORES_UNITARIOS = "table > tr > td > table:nth-child(2) > \ tr:nth-child(4) > td:nth-child(1) > span" VALORES_TOTAIS = "#Prod > div > table > tr > td > table.toggle >\ tr > td.fixo-prod-serv-vb > span" CODIGOS_NCM = "table > tr > td > table:nth-child(1) > tr.col-4 >\ td:nth-child(2) > span" DESCONTOS = "table > tr > td > table:nth-child(1) > tr:nth-child(3) >\ td:nth-child(1) > span" EANS = "#Prod > div > table > tr > td > table:nth-child(2) > tr > td >\ table:nth-child(2) > tr:nth-child(2) > td:nth-child(1) > span" ABA_EMITENTE_X_Y = { "btn_aba_emitente.x": 25, "btn_aba_emitente.y": 11, "hid_uf_dest": "" } ABA_PRODUTOS_X_Y = { "btn_aba_produtos.x": 46, "btn_aba_produtos.y": 8, "hid_uf_dest": "" } def __init__(self, session): self.session = session def _get_municipio(self, municipio): municipio_parts = municipio.split("-") return { "numero": municipio_parts[0].strip(), "nome": municipio_parts[1].strip() } def extract_emitente(self, html, first=True): municipio = html.find(self.MUNICIPIO, first=first).text return { "razao_social": html.find(self.RAZAO_SOCIAL, first=first).text, "nome_fantasia": html.find(self.NOME_FANTASIA, first=first).text, "cnpj": html.find(self.CNPJ, first=first).text, "municipio": self._get_municipio(municipio), "bairro": html.find(self.BAIRRO, first=first).text, "endereco": html.find(self.ENDERECO, first=first).text, "cep": html.find(self.CEP, first=first).text } def extract_nfe(self, html, first=True): return { "modelo": html.find(self.MODELO, first=first).text, "serie": html.find(self.SERIE, first=first).text, "numero": html.find(self.NUMERO, first=first).text, "valor": html.find(self.VALOR, first=first).text, "chave_acesso": html.find(self.CHAVE_ACESSO, first=first).text } def extract_produtos(self, html): descricoes = html.find(self.DESCRICOES, first=False) qtds = html.find(self.QTDS, first=False) unidades_comerciais = html.find( self.UNIDADES_COMERCIAIS, first=False ) valores_unitarios = html.find(self.VALORES_UNITARIOS, first=False) valores_totais = html.find(self.VALORES_TOTAIS, first=False) ncms = html.find(self.CODIGOS_NCM, first=False) descontos = html.find(self.DESCONTOS, first=False) eans = html.find(self.EANS, first=False) result = [] for index in list(range(len(descricoes))): result.append({ "descricao": descricoes[index].text, "qtd": qtds[index].text, "unidade_comercial": unidades_comerciais[index].text, "valor_total": valores_totais[index].text, "valor_unitario": valores_unitarios[index].text, "ncm": ncms[index].text, "desconto": descontos[index].text, "ean": eans[index].text }) return result def _get_basic_hidden_form_data(self, response): return { "viewstate": response.html.find("#__VIEWSTATE", first=True), "viewstate_gen": response.html.find( "#__VIEWSTATEGENERATOR", first=True ), "event_validation": response.html.find( "#__EVENTVALIDATION", first=True ) } def _navigateTo(self, response, tab): basic = self._get_basic_hidden_form_data(response) data = { "__VIEWSTATE": basic.get("viewstate").attrs["value"], "__VIEWSTATEGENERATOR": basic.get("viewstate_gen").attrs["value"], "__EVENTVALIDATION": basic.get("event_validation").attrs["value"], } payload = {**data, **tab} wait_random_delay() return self.session.post( CONSULTA_ABAS, data=payload, headers=self._get_custom_headers(CONSULTA_ABAS) ) def _navigate_to_nfe_tab(self, response): basic = self._get_basic_hidden_form_data(response) data = { "__VIEWSTATE": basic.get("viewstate").attrs["value"], "__VIEWSTATEGENERATOR": basic.get("viewstate_gen").attrs["value"], "__EVENTVALIDATION": basic.get("event_validation").attrs["value"], "btn_visualizar_abas": "Visualizar em Abas" } wait_random_delay() return self.session.post( CONSULTA_DANFE, data=data, headers=self._get_custom_headers(CONSULTA_DANFE) ) def _navigate_to_emitente_tab(self, response): return self._navigateTo(response, self.ABA_EMITENTE_X_Y) def _navigate_to_produtos_tab(self, response): return self._navigateTo(response, self.ABA_PRODUTOS_X_Y) def _get_custom_headers(self, referer): return { **CUSTOM_HEADERS, 'User-Agent': get_random_user_agent(), "Referer": referer } def get_nfce(self, first_response): # click on "Visualizar Abas" nfe_tab_response = self._navigate_to_nfe_tab(first_response) # extract nfe nfe = self.extract_nfe(nfe_tab_response.html) # click on "Emitente" emitente_tab_response = self._navigate_to_emitente_tab( nfe_tab_response ) # extract emitente emitente = self.extract_emitente(emitente_tab_response.html) # click on "Produtos" produtos_tab_resp = self._navigate_to_produtos_tab(nfe_tab_response) # extract produtos produtos = self.extract_produtos(produtos_tab_resp.html) return { **nfe, "emitente": emitente, "produtos": produtos } PK!((pynfce/states/crawling.pyimport random import time user_agent_list = [ #Chrome 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', 'Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36', 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', #Firefox 'Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)', 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)', 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko', 'Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)', 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; Trident/7.0; rv:11.0) like Gecko', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)', #Android Mobile User Agents 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36', 'Mozilla/5.0 (Linux; Android 7.0; SM-G892A Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Mobile Safari/537.36', 'Mozilla/5.0 (Linux; Android 6.0; HTC One X10 Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36', #iPhone User Agents 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/69.0.3497.105 Mobile/15E148 Safari/605.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/13.2b11866 Mobile/16A366 Safari/605.1.15', 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5370a Safari/604.1', 'Mozilla/5.0 (iPhone9,3; U; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1', 'Mozilla/5.0 (Apple-iPhone7C2/1202.466; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3' ] def wait_random_delay(): time.sleep(random.randrange(2, 10)) def get_random_user_agent(): return random.choice(user_agent_list) PK!rrpynfce/states/states.pyBA = "ba" _states_mapping = {} _states_mapping[BA] = "Bahia" def get_state_name(state): return _states_mapping[state] def load_state_class(state): module = __import__(f"{state}", globals(), locals(), [], 1) state_name = get_state_name(state) return getattr(module, state_name) def get_available_states_indexes(): return _states_mapping.keys() PK!HڽTUpynfce-0.3.1.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!H{Kpynfce-0.3.1.dist-info/METADATAAK19ZhB -J{lעa;vIMUԫޛ GȠ^1k݈PK!HW pynfce-0.3.1.dist-info/RECORDK@}¦(X􂗠"!XZR(4LzLNݗsr۱=y>io46& 2S\: Qk֞b+Lշ ziAqh$0uHK]$8+٧Dįxhwm`/(Jr=c9~&pR~:'e󜩣%wuyi@i~N?-{fFk'\kHHϊ4SJ *ͲrP6cW]{Vr@bזM~PK!PEEpynfce/__init__.pyPK!upynfce/nfce/__init__.pyPK!spynfce/nfce/nfce.pyPK!pynfce/states/__init__.pyPK!""pynfce/states/ba.pyPK!(("pynfce/states/crawling.pyPK!rr3pynfce/states/states.pyPK!HڽTU4pynfce-0.3.1.dist-info/WHEELPK!H{KD5pynfce-0.3.1.dist-info/METADATAPK!HW X6pynfce-0.3.1.dist-info/RECORDPK C8