2015-12-30 3 views
4

Я пытаюсь получить самые горячие обои от Reddit's wallpaper subreddit. Я использую beautiful soup, чтобы получить HTML расположение первых обоев А затем regex, чтобы получить URL из метки привязки. Но чаще, чем часто, я получаю URL-адрес, который не соответствует моему регулярному выражению. Вот код, который я использую:Получение лучших обоев от reddit

r = requests.get("https://www.reddit.com/r/wallpapers") 
if r.status_code == 200: 
    print r.status_code 
    text = r.text 
    soup = BeautifulSoup(text, "html.parser") 

search_string = str(soup.find('a', {'class':'title'})) 
photo_url = str(re.search('[htps:/]{7,8}[a-zA-Z0-9._/:.]+[a-zA-Z0-9./:.-]+', search_string).group()) 

Есть ли способ обойти его?

ответ

5

Вот лучший способ сделать это:
Добавление .json до конца URL в Reddit возвращает json объект вместо HTML.
Например https://www.reddit.com/r/wallpapers обеспечит HTML содержание но
https://www.reddit.com/r/wallpapers/.json даст вам объект JSON, который вы можете легко эксплуатировать, используя json модуль в Python

Вот та же программа получения горячих обои:

>>> import urllib 
>>> import json 

>>> data = urllib.urlopen('https://www.reddit.com/r/wallpapers/.json') 
>>> wallpaper_dict = json.loads(data.read()) 

>>> wallpaper_dict['data']['children'][1]['data']['url'] 
u'http://i.imgur.com/C49VtMu.jpg' 

>>> wallpaper_dict['data']['children'][1]['data']['title'] 
u'Space Shuttle' 

>>> wallpaper_dict['data']['children'][1]['data']['domain'] 
u'i.imgur.com' 

Не только это намного чище, но и предотвратит головную боль, если reddit изменит его макет HTML, или кто-то отправит URL-адрес, который не может обработать ваше регулярное выражение.
Как правило, лучше использовать json вместо соскабливания HTML

PS: Список внутри [children] - номер обоев. Первый - самый верхний, второй - второй и т. Д. Поэтому ['data']['children'][2]['data']['url'] предоставит вам ссылку для второго самого горячего обоев. вы получаете суть? :)

PPS: Более того, с помощью этого метода вы можете использовать модуль по умолчанию urllib. Обычно, когда вы очищаете Reddit, вам нужно создать поддельный заголовок User-Agent и передать его во время запроса (или он даст вам код ответа 429, но это не тот случай.

+0

ли добавляющим '.json' на другой' subreddits' 'URL также возвращает объект json? –

+0

@Hodor Да, это так. На всех 'subreddits'. – Jarwin

1

Вот правильный способ сделать это ваш метод, но метод Jarwins лучше. Вы не должны использовать регулярные выражения при работе с HTML. Вы просто должны были ссылаться на атрибут href, чтобы получить ссылки прекращается

import requests 
from bs4 import BeautifulSoup 
r = requests.get("https://www.reddit.com/r/wallpapers") 
if r.status_code == 200: 
    soup = BeautifulSoup(r.text, "html.parser") 
    url = str(soup.find_all('a', {'class':'title'})[1]["href"]) 
    print url