Ich bin ziemlich neu zu Python und ich hoffe, dass jemand hier mir helfen kann.Python Multiprozessing Pool friert ohne Grund ein
Ich habe vor einigen Wochen angefangen, Python zu lernen, und ich habe versucht, einen Webcrawler zu bauen.
Die Idee ist folgende: Der erste Teil crawlt die Domänen von einer Website (für jeden Buchstaben). Der zweite Teil prüft, ob die Domain gültig ist (erreichbar und nicht geparkt) und hält sie in einer Datenbank.
Alles läuft gut, bis der Crawler 'r' erreicht. Nach einigen Minuten friert das Programm ohne Fehlermeldung usw. Auch die Buchstaben nach 'r' machen keine Probleme ... Die Domäne, in der das Programm einfriert, ist nicht das Gleiche.
Hier ist mein Code:
import requests
import re
import logging
import time
from bs4 import BeautifulSoup
from multiprocessing.pool import Pool
""" Extract only the plain text of element
"""
def visible(element):
if element.parent.name in ['style', 'script', '[document]', 'head', 'title']:
return False
elif re.match('.*<!--.*-->.*', str(element), re.DOTALL):
return False
elif re.fullmatch(r"[\s\r\n]", str(element)):
return False
return True
logging.basicConfig(format='%(asctime)s %(name)s - %(levelname)s: %(message)s', level=logging.ERROR)
logger = logging.getLogger('crawler')
hdlr = logging.FileHandler('crawler.log')
formatter = logging.Formatter('%(asctime)s %(name)s - %(levelname)s: %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.DEBUG)
""" Checks if a domain is parked.
Returns true if a domain is not parked, otherwise false
"""
def check_if_valid(website):
try:
resp = requests.get("http://www." + website, timeout=10, verify=False)
soup = BeautifulSoup(resp.text, 'html.parser')
if len(soup.find_all('script')) == 0:
# check for very small web pages
if len(resp.text) < 700:
return None
# check for 'park' pattern
text = filter(visible, soup.find_all(text=True))
for elem in text:
if 'park' in elem:
return None
return "http://www." + website + "/"
except requests.exceptions.RequestException as e:
# no logging -> too many exceptions
return None
except Exception as ex:
logger.exception("Error during domain validation")
def persist_domains(nonParkedDomains):
logger.info("Inserting domains into database")
dbConn = mysqlDB.connect()
for d in nonParkedDomains:
mysqlDB.insert_company_domain(dbConn, d)
mysqlDB.close_connection(dbConn)
if __name__ =="__main__":
dryrun = True
if dryrun:
logger.warning("Testrun! Data does not get persisted!")
url = "http://www.safedomain.at/"
# chars = ['0-9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't','u', 'v', 'w', 'x', 'y', 'z']
chars = ['r','s', 't','u', 'v', 'w', 'x', 'y', 'z']
payload = {'sub': 'domains', 'char': '', 'page': '1'}
domains = list()
cntValidDomains = 0
logger.info("Start collecting domains from \"http://www.safedomain.at\"....")
try:
for c in chars:
payload['char'] = c
payload['page'] = '1'
response = requests.get(url, params=payload, verify=False)
soup = BeautifulSoup(response.text, 'html.parser')
while not soup.find_all('a', {'data-pagenumber': True}):
time.sleep(5)
response = requests.get(url, params=payload, verify=False)
soup = BeautifulSoup(response.text, 'html.parser')
maxPage = int(soup.find_all('a', {'data-pagenumber': True})[-1].getText())
domains = list()
for page in range(1, maxPage + 1):
payload['page'] = page
logger.debug("Start crawling with following payload: char=%s page=%s", payload['char'], payload['page'])
response = requests.get(url, params=payload)
soup = BeautifulSoup(response.text, 'html.parser')
for elem in soup.find_all('ul', {'class': 'arrow-list'}):
for link in elem.find_all('a'):
domains.append(link.getText())
logger.info("Finished! Collected domains for %s: %s",c, len(domains))
logger.info("Checking if domains are valid...")
with Pool(48) as p:
nonParkedDomains = p.map(check_if_valid, domains)
p.close()
p.join()
nonParkedDomains = list(filter(None.__ne__, nonParkedDomains))
cntTemp = cntTemp + len(nonParkedDomains)
# check if domains should get persisted
if dryrun:
logger.info("Valid domains for %s in domains", c)
for elem in nonParkedDomains:
logger.info(elem)
else:
persist_domains(nonParkedDomains)
logger.info("Finished domain validation for %s!", c)
cntValidDomains = cntTemp + cntValidDomains
logger.info("Valid domains: %s", cntTemp)
logger.info("Program finished!")
except Exception as e:
logger.exception("Domain collection stopped unexpectedly")
EDIT: Nach einigen Stunden Debuggen und Testen Ich habe eine Idee. Kann es sein, dass das Request-Modul, das im Thread verwendet wird, Probleme verursacht?
Ich habe bereits ein ähnliches Problem hier gefunden: [link] (http://stackoverflow.com/questions/19071529/python-multiprocessing-125-list-never-finishes) Aber das Programm stoppt im Thread Pool und erreicht nicht einmal die Linie, wo ich schließe und schließe mich dem Pool an. – mLe