Интернет - самая большая библиотека в мире. Просто все книги на полу.

- Джон Аллен Паулос

Давайте подместим пол и попробуем сложить эти книги по книжным полкам.

Общий набор данных сканирования

Вместо сканирования открытого Интернета рекомендуется использовать существующий набор данных Common Crawl - просканированный архив из 2,95 миллиарда веб-страниц с общим содержанием 260 терабайт. Конечно, это не полное представление о сети, но дает нам неплохое начало.

Чтобы проанализировать и классифицировать такой большой корпус, нам потребуется большая вычислительная мощность. Поэтому мы будем использовать сотни машин в Amazon Elastic MapReduce (EMR) с Apache Spark. Хорошая новость заключается в том, что набор данных Common Crawl уже существует на Amazon S3 как часть программы Amazon Public Datasets, и поэтому мы должны иметь к нему эффективный доступ.

Извлечение текста с веб-страниц

Обычное сканирование WARC-файлы содержат необработанные данные сканирования, включая HTTP-ответ от веб-сайтов, с которыми он связался. Если мы посмотрим на один такой HTML-документ -

<!DOCTYPE html>
<html lang=”en-US”>
<head>
<meta charset=”UTF-8">
<meta name=”viewport” content=”width=device-width, initial-scale=1">
<link rel=”profile” href=”http://gmpg.org/xfn/11">
...
<div class=”cover”>
<img src=”https://images-eu.ssl-images-amazon.com/images/I/51Mp9K1v9IL.jpg" /></p>
</div>
<div>
<div id=”desc-B00UVA0J6E” class=”description”>
<p>By Richard S. Smith,Simon W. M. John,Patsy M. Nishina,John P. Sundberg</p>
<p>ISBN-10: 084930864X</p>
<p>ISBN-13: 9780849308642</p>
<div> finishing touch of the 1st section of the Human Genome venture has awarded scientists with a mountain of recent info.
...
<footer id=”colophon” class=”site-footer” role=”contentinfo”>
<div class=”site-info”>
...
</body>
</html>

Как видите, HTML-документы представляют собой очень сложный код, зачастую имеющий множество форматов. Мы бы использовали библиотеку Python - Beautiful Soup, чтобы извлечь текст из этих документов.

def get_text(html_content):
    soup = BeautifulSoup(html_content, "lxml")

    # strip all script and style elements
    for script in soup(["script", "style"]):
        script.decompose()

    return soup.get_text(" ", strip=True)

Мы создали объект BeautifulSoup, передав необработанный HTML-контент. Он содержит все данные во вложенной структуре. Все текстовые данные могут быть извлечены программно, вызвав get_text для этого объекта. Однако, помимо текста, он также извлекает код javascript и CSS, который нам может не понадобиться, поэтому перед извлечением мы удалим их. Это должно дать нам то, что мы хотим, только тексты -

Download e-book for iPad: Systematic Evaluation of the Mouse Eye: Anatomy, Pathology, by Richard S. Smith,Simon W. M. John,Patsy M. Nishina,John P. - Gdynia Design E-books
...
finishing touch of the 1st section of the Human Genome venture has awarded scientists with a mountain of recent info. the supply of all human genes and their destinations is fascinating, yet their mechanisms of motion and interplay with different genes 
...
the booklet then studies and illustrates nearby ocular pathology and correlates it with human eye disease.

Классификация

Чтобы классифицировать этот текст, мы будем использовать scikit-learn - библиотеку Python для машинного обучения. Мы будем обучать наш классификатор с набором данных из 20 групп новостей. Это собрание примерно из 20 000 документов групп новостей, равномерно распределенных по 20 различным группам новостей. Мы бы сопоставили эти группы новостей по следующим восьми категориям.

class Classifier:

    # train the model
   def __init__(self):
        newsgroups_train = fetch_20newsgroups(subset='train', remove = ('headers', 'footers', 'quotes'))
        self.target_names = newsgroups_train.target_names
        self.vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5, stop_words='english')
        vectors = self.vectorizer.fit_transform(newsgroups_train.data)
        self.clf = LinearSVC(penalty='l2', dual=False, tol=1e-3)
        self.clf.fit(vectors, newsgroups_train.target)

    def predict(self, document):
        x_test = self.vectorizer.transform([document])
        pred = self.clf.predict(x_test)
        return self.target_names[pred[0]]

Функция fetch_20newsgroups загружает архив данных с исходного веб-сайта 20 групп новостей. Мы настраиваем его для удаления заголовков, блоков подписей и блоков цитат соответственно, что имеет мало общего с классификацией тем. Мы преобразуем текст в векторы числовых значений с помощью TfidfVectorizer, чтобы скормить их прогнозной модели. Теперь мы будем использовать классификацию линейных опорных векторов (LinearSVC) для обучения нашей модели, которая лучше масштабируется на большом наборе данных. Фактически, можно легко подключить множество других моделей, таких как Наивный Байес, классификатор SGD, k-ближайшие соседи, деревья решений и т. Д., Но эмпирически я обнаружил, что SVM хорошо работает в нашем случае. Теперь мы можем вызвать функцию прогнозирования в нашей модели, чтобы классифицировать документ по одной из восьми категорий.

Анализ прогнозов

Классификатор, кажется, неплохо справляется. Вот несколько веб-страниц -

Beautiful Kazak carpet of distinctive colours matches with the curtains add lively touch. ...
Carpet cleaning is something which can be done at home but you might damage your carpet instead of cleaning it. Often the colours of carpet run as soon as it comes in contact with water. ...
Carpet Repairing
If your carpet is torn or there is piece missing, AbeeRugs can help you fix that. We fix it in a way that we also complete the design no matter how intricate it is. ...
Classified as E-Commerce
--------------------------------
Make more time for the moments that matter. Get expertly-curated updates and medical education, instantly.
New to EasyWeb?
EasyWeb is a free service for United States Healthcare Professionals. ...
Specialty Anesthesiology: general Anesthesiology: adult cardiothoracic Anesthesiology: critical care Anesthesiology: pain Anesthesiology: pediatric Dermatology Emergency Medicine Family Medicine ...
Classified as Medicines
--------------------------------
All Films & Events | Arab Film Festival 2014 ...
Watch Trailer Watch Trailer
A Stone’s Throw from Prison
Raquel Castells / Documentary / Palestine, Spain / 2013 / 65 mins
Growing up in the Occupied Palestinian Territory is not easy. When you leave home for school, your mother can't be sure of when you'll be back. Rami, Ahmed, Mohammed, three among thousands, this documentary is their story, but also that of courageous Israelis and Palestinians working to cut abuses, stop conflict ...
Classified as Politics

Видимо, проанализировав больше прогнозов, можно заметить, что категории слишком широки.

Tanzania farmers adopts vegetable farming to improve nutrition
The farmers in Tanzania are encouraged to grow elite varieties of vegetables, enriched with high-value nutritional content, in order to fight malnutrition, hunger and double agricultural productivity and income of smallholders
The Africa RISING project focuses on the need to take urgent action in achieving Sustainable Development Goals (SDGs) which aim ...
Classified as Medicines

Если посмотреть на все возможные категории, которые у нас есть, прогнозируемая категория кажется правильной, но было бы лучше отнести ее к категории «Сельское хозяйство». Кроме того, для следующего образца больше подошло бы Aeronautics.

Schofields Flying Club - N1418V Flight Schedule
N1418V Flight Schedule
Cessna 172M
Perhaps the staple of general aviation flight training, and rightfully so. The 172 has been in production since 1956, with no end in sight! Our 172 is an ideal VFR training platform!! Because of its high wings, 18V provides a great view of the ground, ...
Classified as Space

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

Recently Sold Vehicles
Here are some vehicles that we recently sold. It's just a sample of the variety and quality of our vehicle selection.
Please feel free to browse our Internet showroom and contact us to make an appointment if you would like to see any of our vehicles in person. ...
Classified as Automobile

И есть также немало примеров, в которых классификатор, кажется, ошибается.

... We all make mistakes. That is a dictum of life. It’s surprising how ignored it is and how discouraged one is to fail in the world. Then again current with this theme of artificial organizing is that the soul is now completely detached from the world it swims in. The title Greenberg centers around […]
To the dilettante the thing is the end, while to the professional as such it is the means; and only he who is directly interested in a thing, and occupies himself with it from love of it ...
Support Joseph A. Hazani on Patreon! ...
Misclassified as Sports
--------------------------------
... Fast, Reliable Everytime
ABC Messenger Local Flower Hill NY Delivery Service
ABC Messenger & Transport, Inc. has the ability to offer rush and pre-scheduled Delivery Service at competitive prices and excellent Flower Hill NY service. Their Delivery Service is recognized as fast and dependable. Through highly experienced and skilled veteran Flower Hill NY dispatchers and seasoned couriers we are able to predict traffic patterns easily and avoid or overcome ...
Misclassified as Medicines

В целом, он дает хорошие прогнозы, на которые мы можем положиться в нашем стартовом проекте.

Определение языка

Поскольку классификатор обучен на английском наборе данных, мы будем использовать библиотеку langdetect, чтобы пропускать неанглоязычные веб-страницы.

from langdetect import detect
lang = detect(text)
if lang != 'en':
    # skip non-English pages
    return

Фильтр ненормативной лексики

Мы также будем использовать фильтр ненормативной лексики, чтобы игнорировать контент для взрослых.

from profanity_check import predict
if predict([text])[0]:
    # adult content

Spark на Amazon EMR

Как обсуждалось ранее, поскольку набор данных Common Crawl огромен, мы будем запускать наше приложение на Spark на Amazon EMR. Мы адаптируемся к примеру кода Common Crawl для обработки данных на Spark.

class WebClassifier(CCSparkJob):

    name = "WebClassifier"
    def __init__(self):
        CCSparkJob.__init__(self)
        self.output_schema = StructType([
            StructField("topic", StringType(), True),
            StructField("count", LongType(), True)
        ])
        self.classifier = Classifier()

    def process_record(self, record):
        # html record
        if self.is_html(record): 
            # extract text from web page
            text = self.get_text(record)
        else:
            return
        # skip non-English pages
        # filter profane content

        topic = self.classifier.predict(text)
        yield topic, text

if __name__ == '__main__':
    job = WebClassifier()
    job.run()

Функция process_record будет вызываться для каждой записи в наборе данных, где мы классифицируем ее по одной из категорий, перечисленных ранее. Полный исходник загружен здесь.

Для дальнейшего ускорения мы будем использовать WET-файлы вместо WARC, который содержит извлеченный открытый текст. Кроме того, мы загрузим предварительно обученный сериализованный классификатор, чтобы не обучать его на каждой машине. Я использовал 100 экземпляров ec2, и на обработку 1% корпуса Common Crawl ушло около полутора часов. Это обошлось мне примерно в 25 долларов. И вот что у нас получилось:

Веб-категории

Мы начали с примерно 1% данных Common Crawl или примерно с 25,6 миллионами веб-страниц. Мы отфильтровали 1,4 миллиона веб-страниц, поскольку они не содержали достаточно текстовой информации для целей классификации. Позже мы пропустили около 13,2 миллиона неанглийских страниц. Нам удалось классифицировать оставшиеся 10,9 миллиона страниц. Судя по всему, существует множество контента электронной коммерции и много контента, в котором говорится о компьютерах и электронике, за которыми следуют политика, лекарства, религия, автомобили и космос. Обратите внимание, что мы также отфильтровали около четверти миллиона веб-страниц для взрослых.

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