I have a script for crawling a page using concurrent.futures.ThreadPoolExecutor using Python 3.8.2. Essentially it crawls a page for links, stores them in sqlite using sqlalchemy, and then moves on to the next page.
I have an issue however that the script never finishes. I have made sure that all processes are finished using two print statements, but the script just hangs and never finished. Is there something I have missed regarding how to deal with concurrency and the sqlite sessions?
from sqlalchemy import create_engine, Column, String
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
def crawl(link):
print('Starting: {}'.format(link))
session = Session()
html = requests.get(url, timeout=10)
soup = BeautifulSoup(html.text, 'lxml')
links = [entry.get('href') for entry in soup.find_all('a', clazz)]
for link in links:
data = {
'type': self.type,
'status': self.status,
'url': link
}
if not session.query(exists().where(Table.url == link)).scalar():
d = DataEntry(**data)
session.add(d)
session.commit()
print('Finished: {}'.format(link))
def main():
links = ['www.link1.com', 'www.link2', ....]
with futures.ThreadPoolExecutor(max_workers=4) as executor:
the_futures = [executor.submit(crawl_for_listings, task) for task in tasks]
for future in the_futures:
try:
result = future.result()
except Exception as e:
print('Thread threw exception:', e)
if __name__ == "__main__":
engine = create_engine("sqlite:///database.sql")
Base = declarative_base()
class Links(Base):
__tablename__ = 'links'
url = Column(String, primary_key=True)
type = Column(String)
status = Column(String)
Base.metadata.create_all(engine)
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
main()
Session.remove()