Заманчиво думать о интернете преимущественно как о сборнике текстовых веб-сайтов, чередующихся с новомодным мультимедийным контентом Web 2.0, который в основном можно игнорировать для целей веб-скрапинга. Однако, интернет прежде всего является: механизмом передачи файлов, независимым от содержания.
Хотя интернет существует в какой-то форме с конца 1960-х годов, HTML дебютировал только в 1992 году. До этого интернет в основном состоял из электронной почты и передачи файлов; концепция веб-страниц, как мы их знаем сегодня, не существовала. Иными словами, интернет не является сборником HTML-файлов. Это сборник множества типов документов, причем HTML-файлы часто используются как оболочка для их отображения. Без возможности читать различные типы документов, включая текст, PDF, изображения, видео, электронную почту и многое другое, мы упускаем огромную часть доступных данных.
В этой статье рассматривается работа с документами, будь то их загрузка в локальную папку или чтение и извлечение данных. Вы также посмотрите на работу с различными типами кодировки текста, что позволяет читать даже веб-страницы на различных языках.
Форматы документов
Формат документа сообщает приложениям — будь то операционная система вашего компьютера или ваш собственный код на Python — как его читать.
На фундаментальном уровне все документы закодированы в двоичном коде как 0 и 1. Кроме того, алгоритмы кодировки определяют такие вещи, как «сколько бит на символ» или «сколько бит представляют цвет для каждого пикселя» (в случае файлов изображений). Помимо этого, может быть слой сжатия или какой-то алгоритм сокращения места, как это происходит с файлами PNG.
Хотя работа с не-HTML файлами может показаться на первый взгляд пугающей, будьте уверены, что с правильной библиотекой Python будет полностью оборудована для работы с любым форматом информации, которую вы хотите использовать.
Единственное различие между текстовым файлом, видеофайлом и файлом изображения заключается в том, как их 0 и 1 интерпретируются. В этом разделе рассматриваются несколько часто встречаемых типов файлов: текстовые, CSV, PDF и документы Word. Обратите внимание, что все они, в основном, являются файлами, которые хранят текст.
Текстовые файлы
Хранение файлов в виде обычного текста в Интернете несколько необычно, но иногда это популярно среди сайтов в стиле «откровенный минимализм» или старомодных сайтов, где есть большие хранилища текстовых файлов. Например, Internet Engineering Task Force (IETF) хранит все свои опубликованные документы в форматах HTML, PDF и текстовых файлов (см. https://www.ietf.org/rfc/rfc1149.txt в качестве примера).
Большинство браузеров отображают эти текстовые файлы нормально, и вы должны иметь возможность сканировать их без проблем.
Для большинства базовых текстовых документов, например, для практического файла, расположенного по адресу http://www.python‐scraping.com/pages/warandpeace/chapter1.txt, можно использовать следующий метод:
from urllib.request import urlopen
textPage = urlopen('http://www.pythonscraping.com/'\
'pages/warandpeace/chapter1.txt')
print(textPage.read())
Обычно, когда вы извлекаете страницу с помощью urlopen, вы преобразуете ее в объект BeautifulSoup, чтобы разобрать HTML. В этом случае вы можете читать страницу напрямую. Преобразование ее в объект BeautifulSoup, хотя и возможно, будет неэффективным — нет HTML для анализа, поэтому библиотека будет бесполезной. После того как текстовый файл считан как строка, вам просто нужно анализировать его, как вы бы это сделали с любой другой строкой, считанной в Python. Недостаток здесь, конечно, в том, что у вас нет возможности использовать HTML-теги в качестве подсказок контекста, указывающих вам направление текста, который вам действительно нужен, по сравнению с текстом, который вам не нужен.
Кодировки текстовых файлов
Обычно, расширения файла достаточно для его корректного чтения. Но, странно, это правило не распространяется на самый базовый из всех документов: файлы с расширением .txt.
Девять раз из десяти, чтение текста с использованием описанных ранее методов будет работать нормально. Однако работа с текстом в интернете может быть сложной задачей. Далее мы рассмотрим основы кодирования текста на английском и других языках, от ASCII до Unicode и ISO, и как с ними работать.
История кодирования текста
ASCII был разработан в 1960-х годах, когда биты были дороги, и не было никаких причин кодировать что-либо, кроме латинского алфавита и нескольких знаков препинания. По этой причине использовалось всего 7 бит для кодирования 128 заглавных и строчных букв, а также знаков препинания. Несмотря на всю эту творческую работу, они всё же остались с 33 непечатаемыми символами, некоторые из которых использовались, заменялись или устаревали с течением времени по мере изменения технологий. Места хватало всем, верно?
Как известно каждому программисту, число 7 — странное. Оно не является красивой степенью двойки, но оно искусительно близко. В 1960-х годах компьютерные ученые спорили, добавить ли еще один бит для удобства иметь красивое круглое число, или оставить все как есть для экономии места хранения файлов. В итоге победили 7 бит. Однако в современных вычислениях каждая 7-битная последовательность дополняется дополнительным 0 в начале, что приводит к тому, что мы получаем худшее из обоих миров: файлы становятся на 14% больше, и нет гибкости в использовании только 128 символов.
В начале 1990-х годов люди осознали, что существует больше языков, чем только английский, и было бы замечательно, если бы компьютеры могли их отображать. Неприбыльная организация под названием Unicode Consortium предприняла попытку создать универсальный текстовый кодировщик, установив кодировки для каждого символа, который необходимо использовать в любом текстовом документе, на любом языке. Целью было включить все, начиная от латинского алфавита, на котором написана эта книга, заканчивая кириллицей, китайскими пиктограммами, математическими и логическими символами, а также эмотиконами и различными символами, такими как символ биологической опасности и символ мира.
Результатом стал кодировщик, который, возможно, вы уже знаете, названный UTF-8, что означает, путающим образом, «Универсальный набор символов — Формат преобразования 8 бит». Здесь 8 бит относится не к размеру каждого символа, а к минимальному размеру, необходимому для отображения символа.
Реальный размер символа в UTF-8 гибкий. Он может составлять от 1 байта до 4 байт, в зависимости от того, где символ находится в списке возможных символов (более популярные символы кодируются меньшим количеством байт, более редкие требуют больше байт).
Как достигается такое гибкое кодирование? Использование 7 бит с последующим бесполезным ведущим нулем на первый взгляд выглядело как недостаток дизайна в ASCII, но оказалось огромным преимуществом для UTF-8. Поскольку ASCII был настолько популярен, Unicode решил использовать этот ведущий бит нуля, объявив, что все байты, начинающиеся с нуля, указывают на то, что в символе используется только один байт, и сделав две схемы кодирования для ASCII и UTF-8 идентичными. Поэтому следующие символы допустимы как в UTF-8, так и в ASCII:
01000001 — A 01000010 — B 01000011 — C
А следующие символы допустимы только в UTF-8 и будут отображаться как непечатаемые, если документ будет интерпретироваться как документ ASCII:
11000011 10000000 — À 11000011 10011111 — ß 11000011 10100111 — ç
Помимо UTF-8, существуют другие стандарты UTF, такие как UTF-16, UTF-24 и UTF-32, хотя документы, закодированные в этих форматах, редко встречаются.
Хотя этот первоначальный «недостаток» ASCII имел значительное преимущество для UTF-8, недостаток полностью не исчез. Первые 8 бит информации в каждом символе по-прежнему могут кодировать только 128 символов, а не полные 256. В многобайтовом символе UTF-8 дополнительные ведущие биты тратятся не на кодирование символов, а на контрольные биты, используемые для предотвращения повреждения. Из 32 (8 x 4) бит в 4-байтовых символах только 21 бит используются для кодирования символов, всего 2 097 152 возможных символа, из которых 1 114 112 в настоящее время выделены.
Проблема всех универсальных стандартов кодирования языка, конечно же, заключается в том, что любой документ, написанный на одном нелатинском языке, может быть намного больше, чем это необходимо. Хотя ваш язык может состоять всего из 100 или около того символов, вам потребуется по 16 бит на каждый символ, а не только 8 бит, как в случае с англоязычным ASCII. Это делает текстовые документы в UTF-8 примерно вдвое больше по размеру, по крайней мере, для языков, не использующих набор символов латиницы.
ISO решает эту проблему, создавая специфические кодировки для каждого языка. Как и Unicode, у него есть те же кодировки, что и у ASCII, но он использует ведущий бит с нулём в начале каждого символа, чтобы позволить создавать 128 специальных символов для всех языков, которые их требуют. Это работает наилучшим образом для европейских языков, которые также сильно полагаются на латинский алфавит (которые остаются на позициях с 0 по 127 в кодировке), но требуют дополнительных специальных символов. Это позволяет ISO-8859-1 (разработанный для латинского алфавита) иметь символы, такие как дроби (например, ½) или знак копирайта (©).
Другие наборы символов ISO, такие как ISO-8859-9 (турецкий), ISO-8859-2 (немецкий, среди других языков) и ISO-8859-15 (французский, среди других языков), также можно встретить в интернете с некоторой регулярностью.
Хотя популярность документов, кодированных в ISO, последние годы снижается, около 9% веб-сайтов в интернете все еще кодируются каким-либо вариантом ISO, что делает его важным для знания и проверки кодировок перед анализом сайта.
Практический пример работы с кодировками
В предыдущем разделе вы использовали стандартные настройки urlopen для чтения текстовых документов, которые могут встретиться в интернете. Это отлично работает для большинства английских текстов. Однако, как только вы столкнетесь с русским, арабским или даже словом «résumé», у вас могут возникнуть проблемы.
from urllib.request import urlopen
textPage = urlopen('http://www.pythonscraping.com/pages/warandpeace/chapter1-ru.txt')
print(textPage.read())
Этот код читает первую главу оригинальной книги «Война и мир» (написанной на русском и французском) и выводит ее на экран. Вывод будет содержать текст вроде:
b"\xd0\xa7\xd0\x90\xd0\xa1\xd0\xa2\xd0\xac \xd0\x9f\xd0\x95\xd0\xa0\xd0\x92\xd0\x90\xd0\xaf\n\nI\n\n\xe2\x80\x94 Eh bien, mon prince.
К тому же, посещение этой страницы в большинстве браузеров приводит к выводу абракадабры.
Даже нам, как носителям русского языка невозможно ничего разобрать. Проблема заключается в том, что Python пытается прочитать документ как документ ASCII, в то время как браузер пытается прочитать его как документ, закодированный в ISO-8859-1. Ни один из них, конечно же, не осознает, что это документ в кодировке UTF-8.
Вы можете явно определить строку как UTF-8, что позволит правильно отображать кириллические символы:
from urllib.request import urlopen
textPage = urlopen('http://www.pythonscraping.com/pages/warandpeace/chapter1-ru.txt')
print(str(textPage.read(), 'utf-8'))
Вот как выглядит это концепция в BeautifulSoup и Python 3.x:
html = urlopen('http://en.wikipedia.org/wiki/Python_(programming_language)')
bs = BeautifulSoup(html, 'html.parser')
content = bs.find('div', {'id':'mw-content-text'}).get_text()
content = bytes(content, 'UTF-8')
content = content.decode('UTF-8')
Python 3.x по умолчанию кодирует все символы в UTF-8. Может быть соблазн оставить это как есть и использовать кодировку UTF-8 для каждого веб-скрейпера, который вы пишете. В конце концов, UTF-8 также плавно обрабатывает ASCII-символы, а также иностранные языки. Однако важно помнить о 9% веб-сайтов, которые используют некоторую версию кодировки ISO, поэтому вы никогда не сможете полностью избежать этой проблемы.
К сожалению, в случае текстовых документов невозможно однозначно определить, какая кодировка у документа. Некоторые библиотеки могут проанализировать документ и сделать наилучшее предположение (используя немного логики, чтобы понять, что «Ñ€Ð°ÑÑказѻ вероятно не является словом), но часто это неверно.
К счастью, в случае HTML-страниц кодировка обычно содержится в теге в секции <head> сайта. Большинство сайтов, особенно англоязычные, имеют этот тег:
<meta charset="utf-8" />
В то время как на сайте ECMA International этот тег выглядит так:
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
Если вы планируете часто делать веб-скрейпинг, особенно на русскоязычных сайтах (или сайтах на языках, отличных от латиницы), было бы разумно искать этот метатег и использовать рекомендуемую им кодировку при чтении содержимого страницы.
Формат CSV
При веб-скрейпинге вы вероятно столкнетесь либо с файлом CSV, либо с коллегой, который предпочитает данные в таком формате. К счастью, в Python есть отличная библиотека как для чтения, так и для записи CSV файлов. Хотя эта библиотека способна обрабатывать множество вариаций CSV, эта секция в основном сосредотачивается на стандартном формате. Если у вас есть специальный случай, который вам нужно обработать, обратитесь к документации!
Чтение CSV файлов
Библиотека csv в Python в основном ориентирована на работу с локальными файлами, исходя из предположения, что данные CSV, которые вам нужны, хранятся на вашем компьютере. К сожалению, это не всегда так, особенно когда вы занимаетесь веб-скрейпингом. Есть несколько способов обойти это:
- Скачайте файл локально вручную и укажите Python местоположение локального файла.
- Напишите скрипт Python для скачивания файла, чтения его и (при необходимости) удаления после получения.
- Получите файл в виде строки из веба и оберните строку в объект StringIO, чтобы он вел себя как файл.
Хотя первые два варианта работоспособны, хранение файлов на жестком диске, когда вы могли бы легко держать их в памяти, является плохой практикой. Гораздо лучше считывать файл как строку и обертывать его в объект, который позволяет Python рассматривать его как файл, но не сохранять его. В следующем скрипте извлекается CSV файл из интернета (в данном случае, список альбомов Монти Пайтона по адресу http://pythonscraping.com/files/MontyPythonAlbums.csv) и выводится построчно на терминал:
from urllib.request import urlopen
from io import StringIO
import csv
data = urlopen('http://pythonscraping.com/files/MontyPythonAlbums.csv').read().decode('ascii', 'ignore')
dataFile = StringIO(data)
csvReader = csv.reader(dataFile)
for row in csvReader:
print(row)
Вывод выглядит следующим образом:
['Name', 'Year'] ["Monty Python's Flying Circus", '1970']
['Another Monty Python Record', '1971']
["Monty Python's Previous Record", '1972']
Как видно из примера кода, объект reader, возвращаемый функцией csv.reader, является итерируемым и состоит из объектов типа список в Python. Благодаря этому, каждая строка в объекте csvReader доступна следующим образом:
for row in csvReader:
print('The album "' + row[0] + '" was released in ' + str(row[1]))
Вывод
The album "Name" was released in Year
The album "Monty Python's Flying Circus" was released in 1970
The album "Another Monty Python Record" was released in 1971
The album "Monty Python's Previous Record" was released in 1972
Заметьте первую строку: The album «Name» was released in Year. Хотя это может быть результатом, который легко проигнорировать при написании примерного кода, вы не захотите, чтобы такая строка попала в ваши данные в реальном мире. Менее опытный программист может просто пропустить первую строку в объекте csvReader или написать специальный случай для ее обработки. К счастью, существует альтернатива функции csv.reader, которая делает всю эту работу автоматически за вас. Встречайте DictReader:
from urllib.request import urlopen
from io import StringIO
import csv
data = urlopen('http://pythonscraping.com/files/MontyPythonAlbums.csv').read().decode('ascii', 'ignore')
dataFile = StringIO(data)
dictReader = csv.DictReader(dataFile)
print(dictReader.fieldnames)
for row in dictReader:
print(row)
csv.DictReader возвращает значения каждой строки в CSV файле в виде объектов словаря, а не объектов списка, с названиями полей, хранящимися в переменной dictReader.fieldnames и в качестве ключей в каждом словарном объекте:
['Name', 'Year']
{'Name': "Monty Python's Flying Circus", 'Year': '1970'}
{'Name': 'Another Monty Python Record', 'Year': '1971'}
{'Name': "Monty Python's Previous Record", 'Year': '1972'}
Конечно, недостатком является то, что создание, обработка и печать этих объектов DictReader занимает немного больше времени по сравнению с csvReader, но удобство и простота использования зачастую стоят дополнительной нагрузки. Также имейте в виду, что в случае веб-скрейпинга накладные расходы, необходимые для запроса и получения данных веб-сайта с внешнего сервера, почти всегда будут неизбежным ограничивающим фактором в любой программе, которую вы напишете, поэтому беспокоиться о том, какая техника может сэкономить микросекунды общего времени выполнения, зачастую бесполезно!
Формат pdf
Как пользователь Linux, я знаю, как больно получать файл .docx, который моя немайкрософтовская программа испортит, и бороться, пытаясь найти кодеки для интерпретации нового формата медиафайлов от Apple. В некотором смысле Adobe была революционна, создав свой Портативный формат документа в 1993 году. PDF-файлы позволили пользователям на разных платформах просматривать изображения и текстовые документы точно так же, независимо от платформы, на которой они их просматривали.
Хотя хранение PDF-файлов в Интернете уже немодно (зачем хранить контент в статическом, медленно загружающемся формате, когда можно было бы написать его в HTML?), PDF-файлы остаются повсеместными, особенно когда речь идет о официальных формах и заявлениях.
В 2009 году британец по имени Ник Иннес стал известен, когда запросил информацию о результате тестов общественных студентов у Совета Бакингемшира, которая была доступна в рамках британской версии Закона о свободе информации. После нескольких повторных запросов и отказов, он наконец получил нужную информацию в виде 184 PDF-документов.
Хотя Иннес настоял и в конечном итоге получил более правильно оформленную базу данных, если бы он был опытным веб-скрапером, он, вероятно, смог бы сэкономить себе много времени в судах и использовать PDF-документы напрямую с помощью одного из множества модулей Python для анализа PDF.
PDFMiner3K — одна из относительно простых в использовании библиотек для работы с pdf. Она гибкая и позволяет использовать как из командной строки, так и в существующем коде. Также она может обрабатывать различные языковые кодировки — это часто пригождается в сети.
Документация находится по адресу /pdfminer3k-1.3.0/docs/index.html в извлеченной папке, хотя текущая документация, как правило, ориентирована больше на интерфейс командной строки, чем на интеграцию с кодом Python.
Базовая реализация, которая позволяет читать произвольные PDF-файлы в строку, имея локальный файловый объект:
from urllib.request import urlopen
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from io import StringIO
from io import open
def readPDF(pdfFile):
rsrcmgr = PDFResourceManager()
retstr = StringIO()
laparams = LAParams()
device = TextConverter(rsrcmgr, retstr, laparams=laparams)
process_pdf(rsrcmgr, device, pdfFile)
device.close()
content = retstr.getvalue()
retstr.close()
return content
pdfFile = urlopen('http://pythonscraping.com/pages/warandpeace/chapter1.pdf')
outputString = readPDF(pdfFile)
print(outputString)
pdfFile.close()
Это дает знакомый текстовый вывод:
ГЛАВА I "Ну что, князь, Генуя и Лукка теперь лишь владения Бонапарта. Но я предупреждаю тебя, если ты не скажешь мне, что это значит война, если ты все еще пытаешься оправдать бесчинства и ужасы, совершенные тем Антихристом (я действительно верю, что он Антихрист) - я собираюсь ...
Хорошо то, что этот PDF-ридер позволяет работать с файлами локально, вы можете заменить обычный файловый объект Python на тот, который возвращает urlopen, и использовать эту строку:
pdfFile = open('../pages/warandpeace/chapter1.pdf', 'rb')
Результат может быть неидеальным, особенно для PDF-файлов с изображениями, странно оформленным текстом или текстом, расположенным в таблицах или графиках. Однако для большинства PDF-файлов только с текстом вывод должен быть таким же, как если бы PDF-файл был текстовым файлом.
Форматы Microsoft Word
На свой страх и риск, не желая обидеть моих друзей из Microsoft: мне не нравится Microsoft Word. Не потому что это необходимо плохое программное обеспечение, а из-за того, как его пользователи его злоупотребляют. Он обладает особенным талантом превращать то, что должно быть простым текстовым документом или PDF, в большие, медленные, трудно открываемые чудовища, часто теряющие всю форматировку с машины на машину и, по какой-то причине, редактируемые, когда контент часто предназначен быть статичным.
Файлы Word предназначены для создания контента, а не для его обмена. Тем не менее, они повсеместно распространены на определенных сайтах, содержа важные документы, информацию, и даже диаграммы и мультимедиа; короче говоря, все то, что может и должно быть создано с помощью HTML.
До примерно 2008 года продукты Microsoft Office использовали собственный формат файла .doc. Этот двоичный формат файла был труден для чтения и плохо поддерживался другими текстовыми процессорами. В попытке пойти в ногу со временем и принять стандарт, используемый многими другими программными продуктами, Microsoft решила использовать стандарт на основе Open Office XML, который сделал файлы совместимыми с открытым и другим программным обеспечением.
К сожалению, поддержка Python для этого формата файла, используемого Google Docs, Open Office и Microsoft Office, все еще не очень хороша. Существует библиотека python-docx, но она позволяет пользователям только создавать документы и читать только базовые данные о файле, такие как размер и заголовок файла, но не сам контент. Для чтения содержимого файла Microsoft Office вам придется создать свое собственное решение.
Первый шаг — прочитать XML из файла:
from zipfile import ZipFile
from urllib.request import urlopen
from io import BytesIO
wordFile = urlopen('http://pythonscraping.com/pages/AWordDocument.docx').read()
wordFile = BytesIO(wordFile)
document = ZipFile(wordFile)
xml_content = document.read('word/document.xml')
print(xml_content.decode('utf-8'))
Этот код читает удаленный файл Word как объект двоичного файла (BytesIO аналогичен StringIO, использованному ранее в этой главе), разархивирует его с помощью встроенной в Python библиотеки zipfile (все файлы .docx являются zip-архивами для экономии места), а затем читает разархивированный файл, который представляет собой XML.
Результат выполнения скрипта Python для чтения моего простого файла Word следующий:
<!--?xml version="1.0" encoding="UTF-8" standalone="yes"?-->
<w:document mc:ignorable="w14 w15 wp14" xmlns:m="http://schemas.openx
mlformats.org/officeDocument/2006/math" xmlns:mc="http://schemas.open
xmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-micros
oft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/off
iceDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vm
l" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/m
ain" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="htt
p://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://
schemas.microsoft.com/office/word/2012/wordml" xmlns:wne="http://sche
mas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.o
penxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="h
ttp://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" x
mlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessin
gCanvas" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wor
dprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word
/2010/wordprocessingInk" xmlns:wps="http://schemas.microsoft.com/offi
ce/word/2010/wordprocessingShape"><w:body><w:p w:rsidp="00764658" w:r
sidr="00764658" w:rsidrdefault="00764658"><w:ppr><w:pstyle w:val="Tit
le"></w:pstyle></w:ppr><w:r><w:t>A Word Document on a Website</w:t></
w:r><w:bookmarkstart w:id="0" w:name="_GoBack"></w:bookmarkstart><w:b
ookmarkend w:id="0"></w:bookmarkend></w:p><w:p w:rsidp="00764658" w:r
sidr="00764658" w:rsidrdefault="00764658"></w:p><w:p w:rsidp="0076465
8" w:rsidr="00764658" w:rsidrdefault="00764658" w:rsidrpr="00764658">
<w: r> <w:t>This is a Word document, full of content that you want ve
ry much. Unfortunately, it’s difficult to access because I’m putting
it on my website as a .</w:t></w:r><w:prooferr w:type="spellStart"></
w:prooferr><w:r><w:t>docx</w:t></w:r><w:prooferr w:type="spellEnd"></
w:prooferr> <w:r> <w:t xml:space="preserve"> file, rather than just p
ublishing it as HTML</w:t> </w:r> </w:p> <w:sectpr w:rsidr="00764658"
w:rsidrpr="00764658"> <w:pgszw:h="15840" w:w="12240"></w:pgsz><w:pgm
ar w:bottom="1440" w:footer="720" w:gutter="0" w:header="720" w:left=
"1440" w:right="1440" w:top="1440"></w:pgmar> <w:cols w:space="720"><
/w:cols&g; <w:docgrid w:linepitch="360"></w:docgrid> </w:sectpr> </w:
body> </w:document>
Здесь много метаданных, но фактический текст, который вам нужен, спрятан. К счастью, весь текст в документе, включая заголовок вверху, содержится в тегах w:t, что делает его легко извлекаемым:
from zipfile import ZipFile
from urllib.request import urlopen
from io import BytesIO
from bs4 import BeautifulSoup
wordFile = urlopen('http://pythonscraping.com/pages/AWordDocument.docx').read()
wordFile = BytesIO(wordFile)
document = ZipFile(wordFile)
xml_content = document.read('word/document.xml')
wordObj = BeautifulSoup(xml_content.decode('utf-8'), 'xml')
textStrings = wordObj.find_all('w:t')
for textElem in textStrings:
print(textElem.text)
Обратите внимание, что вместо парсера html.parser, который вы обычно используете с BeautifulSoup, вы передаете ему парсер xml. Это потому, что двоеточия являются неправильными в именах тегов HTML, таких как w:t, и html.parser их не распознает. Результат не идеален, но он приближается к нему, и вывод каждого тега w:t на новой строке делает его легко читаемым:
A Word Document on a Website
This is a Word document, full of content that you want very much. Unfortunately,
it’s difficult to access because I’m putting it on my website as a .
docx
file, rather than just publishing it as HTML
Обратите внимание, что слово «docx» находится на отдельной строке. В исходном XML оно окружено тегом <w:proofErr w:type=»spellStart»/>. Это способ Word выделить «docx» красной волнистой линией, указывая на то, что он считает, что в названии его собственного формата файла есть ошибка в написании. Заголовок документа предшествует тегу-описателю стиля <w:pstyle w:val=»Title»>. Хотя это не делает его чрезвычайно легким для нас идентифицировать заголовки (или другие стилизованные тексты) как таковые, использование функций навигации BeautifulSoup может быть полезным:
textStrings = wordObj.find_all('w:t')
for textElem in textStrings:
style = textElem.parent.parent.find('w:pStyle')
if style is not None and style['w:val'] == 'Title':
print('Title is: {}'.format(textElem.text))
else:
print(textElem.text)
Эта функция легко может быть расширена для вывода тегов вокруг различных стилей текста или маркировки их каким-либо другим способом.
Индивидуальное и групповое обучение «Аналитик данных»
Если вы хотите стать экспертом в аналитике, могу помочь. Запишитесь на мой курс «Аналитик данных» и начните свой путь в мир ИТ уже сегодня!
Контакты
Для получения дополнительной информации и записи на курсы свяжитесь со мной:
Телеграм: https://t.me/Vvkomlev
Email: victor.komlev@mail.ru
Объясняю сложное простыми словами. Даже если вы никогда не работали с ИТ и далеки от программирования, теперь у вас точно все получится! Проверено десятками примеров моих учеников.
Гибкий график обучения. Я предлагаю занятия в мини-группах и индивидуально, что позволяет каждому заниматься в удобном темпе. Вы можете совмещать обучение с работой или учебой.
Практическая направленность. 80%: практики, 20% теории. У меня множество авторских заданий, которые фокусируются на практике. Вы не просто изучаете теорию, а сразу применяете знания в реальных проектах и задачах.
Разнообразие учебных материалов: Теория представлена в виде текстовых уроков с примерами и видео, что делает обучение максимально эффективным и удобным.
Понимаю, что обучение информационным технологиям может быть сложным, особенно для новичков. Моя цель – сделать этот процесс максимально простым и увлекательным. У меня персонализированный подход к каждому ученику. Максимальный фокус внимания на ваши потребности и уровень подготовки.