How to Extract Title and Text from Scraped Article

Say you have successfully extracted the full HTML of multiple articles using a web crawler and stored it in a database. You can easily extract the title and text from this article.

In this tutorial, the data is being stored in a MongoDB collection. There is a URL column containing article URLs and an HTML column containing the full HTML of each article.

Using Jupyter Notebook:

Step 1: Import the scraped data from the MongoDB collection:

import re

#create a MongoClient to the running mongod instance (make sure that MongoDB instance is currently running)
from pymongo import MongoClient

#specify the host and port to connect on
MONGO_ADDRESS = "mongodb://<IP ADDRESS HERE>"
from bson import json_util
from collections import Counter


def connection():
    # Connect to the database
    client = MongoClient(MONGO_ADDRESS)
    db = client.GoogleResult
    # Handle to the connection
    collection = db.Articles

    news = list(collection.find({},{'URL', 'HTML'}))
        
    return news

news = connection()

Step 2: Convert news to pandas dataframe:

import pandas as pd

df = pd.DataFrame.from_records(news)

Step 3: Get the title from each article:

import re

def get_article_title(article):
    if '<title>' in article:
        m=re.search('<title>([\d\D]+)</title>', article)
        return m.group(1)

Step 4: Apply function to each article:

df["Title"] = df.apply(lambda article: get_article_title(article['HTML']), axis=1)

Step 5: Remove \n from title:

df['Title'] = df['Title'].str.replace('\n', '')

Step 6: Use Beautiful Soup to remove script from article:

def clean_me(article):
    soup = BeautifulSoup(article)
    for s in soup(['script', 'style']):
        s.decompose()
    return ' '.join(soup.stripped_strings)

Step 7: Apply to all articles:

df['Text'] = df.apply(lambda article: clean_me(article['HTML']), axis=1)

Step 8: Drop any rows which are empty or NaN in the ‘Page’ column:

df = df[df['Text'] != '']
df = df[df['Text'].notna()]

Step 9: Drop any rows which contain ‘403 Forbidden’ in the ‘Page’ column:

df = df[~df['Text'].str.contains('403 Forbidden')]

Using an IDE such as PyCharm:

main.py:


from extract_text import get_title, clean
import pandas as pd
import re
from pymongo import MongoClient
from bson import json_util
from collections import Counter


# Read Db
MONGO_ADDRESS = "mongodb://<IP ADDRESS HERE>"

def connection():
    # Connect to the database
    client = MongoClient(MONGO_ADDRESS)
    db = client.GoogleResult
    # Handle to the connection
    collection = db.Articles

    news = list(collection.find({},{'<LIST COLUMN NAMES HERE>'}))
        
    return news

news = connection()

raw_data = pd.DataFrame.from_records(news)


# Get and clean article title
raw_data['Title'] = raw_data.apply(lambda article: get_title(article['HTML']), axis=1)
raw_data['Title'] = raw_data['Title'].str.replace('\n', '')


# Clean article body
raw_data['Text'] = raw_data.apply(lambda article: clean(article['HTML']), axis=1)
raw_data = raw_data[raw_data['Text'] != '']
raw_data = raw_data[raw_data['Text'].notna()]
raw_data = raw_data[~raw_data['Text'].str.contains('403 Forbidden')]

extract_text.py:

import pandas as pd
from bs4 import BeautifulSoup
import re
import string


# Get article title
def get_title(article):
    """
    Get title from article and clean it
    """
    if '<title>' in article:
        m = re.search('<title>([\d\D]+)</title>', article)
        return m.group(1)


# Clean article
def clean(article):
    """
    Clean the body of article
    """
    soup = BeautifulSoup(article)
    for s in soup(['script', 'style']):
        s.decompose()
    return ' '.join(soup.stripped_strings)

Leave a Reply

Your email address will not be published. Required fields are marked *