Python: scrapy, selenium, beautiful soup что лучше для парсинга веб сайтов

Понимание реальных веб-страниц

Давайте поймем, с чем мы сталкиваемся, посмотрев на вывод какого-то общего кода веб-приложения. В статье «Введение в Vagrant» есть некоторые комментарии Disqus в нижней части страницы:

Чтобы получить эти комментарии, нам нужно сначала найти их на странице.

Просмотр источника страницы

Каждый браузер с самого начала (1990-е годы) поддерживал возможность просмотра HTML текущей страницы. Вот фрагмент из источника представления «Введение в Vagrant», который начинается с огромного фрагмента миниатюрного и укрреченного JavaScript, не связанного с самой статьей. Вот небольшая его часть:

Вот некоторые фактические HTML со страницы:

Это выглядит довольно грязно, но удивительно то, что вы не найдете комментарии Disqus в источнике страницы.

Inline Frame

В этом есть смысл. Встраивание стороннего контента в качестве iframe является одной из основных причин использования iframe. Давайте найдем тег , затем в источнике главной страницы. Опровергнуто снова! В источнике главной страницы нет тега .

Разметка с использованием JavaScript

Причиной этого упущения является то, что показывает вам контент, который был получен с сервера. Но итоговый DOM (объектная модель документа), получаемый браузером, может быть совсем другой. JavaScript запускается и может манипулировать DOM по своему усмотрению. Невозможно найти iframe, потому что его не было, когда страница была получена с сервера.

find() Method

find() is one of the best features in BeautifulSoup. It helps aggregate DOM elements easily so you can manipulate what you need.

Knowing which HTML element you want on a webpage is half the battle. To do this I like to use the Google Chrome browser’s Inspect feature. On a Mac, if you hover over the element you want to grab (in this instance, the “Buy Stickers” button on the pyladies.com, and 2-finger press, a menu opens with the “Inspect” option. On a Windows machine, it’s a right-click while hovering over the element with a similar menu option. To access web page elements in other browsers, read more here.

How to Inspect the DOM of a webpage

Identifying the “Buy Stickers” button on the webpage’s HTML code

Once you uniquely identify the element, then you can use BeautifulSoup’s find() to locate it. In this case, it’s

soup.find('div', id="stickers_btn")  # Use print() for the results

Printing the results display the following.

Adding “print(soup.find(‘div’, id=”stickers_btn”))”

Installing multiple versions

On Unix and Mac systems if you intend to install multiple versions of Python
using the same installation prefix ( argument to the configure
script) you must take care that your primary python executable is not
overwritten by the installation of a different version. All files and
directories installed using contain the major and minor
version and can thus live side-by-side. also creates
which refers to . If you
intend to install multiple versions using the same prefix you must decide which
version (if any) is your «primary» version. Install that version using . Install all other versions using .

For example, if you want to install Python 2.7, 3.6, and 3.10 with 3.10 being the
primary version, you would execute in your 3.10 build directory
and in the others.

Navigating the DOM

You can navigate through the DOM tree using regular tag names. Chaining those tag names can help you navigate the tree more deeply. For example, you can get the first link in the first paragraph of the given Wikipedia page by using . All the links in the first paragraph can be accessed by using .

You can also access all the children of a tag as a list by using . To get the children at a specific index, you can use . You can also iterate over a tag’s children by using the  attribute.

Both and are useful only when you want to access the direct or first-level descendants of a tag. To get all the descendants, you can use the  attribute.

You can also access the parent of an element using the attribute. Similarly, you can access all the ancestors of an element using the attribute. The parent of the top-level tag is the Object itself, and its parent is None.

You can access the previous and next sibling of an element using the and attributes. 

For two elements to be siblings, they should have the same parent. This means that the first child of an element will not have a previous sibling. Similarly, the last child of the element will not have a next sibling. In actual webpages, the previous and next siblings of an element will most probably be a new line character. 

You can also iterate over all the siblings of an element using and .

You can go to the element that comes immediately after the current element using the attribute. To access the element that comes immediately before the current element, use the attribute. 

Similarly, you can iterate over all the elements that come before and after the current element using and respectively.

Discovering the Rest of BeautifulSoup’s Methods

If you want to see the many possible commands in Beautiful Soup, you can use the python’s Interactive Mode and use the double tab feature, <tab><tab> after the and the period ”.” to list the possibilities. This is similar to the dir() python method.

Enter the program above into python.

$ python3Python 3.4.3 (default, Nov 28 2017, 16:41:13) on linuxType "help", "copyright", "credits" or "license" for more information.

Hit <tab><tab> quickly at the “soup.” text you just entered (including the period without spaces).

Generate a list of Beautiful Soup commands in python Interactive Mode using <tab><tab>

find_all() Method

Now, if you want to put all of the same type of elements into an array, BeautifulSoup has find_all().

soup.find_all('a')      # finds all <a> elementssoup.find_all('a')   # reference the first <a> elementsoup.find_all('a')   # reference the second <a> element

Once you have them in an array, now you can iterate over your data. This is the power of using a programming language. This is when I found Selenium IDE lacking and shifted over to Selenium WebDriver and Java. Looping through elements was vital to manipulate the data and being able to use program logic.

for link in soup.find_all('a'):  # iterate over every <a> tag    print(link)                  # print it to the screen

Print each <a> tag in pyladies.com

Build Instructions

On Unix, Linux, BSD, macOS, and Cygwin:

./configure
make
make test
sudo make install

This will install Python as .

You can pass many options to the configure script; run
to find out more. On macOS case-insensitive file systems and on Cygwin,
the executable is called ; elsewhere it’s just .

On macOS, there are additional configure and build options related
to macOS framework and universal builds. Refer to Mac/README.rst.

On Windows, see PCbuild/readme.txt.

If you wish, you can create a subdirectory and invoke configure from there.
For example:

mkdir debug
cd debug
../configure --with-pydebug
make
make test

(This will fail if you also built at the top-level directory. You should do
a at the top-level first.)

To get an optimized build of Python,
before you run . This sets the default make targets up to enable
Profile Guided Optimization (PGO) and may be used to auto-enable Link Time
Optimization (LTO) on some platforms. For more details, see the sections
below.

PGO takes advantage of recent versions of the GCC or Clang compilers. If used,
either via or by manually running
regardless of configure flags, the optimized build
process will perform the following steps:

The entire Python directory is cleaned of temporary files that may have
resulted from a previous compilation.

An instrumented version of the interpreter is built, using suitable compiler
flags for each flavour. Note that this is just an intermediary step. The
binary resulting from this step is not good for real life workloads as it has
profiling instructions embedded inside.

After the instrumented interpreter is built, the Makefile will run a training
workload. This is necessary in order to profile the interpreter execution.
Note also that any output, both stdout and stderr, that may appear at this step
is suppressed.

The final step is to build the actual interpreter, using the information
collected from the instrumented one. The end result will be a Python binary
that is optimized; suitable for distribution or production installation.

Enabled via configure’s flag. LTO takes advantage of the
ability of recent compiler toolchains to optimize across the otherwise
arbitrary file boundary when building final executables or shared
libraries for additional performance gains.

Installing a Parser

Before discussing the differences between different parsers that you can use with Beautiful Soup, let’s write the code to create a soup.

The  object can accept two arguments. The first argument is the actual markup, and the second argument is the parser that you want to use. The different parsers are: , lxml, and html5lib. The parser has two versions, an HTML parser and an XML parser.

The  is a built-in parser, and it does not work so well in older versions of Python. You can install the other parsers using the following commands:

The parser is very fast and can be used to quickly parse given HTML. On the other hand, the parser is very slow, but it is also extremely lenient. Here is an example of using each of these parsers:

The differences outlined by the above example only matter when you are parsing invalid HTML. However, most of the HTML on the web is malformed, and knowing these differences will help you in debugging some parsing errors and deciding which parser you want to use in a project. Generally, the  parser is a very good choice.

Installation

You can install Beautiful Soup 4 using . The package name is . It should work on both Python 2 and Python 3.

If you don’t have pip installed on your system, you can directly download the Beautiful Soup 4 source tarball and install it using .

BeautifulSoup is originally packaged as Python 2 code. When you install it for use with Python 3, it is automatically updated to Python 3 code. The code won’t be converted unless you install the package. Here are a few common errors that you might notice:

  • The “No module named HTMLParser”  occurs when you are running the Python 2 version of the code under Python 3.
  • The “No module named html.parser”  occurs when you are running the Python 3 version of the code under Python 2.

Both the errors above can be corrected by uninstalling and reinstalling Beautiful Soup.

Подсчет комментариев Disqus

Давайте сделаем некоторый динамический скрапинг и используем Selenium для подсчета комментариев Disqus в Tuts + tutorials. Вот необходимые импорты.

Функция принимает драйвер и URL-адрес. Он использует метод драйвера для извлечения URL-адреса. Это похоже на , но разница в том, что объект-драйвер управляет живым представлением DOM.

Затем он получает название учебника и находит iframe Disqus, используя его родительский id , а затем сам iframe:

Следующим шагом будет выбор содержимого самого iframe

Обратите внимание, что мы ожидаем присутствия элемента , потому что комментарии загружаются динамически и необязательно будут сразу доступны

Последняя часть должна вернуть последний комментарий, если он не был сделан мной. Идея состоит в том, чтобы обнаружить комментарии, на которые я еще не ответил.

MAKING THE UGLY, BEAUTIFUL

When BeautifulSoup parses html, it‘s not usually in the best of formats. The spacing is pretty horrible. The tags are difficult to find. Here is an image to show what they would look like when you get to print the soup:

However, there is a solution to this. The solution gives the html the perfect spacing, making things look good. This solution is deservedly called “prettify“.

Admittedly, you may not get to use this feature most of the time; however there are times when you may not have access to the inspect element tool of a web browser. In those times of limited resources, you would find the prettify method very useful.

Here is how you use it:

soup.prettify()

The markup would look properly spaced, just like in the image below:

When you apply the prettify method on the soup, the result is no longer a type  bs4.BeautifulSoup. The result is now type ‘unicode‘. This means you cannot apply other BeautifulSoup methods on it, however the soup itself is not affected so we are safe.

FINDING OUR FAVORITE TAGS

HTML is made up of tags. It stores all of it’s data in them, and in the midst of all that clutter lies the data we need. Basically, this means when we find the right tags, we can get what we need.

So how do we find the right tags? We make use of BeautifulSoup‘s find and find_all methods.

Here‘s how they work:

The find method searches for the first tag with the needed name and returns an object of type bs4.element.Tag.

The find_all method on the other hand, searches for all tags with the needed tag name and returns them as a list of type bs4.element.ResultSet. All the items in the list are of type bs4.element.Tag, so we can carry out indexing on the list and continue our beautifulsoup exploration.

Let‘s see some code. Let‘s find all the div tags:

soup.find(“div“)

We would get the following result:

<div class=»name»><b>Name:<b>Dr Peter Parker<div>

Checking the html variable, you would notice that this is the first div tag.

soup.find_all(“div“)

We would get the following result:

It returns a list.  If for example you want the third div tag, you run the following code:

soup.find_all(“div“)2

It would return the following:

<div class=»telephone»><b>Telephone:</b>+12345678910</div>

FINDING THE ATTRIBUTES OF OUR FAVORITE TAGS

Now that we have seen how to get our favorite tags, how about getting their attributes?

When we have extracted the needed tag, using the find or find_all methods, we can get attributes by applying attrs. This would return a dictionary of the attribute and it‘s value.

soup.find_all(“a“).attrs

Which would return the following result:

{‘href’: ‘mailto:peteparker@svalley.com’}

Same thing for the website attribute.

soup.find_all(“a“)1.attrs

Which would return the following result:

{‘href’: ‘<a href=»http://pparkerworks.com/»>http://pparkerworks.com</a>’}

The returned values are dictionaries and normal dictionary syntax can be applied to get the keys and values.

LET‘S SEE THE PARENT AND CHILDREN

There are tags everywhere. Sometimes, we want to know what the children tags are and what the parent tag is.

If you don‘t already know what a parent and child tag is, this brief explanation should suffice: a parent tag is the immediate outer tag and a child is the immediate inner tag of the tag in question.

Taking a look at our html, the body tag is the parent tag of all the div tags. Also, the bold tag and the anchor tag are the children of the div tags, where applicable as not all div tags possess anchor tags.

So we can access the parent tag by calling the findParent method.

soup.find(«div»).findParent()

This would return the whole of the body tag:

To get the children tag of the fourth div tag, we call the findChildren method:

soup.find_all(«div»)4.findChildren()

It returns the following:

[<b>Website:<b>, <a href=»http://pparkerworks.com»>pparkerworks.com<a>]

WHAT‘S IN IT FOR US?

When browsing web pages, we do not see tags everywhere on the screen. All we see is the content of the different tags. What if we want the content of a tag, without all of the angular brackets making life uncomfortable? That‘s not difficult, all we‘d do is to call get_text method on the tag of choice and we get the text in the tag and if the tag has other tags in it, it also gets their text values.

Here‘s an example:

soup.find(«body»).get_text()

This returns all of the text values in the body tag:

CONCLUSION

That‘s what we‘ve got for this article. However, there are still other interesting things that can be done with beautifulsoup. You can either check out the documentation or use dir(BeautfulSoup) on the interactive shell to see the list of operations that can be carried out on a BeautifulSoup object. That‘s all from me today, till I write again.

Objects in Beautiful Soup

Beautiful Soup parses the given HTML document into a tree of Python objects. There are four main Python objects that you need to know about: , , , and .

The  object refers to an actual XML or HTML tag in the document. You can access the name of a tag using . You can also set a tag’s name to something else. The name change will be visible in the markup generated by Beautiful Soup.

You can access different attributes like the class and id of a tag using  and  respectively. You can also access the whole dictionary of attributes using . You can also add, remove or modify a tag’s attributes. The attributes like an element’s  which can take multiple values are stored as a list.

The text within a tag is stored as a  in Beautiful Soup. It has a few useful methods like  to replace the text within a tag. You can also convert a  to unicode string using .

Beautiful Soup also allows you to access the comments in a webpage. These comments are stored as a  object, which is also basically a .

You have already learned about the  object in the previous section. It is used to represent the document as a whole. Since it is not an actual object, it does not have any name or attributes.

Динамический скрапинг с Selenium

Статический скрапинг был достаточно хорош, чтобы получить список статей, но, как мы видели ранее, комментарии Disqus встроены в JavaScript как элемент iframe. Чтобы собрать комментарии, нам нужно будет автоматизировать браузер и взаимодействовать с DOM в интерактивном режиме. Одним из лучших инструментов для работы является Selenium.

Selenium в первую очередь ориентирован на автоматическое тестирование веб-приложений, но он отлично подходит для универсального средства автоматизации браузера.

Выберите свой веб-драйвер

Selenium нужен веб-драйвер (он автоматизирует браузер). Для веб-скрапинга обычно не имеет значения, какой драйвер вы выберете. Я предпочитаю драйвер Chrome. Следуйте инструкциям в этом .

Chrome против PhantomJS

В некоторых случаях вы можете использовать headless браузер, что означает отсутствие отображения пользовательского интерфейса. Теоретически, PhantomJS — это еще один веб-драйвер. Но на практике люди сообщали о проблемах несовместимости, когда Selenium работает правильно с Chrome или Firefox, а иногда и с PhantomJS. Я предпочитаю удалить эту переменную из уравнения и использовать фактический драйвер браузера.

Когда следует использовать веб-скрапера?

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

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

Статические скраперы с запросами и BeautifulSoup

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

Установка Requests и BeautifulSoup

Сначала установите pipenv, а затем:

Это также создаст для вас виртуальную среду. Если вы используете код из gitlab, вы можете просто выполнить .

Получение страниц

Получение страницы с запросами — это одна строка

Объект ответа имеет множество атрибутов. Самые важные из них и . Если запрос терпит неудачу, то будет False, а будет содержать ошибку. Содержимое представляет собой поток байтов. Обычно с текстом лучше декодировать его до utf-8 при работе:

Если все в порядке, то будет содержать запрошенную веб-страницу (такую же, как источник страницы).

Поиск элементов с помощью BeautifulSoup

Функция ниже извлекает веб-страницу по URL-адресам, расшифровывает ее в UTF-8 и анализирует ее в объект BeautifulSoup с помощью парсера HTML.

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

Страницы Tuts + author содержат несколько руководств. Вот моя страница автора. На каждой странице есть до 12 учебников. Если у вас более 12 руководств, вы можете перейти к следующей странице. HTML для каждой статьи заключен в тег . Следующая функция находит все элементы статьи на странице, проходится по их ссылкам и извлекает атрибут href для получения URL-адреса учебника:

Следующий код получает все статьи с моей страницы и печатает их (без общего префикса):

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *