Сосредоточены на конкретных результатах, очищая Twitter с помощью Python и Beautiful Soup 4?

Это продолжение моего сообщения Использование Python для очистки Вложенные элементы Div и Spans в Twitter?.

Я не использую Twitter API, потому что он не просматривает твиты по хэштегам так давно. Полный код и выходные данные приведены ниже после примеров.

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

Например:

 link = soup('a', {'class': 'tweet-timestamp js-permalink js-nav js-tooltip'})
 url = link[0]

Получает это:

 <a class="tweet-timestamp js-permalink js-nav js-tooltip" href="/Mikepeeljourno/status/648787700980408320" title="2:13 AM - 29 Sep 2015">
 <span class="_timestamp js-short-timestamp " data-aria-label-part="last" data-long-form="true" data-time="1443518016" data-time-ms="1443518016000">29 Sep 2015</span></a>

Для URL мне нужно только значение href из первой строки.

Точно так же команды retweets и favorites возвращают большие фрагменты html, когда все, что мне действительно нужно, это числовое значение, отображаемое для каждого из них.

Как я могу сузить результаты до необходимых данных для выходных данных URL, retweetcount и favcount?

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

Полный код:

 from bs4 import BeautifulSoup
 import requests
 import sys

 url = 'https://twitter.com/search?q=%23bangkokbombing%20since%3A2015-08-10%20until%3A2015-09-30&src=typd&lang=en'
 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36'}
 r = requests.get(url, headers=headers)
 data = r.text.encode('utf-8')
 soup = BeautifulSoup(data, "html.parser")

 name = soup('strong', {'class': 'fullname js-action-profile-name show-popup-with-id'})
 username = name[0].contents[0]

 handle = soup('span', {'class': 'username js-action-profile-name'})
 userhandle = handle[0].contents[1].contents[0]

 link = soup('a', {'class': 'tweet-timestamp js-permalink js-nav js-tooltip'})
 url = link[0]

 messagetext = soup('p', {'class': 'TweetTextSize  js-tweet-text tweet-text'})
 message = messagetext[0]

 retweets = soup('button', {'class': 'ProfileTweet-actionButtonUndo js-actionButton js-actionRetweet'})
 retweetcount = retweets[0]

 favorites = soup('button', {'class': 'ProfileTweet-actionButtonUndo u-linkClean js-actionButton js-actionFavorite'})
 favcount = favorites[0]

 print (username, "\n", "@", userhandle, "\n", "\n", url, "\n", "\n", message, "\n", "\n", retweetcount, "\n", "\n", favcount) #extra linebreaks for ease of reading

Полный вывод:

Michael Peel

@Mikepeeljourno

<a class="tweet-timestamp js-permalink js-nav js-tooltip" href="/Mikepeeljourno/status/648787700980408320" title="2:13 AM - 29 Sep 2015"><span class="_timestamp js-short-timestamp " data-aria-label-part="last" data-long-form="true" data-time="1443518016" data-time-ms="1443518016000">29 Sep 2015</span></a>

<p class="TweetTextSize js-tweet-text tweet-text" data-aria-label-part="0" lang="en"><a class="twitter-hashtag pretty-link js-nav" data-query-source="hashtag_click" dir="ltr" href="/hashtag/FT?src=hash"><s>#</s><b>FT</b></a> Case closed: <a class="twitter-hashtag pretty-link js-nav" data-query-source="hashtag_click" dir="ltr" href="/hashtag/Thailand?src=hash"><s>#</s><b>Thailand</b></a> police chief proclaims <a class="twitter-hashtag pretty-link js-nav" data-query-source="hashtag_click" dir="ltr" href="/hashtag/Bangkokbombing?src=hash"><s>#</s><b><strong>Bangkokbombing</strong></b></a> solved ahead of his retirement this week -even as questions over case grow</p>

<button class="ProfileTweet-actionButtonUndo js-actionButton js-actionRetweet" data-modal="ProfileTweet-retweet" type="button">
<div class="IconContainer js-tooltip" title="Undo retweet">
<span class="Icon Icon--retweet"></span>
<span class="u-hiddenVisually">Retweeted</span>
</div>
<div class="IconTextContainer">
<span class="ProfileTweet-actionCount">
<span aria-hidden="true" class="ProfileTweet-actionCountForPresentation">4</span>
</span>
</div>
</button>

<button class="ProfileTweet-actionButtonUndo u-linkClean js-actionButton js-actionFavorite" type="button">
<div class="IconContainer js-tooltip" title="Undo like">
<div class="HeartAnimationContainer">
<div class="HeartAnimation"></div>
</div>
<span class="u-hiddenVisually">Liked</span>
</div>
<div class="IconTextContainer">
<span class="ProfileTweet-actionCount">
<span aria-hidden="true" class="ProfileTweet-actionCountForPresentation">2</span>
</span>
</div>
</button>

Было высказано предположение, что BeautifulSoup - извлечение значений атрибутов может иметь ответ на этот вопрос. Однако я думаю, что вопрос и ответы на него не имеют достаточного контекста или объяснения, чтобы быть полезными в более сложных ситуациях. Ссылка на соответствующую часть документации Beautiful Soup полезна: http://www.crummy.com/software/BeautifulSoup/documentation.html#The%20attributes%20of%20Tags


person David Beales    schedule 26.01.2016    source источник
comment
Возможный дубликат BeautifulSoup - извлечение значений атрибутов   -  person Casimir Crystal    schedule 26.01.2016
comment
@KevinGuan, в его вопросе есть нечто большее, чем просто извлечение атрибута href. Поиск потомков из расширенного ResultSet немного сбивает с толку, на что я ответил ниже.   -  person oxalorg    schedule 26.01.2016


Ответы (2)


Используйте словарный доступ к атрибутам Tag.

Например, чтобы получить значение атрибута href:

links = soup('a', {'class': 'tweet-timestamp js-permalink js-nav js-tooltip'})
url = link[0]["href"]

Или, если вам нужно получить значения href для каждой найденной ссылки:

links = soup('a', {'class': 'tweet-timestamp js-permalink js-nav js-tooltip'})
urls = [link["href"] for link in links]

В качестве примечания: вам не нужно указывать полное значение class для поиска элементов. class — это специальный многозначный атрибут, и вы можете просто использовать один из классов (если этого достаточно, чтобы сузить поиск нужных элементов). Например, вместо:

soup('a', {'class': 'tweet-timestamp js-permalink js-nav js-tooltip'})

Вы можете использовать:

soup('a', {'class': 'tweet-timestamp'})

Или CSS-селектор:

soup.select("a.tweet-timestamp")
person alecxe    schedule 26.01.2016
comment
Это два отличных ответа с несколькими решениями. Я понимаю, что невозможно принять оба ответа как правильные, но я бы хотел, чтобы это было... Большое спасибо. - person David Beales; 26.01.2016
comment
Этот ответ был выбран из-за примеров циклов, словарного запаса, облегчающего дальнейший поиск, и полезной информации о выборе многозначных атрибутов. Но опять же, оба были превосходны. - person David Beales; 27.01.2016

Alexxe уже объяснил, как использовать ключ href для получения значения.

Итак, я собираюсь ответить на другую часть ваших вопросов:

Точно так же команды ретвитов и избранного возвращают большие фрагменты html, когда все, что мне действительно нужно, — это числовое значение, которое отображается для каждого из них.

.contents возвращает список всех дочерних элементов. Поскольку вы находите «кнопки», у которых есть несколько интересующих вас дочерних элементов, вы можете просто получить их из следующего проанализированного списка содержимого:

retweetcount = retweets[0].contents[3].contents[1].contents[1].string

Это вернет значение 4.

Если вам нужен более читаемый подход, попробуйте следующее:

retweetcount = retweets[0].find_all('span', class_='ProfileTweet-actionCountForPresentation')[0].string

favcount = favorites[0].find_all('span', { 'class' : 'ProfileTweet-actionCountForPresentation')[0].string

Это возвращает 4 и 2 соответственно. Это работает, потому что мы преобразуем ResultSet, возвращаемый супом/find_all, и получаем элемент тега (используя [0]) и снова рекурсивно находим всех его потомков, используя find_all().

Теперь вы можете просмотреть каждый твит и довольно легко извлечь эту информацию.

person oxalorg    schedule 26.01.2016