Beautiiful Soup Crawler останавливается в середине работы - PullRequest
0 голосов
/ 22 апреля 2019

Я пишу программу для сохранения газетных комментариев в sqlite db.Для очистки я использую красивый суп и запросы.

Проблема в том, что код работает только в течение нескольких минут, а затем останавливается без каких-либо ошибок.

Я не знаюпочему это останавливается.Если я проверяю страницу, где она остановилась в последний раз, с помощью моего браузера, я не вижу никакой разницы по страницам, которые он ранее удалял.

Может быть проблема в том, что слишком много экземпляров HeiseScraper () открыто?

from urllib.request import urlopen
from bs4 import BeautifulSoup
from sqlalchemy import create_engine, exc
from sqlalchemy.orm import sessionmaker

from db_controller import Comment, Person

engine = create_engine('sqlite:///sqlalchemy_example.db')
dbsession = sessionmaker(bind=engine)

class HeiseScraper:

    def __init__(self, page):
        self.soup = BeautifulSoup(urlopen(page), "html.parser")
        self.root = page
        self.session = dbsession()


    def kommentar_to_db(self, Kommentar):
        user = Person(
                id=Kommentar["userid"],
                name=Kommentar["username"],
                info = Kommentar["userinfo"])

        user.comment = [
                Comment(
                    id=Kommentar["id"],
                    content=Kommentar["content"].strip(),
                    date=Kommentar["date"].strip(),
                    person_id = Kommentar["userid"],
                    link=Kommentar["relates"],
                    artikel=Kommentar["artikel"].strip(),
                    link2=Kommentar["link2"]
                    )
                ]
        try:
            self.session.add(user)
            self.session.commit()
            print(user)
            print(user.comment)
        except exc.IntegrityError as e:
            self.session.rollback()
            kommentar = Comment(
                    id=Kommentar["id"],
                    content=Kommentar["content"].strip(),
                    date=Kommentar["date"].strip(),
                    person_id = Kommentar["userid"],
                    link=Kommentar["relates"],
                    artikel=Kommentar["artikel"],
                    link2=Kommentar["link2"]
                    )
            try:
                self.session.add(kommentar)
                self.session.commit()
                print(kommentar)
            except exc.IntegrityError as e:
                print(e)


    def getTelepLinks(self):
        urls = [[link.get("href"), link.text] for link in self.soup.find_all(class_="forum_edit_links width_mod_for_admins")]
        return urls


    def getKommentarseiten(self):
        urls = [self.root]
        kseiten = self.soup.find_all(class_="seiten")
        if len(kseiten)>0:
            for link in kseiten[0].find_all("a"):
                urls.append(link.get("href"))
        return urls


    def getKommentarLinks(self):
        links = []
        kommentarlinks = self.soup.find_all(class_="posting_subject")
        print(kommentarlinks)
        for kommentar in kommentarlinks:
            try:
                links.append(kommentar["href"])
            except IndexError as ie:
                print(ie)
            except Exception as e:
                print(e)
        print(links)
        return(links)


    def getKommentar(self, artikel, link):
        Kommentar={}
        for body in self.soup.find_all("body"):
            Kommentar["artikel"]=artikel
            Kommentar["relates"]= body.find_all(class_="forum_headline")[0].find_all('a')[0]['href']
            Kommentar["content"]=[comment.text for comment in body.find_all(class_="post")][0]
            Kommentar["date"]=[timestamp.text for timestamp in body.find_all(class_="posting_timestamp")][0]
            Kommentar["username"]=[username.text for username in body.find_all(class_="full_user_string")][0]
            Kommentar["userid"]=[username.get("data-user-id") for username in body.find_all(class_="userbar clearfix")][0]
            Kommentar["thread"]=[thread.text for thread in body.find_all(class_="thread_title")][0]
            Kommentar["id"] = [div.get("id") for div in body.find_all(class_="first_posting")][0]
            for p in body.find_all('p'):
                if "full_user_string" in str(p.parent):
                    Kommentar["userinfo"]=p.text.strip()
            Kommentar["link2"]=link
        return Kommentar



if __name__ == "__main__":
    forum="https://www.heise.de/forum/Telepolis/Kommentare/forum-43418/"
    teleScraper = HeiseScraper(forum)
    pages = max([int(page.text) for page in teleScraper.soup.find_all(class_="page")])
    for n in range(pages):
        print(teleScraper.root+"?forum_page={0:d}".format(n+1))
        scr = HeiseScraper(teleScraper.root+"?forum_page={0:d}".format(n+1) )
        for url in scr.getTelepLinks():
            print(url)
            commentScr = HeiseScraper(url[0])
            links = commentScr.getKommentarseiten()
            for link in links:
                print("link",link)
                s = HeiseScraper(link)
                kommentare=s.getKommentarLinks()
                if kommentare is not None:
                    for kommentar in kommentare:
                        if len(kommentar)>0:
                            print("kommentar", kommentar)
                            f=HeiseScraper(kommentar)
                            f.kommentar_to_db(f.getKommentar(url[0], f.root))

db_controller

import os
import sys
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class Session():
    engine = create_engine('sqlite:///sqlalchemy_example.db')
    Base.metadata.bind = engine
    dbsession = sessionmaker(bind=engine)
    session = dbsession()

class Person(Base):
    __tablename__ = 'Person'
    id = Column(String(200), primary_key=True)
    name = Column(String(250), nullable=False)
    info = Column(String(250), nullable=True)
    comment = relationship("Comment", back_populates="person")

    def __repr__(self):
        return "id: {},\nname: {},\ninfo: {},\ncomment: {}\n\n".format(self.id, self.name, self.info, self.comment)

class Comment(Base):
    __tablename__ = 'Comment'
    id = Column(String(250), primary_key=True)
    content = Column(String(5000))
    date = Column(String(250))
    person_id = Column(String(200), ForeignKey('Person.id'))
    person = relationship("Person", back_populates="comment")
    link = Column(String(200))
    artikel = Column(String(500))
    link2 = Column(String(299))

    def __repr__(self):
        return "id={},\nlink={},\nArtikeltitel={},\ncontent={},\ndate={},\nperson_id={}\n\n".format(self.id, self.link, self.artikel, self.content, self.date, self.person_id)

engine = create_engine('sqlite:///sqlalchemy_example.db')
Base.metadata.create_all(engine)

1 Ответ

0 голосов
/ 28 апреля 2019

Я решил мою проблему. Это было внутри функции urlopen (). Вы можете определить время ожидания как urlopen(page, timeout=5). Таким образом, программа просто пропускает запросы, которые не получают ответа после определенного интервала времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...