Извлечь URL-адрес в строке JSON с помощью Python, используя re.match() или split()

#python #json #url

#python #json #url

Вопрос:

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

 import json
import urllib

f = open('json-test-file-for-insta-url-snippet.json')
data = json.load(f)

print(json.dumps(data["event"]["attachments"][0]["text"]))
  

Я получил этот результат:

 "u201cUNLIMITED LIVEu201d world tour moved to 2021!nDue to the Covid-19 pandemic and the subsequent regulations and concert restrictions, the world tour, originally planned for the autumn of 2020, could not take place. n"u201eI was very much looking forward to our tour in autumn 2020 all over the world, so Iu2019m deeply sorry that these concerts had to be rescheduled due to the Covid-19 pandemic. Iu2019m very happy that we have already found new dates for our tour in autumn 2021, because I cannot wait to return to get back on stage and to play for you guys. Take care of yourselves u2013 I hope to see you all happy and healthy again very, very soon!u201d nAll your tickets remain valid for the new dates! Please find them below: nnKAZ Almaty - Sep 11, 2021nRUS Yekaterinburg - Sep 14, 2021nRUS Kazan, Sep 16, 2021nRUS Voronezh - Sep 18, 2021nRUS Krasnodar - Sep 20, 2021nRUS Moscow - Sep 22, 2021nRUS St. Petersburg - Sep 24, 2021nUKR Kharkiv - Sep 26 2021nUKR Odessa - Sep 28, 2021nUKR Kiev - Sep 30, 2021nITA Bolzano - Oct 13, 2021nITA Bologna - Oct 15, 2021nITA Genoa - Oct 16, 2021nITA Milano - Oct 17, 2021nITA Conegliano Veneto - Oct 19, 2021nBG Sofia - Oct 24, 2021nRO Bucharest - Oct 26, 2021nRO Cluj - Oct 29, 2021  #davidgarrett #tour2021 #unlimited #live #postponedn*Score* -2.57x | *Likes* 338 (-830) | *Comments* 13 (-46)n_Posted on Tuesday, August 18 at 9:59 AM CEST <https://www.instagram.com/p/CEBew-xHwhJ/|(Instagram)>_n_Received via Viral Alert_"
  

Теперь я хочу извлечь Insta-URL в конце — как я могу это сделать на Python? Возможно ли это только с регулярным выражением или есть более разумный способ? Я много читал в Stackoverflow, но у меня ничего не получалось. Пожалуйста, помогите!

Ответ №1:

Вы могли бы использовать следующее регулярное выражение для извлечения ссылки Instagram из вашего текста:

 <(. )|(Instagram)>
  

Смотрите здесь

Он выполняет поиск любого текста, заключенного в < и |(Instagram)> , и сохраняет его в группе захвата.


Вы можете использовать его следующим образом

 import re

INSTA_LINK_RE = re.compile(r'<(. )|(Instagram)>')

match = INSTA_LINK_RE.search(json.dumps(data["event"]["attachments"][0]["text"]))

if match:
    url = match[1]  # gets the first capturing group
  

Если вы хотите получить только короткий код, используйте это регулярное выражение

 <https://www.instagram.com/p/(. )/|(Instagram)> 
  

Это работает, если у вас есть str объект для анализа с помощью вашего str регулярного выражения.

Если ваш текст является bytes объектом, вам нужно сначала его декодировать…

 # JSON files are normally encoded with UTF-8
json.dumps(data["event"]["attachments"][0]["text"]).decode('utf8`)
  

… или используйте bytes регулярное выражение

 # note the `b` prefix for the regex pattern
INSTA_LINK_RE = re.compile(br'<(. )|(Instagram)>')
  

Чтобы напрямую получить dict, содержащий str объекты, вы также можете передать кодировку в open функцию:

 f = open('json-test-file-for-insta-url-snippet.json', encoding='utf-8`)
  

Смотрите некоторые документы python, чтобы узнать больше:

Комментарии:

1. спасибо всем, это мне очень помогло! это отлично работает для моего эксперимента nutshell, когда я передаю строку напрямую с помощью data = stringxyz — но когда я пытаюсь получить результат шорткода из моего локального файла json, я получаю ошибку:

2. import re import json f = open('json-test-file-for-insta-url-snippet.json') data = json.load(f) print(json.dumps(data["event"]["attachments"][0]["text"])) print(re.findall("<https://www.instagram.com/p/(. )/|(Instagram)>", data)) Вывод: File "get-text-from-attachements.py", line 47, in <module> print(re.findall("<https://www.instagram.com/p/(. )/|(Instagram)>", data)) File "/usr/lib/python3.8/re.py", line 239, in findall return _compile(pattern, flags).findall(string) TypeError: expected string or bytes-like object что я делаю не так?

3. Поскольку вы читаете текст из файла, вы получаете bytes объект вместо str единицы. Вы должны декодировать байты, чтобы получить правильную строку. Файлы JSON кодируются в UTF8, поэтому вам придется использовать data.decode('uft8') . также смотрите docs.python.org/3.6/library /…

4. хорошо, я попробовал print(re.findall("<https://www.instagram.com/p/(. )/|(Instagram)>", data.decode('utf8'))) и получил: File "get-text-from-attachements.py", line 47, in <module> print(re.findall("<https://www.instagram.com/p/(. )/|(Instagram)>", data.decode('utf8'))) AttributeError: 'dict' object has no attribute 'decode' существует ли специальная задача декодирования для словарей?

5. кодирование касается текстовых данных. ваши data переменные на самом деле являются dict, поскольку они содержат ваш проанализированный JSON. пожалуйста, посмотрите на обновленный ответ и ссылки внизу него

Ответ №2:

Поскольку результат находится в строковом формате. Регулярное выражение — самый умный способ (требует времени для изучения, но это очень мощный инструмент). Однако вы можете использовать модуль под названием instaloader. Не уверен, с чем вы работаете, но instaloader действительно помогает Instagram.

Комментарии:

1. спасибо большое, я проверю это, но мне просто нужен URL (или короткий код) из этой строки JSON. Я попробовал это с регулярным выражением типа ‘print (re.findall(«(?P<url> https?:// [^ s] )», data))’, но я получил ‘TypeError: ожидаемый объект, подобный строке или байтам’ :-/

Ответ №3:

 import json

link = json.dumps(data["event"]["attachments"][0]["text"])
link_list = ','.split(link)
for x in link_list:
    x = x[19:]
    if x.stratswith('https:'):
        i = '|'.split(x)
        link = i[0]
  

Сначала я разделяю данные в списке, затем просматриваю список, пока не найду что-нибудь, начинающееся с https: (ссылка).Затем я разделяю его еще раз в конце ссылки и извлекаю из списка