получить Укажите значение из HTML с помощью Python Beautifulsoup - PullRequest
0 голосов
/ 22 февраля 2019

Я новичок в утилизации, и я делаю какой-то проект утилизации, и я пытаюсь получить значение из HTML ниже:

<div class="buttons_zoom"><div class="full_prod"><a href="javascript:void(0)" onclick="js:getProdID('https://www.XXXXXXX.co.il','{31F93B1D-449F-4AD7-BFB0-97A0A8E068F6}','379104')" title="לחם אחיד פרוס אנג'ל 750 גרם - פרטים נוספים"><img alt="פרטים נוספים" border="0" src="template/images/new_site/icon-view-prod-cartpage.png"/></a></div></div>

Я хочу получить это значение: 379104, который находится в onclick im, используя BeautifulSoupcode:

 for i in page_content.find_all('div', attrs={'class':'prodPrice'}):
            temp = i.parent.parent.contents[0]

temp возвращает список объектов и temp = в HTML-код. Выше кто-то может помочь извлечь этот идентификатор, спасибо !!

Edit ****** Ого, ребята, спасибо заудивительное объяснение !!!!!но у меня есть 2 проблемы: 1. Повторите механизм, который не работает, я установил его на тайм-аут = 1, чтобы заставить его выйти из строя, но как только он не вернется:

requests.exceptions.RetryError: HTTPSConnectionPool(host='www.XXXXX.il', port=443): Max retries exceeded with url: /default.asp?catid=%7B2234C62C-BD68-4641-ABF4-3C225D7E3D81%7D (Caused by ResponseError('too many redirects',)) 

Не могли бы вы помочь мне с кодом механизма повтораниже: 2. проблемы производительности без механизма повторных попыток при установленном тайм-ауте = 6 циклов очистки 8000 элементов, что занимает 15 минут, как я могу улучшить производительность этого кода?Код ниже:

def get_items(self, dict):
        itemdict = {}
        for k, v in dict.items():
            boolean = True
        # here, we fetch the content from the url, using the requests library
            while (boolean):
             try:
                a =requests.Session()
                retries = Retry(total=3, backoff_factor=0.1, status_forcelist=[301,500, 502, 503, 504])
                a.mount(('https://'), HTTPAdapter(max_retries=retries))
                page_response = a.get('https://www.XXXXXXX.il' + v, timeout=1)
             except requests.exceptions.Timeout:
                print  ("Timeout occurred")
                logging.basicConfig(level=logging.DEBUG)
             else:
                 boolean = False

            # we use the html parser to parse the url content and store it in a variable.
            page_content = BeautifulSoup(page_response.content, "html.parser")
            for i in page_content.find_all('div', attrs={'class':'prodPrice'}):
                parent = i.parent.parent.contents[0]
                getparentfunc= parent.find("a", attrs={"href": "javascript:void(0)"})
                itemid = re.search(".*'(\d+)'.*", getparentfunc.attrs['onclick']).groups()[0]
                itemName = re.sub(r'\W+', ' ', i.parent.contents[0].text)
                priceitem = re.sub(r'[\D.]+ ', ' ', i.text)
                itemdict[itemid] = [itemName, priceitem]

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019
from bs4 import BeautifulSoup as bs
import re

txt = """<div class="buttons_zoom"><div class="full_prod"><a href="javascript:void(0)" onclick="js:getProdID('https://www.XXXXXXX.co.il','{31F93B1D-449F-4AD7-BFB0-97A0A8E068F6}','379104')" title="לחם אחיד פרוס אנג'ל 750 גרם - פרטים נוספים"><img alt="פרטים נוספים" border="0" src="template/images/new_site/icon-view-prod-cartpage.png"/></a></div></div>"""

soup = bs(txt,'html.parser')
a = soup.find("a", attrs={"href":"javascript:void(0)"})
r = re.search(".*'(\d+)'.*", data).groups()[0]
print(r) # will print '379104'

Редактировать

Заменено ".*\}.*,.*'(\d+)'\).*" на ".*'(\d+)'.*".Они дают тот же результат, но последний намного чище.


Объяснение: Суп

find (первый) элемент с тегом a, где атрибут "href""имеет" javascript: void (0) "в качестве значения.Подробнее о красивых аргументах ключевого слова супа здесь .

a = soup.find("a", attrs={"href":"javascript:void(0)"})

Это эквивалентно

a = soup.find("a", href="javascript:void(0)")

В более старых версиях Beautiful Soup, у которых нет ярлыка class_, вы можете использовать упомянутый выше трюк attrs.Создайте словарь, значением которого для «class» является строка (или регулярное выражение, или что-то еще), которое вы хотите найти.- см. Прекрасную документацию супа об "attrs"

a указывает на элемент типа <class 'bs4.element.Tag'>.Мы можем получить доступ к атрибутам тега так же, как и для словаря, через свойство a.attrs (подробнее об этом в красивых атрибутах супа ).Это то, что мы делаем в следующем утверждении.

a_tag_attributes = a.attrs # that's the dictionary of attributes in question...

Ключи словаря имеют имена в соответствии с атрибутами тегов.Здесь у нас есть следующие ключи / атрибуты name: 'title', 'href' и 'onclick'.
Мы можем проверить это сами, распечатав их.

print(a_tag_attributes.keys()) # equivalent to print(a.attrs.keys())

Это приведет к выводу

dict_keys(['title', 'href', 'onclick']) # those are the attributes names (the keys to our dictionary)

Отсюда нам нужно получить интересующие нас данные. Ключом к нашим данным является «onclick» (он назван в честь HTMLатрибут, где лежат данные, которые мы ищем).

data = a_tag_attributes["onclick"] # equivalent to data = a.attrs["onclick"] 

data теперь содержит следующую строку.

"js:getProdID('https://www.XXXXXXX.co.il','{31F93B1D-449F-4AD7-BFB0-97A0A8E068F6}','379104')"

Объяснение: Regex

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

Чтобы использовать регулярное выражение в Python, мы должны импортировать Regexмодуль re.Подробнее о модуле 're' здесь, хорошие хорошие вещи .

import re

Regex позволяет нам искать строку, соответствующую шаблону.

Здесь строка - это наши данные, а шаблон - ".*'(\d+)'.*" (которая также является строкой, которую можно определить с помощью двойных кавычек).

Вы можетедумайте о регулярных выражениях как о подстановочных знаках на стероидах.Вы, вероятно, знакомы с подстановочными знаками, такими как *.txt, чтобы найти все текстовые файлы в файловом менеджере.Эквивалент регулярного выражения: ^.*\.txt$.

Лучше всего читать о регулярных выражениях, чтобы лучше понять, что это такое.Вот быстрый старт, хорошо, хорошо, хорошо .

Здесь мы search для строки.Мы описываем строку как не имеющую или бесконечное количество символов.За этими символами следуют несколько цифр (хотя бы одна) и заключенные в одинарные кавычки.Тогда у нас есть еще несколько персонажей.

Скобки используются для извлечения группы (это называется захват в регулярном выражении), мы фиксируем только часть, которая является числом.

Поместив часть регулярного выражения в круглые скобки или скобки, вы можете сгруппировать эту часть регулярного выражения вместе.Это позволяет применять квантификатор ко всей группе или ограничивать изменения в части регулярного выражения.
Для группировки можно использовать только круглые скобки.Квадратные скобки определяют класс символов, а фигурные скобки используются квантификатором с конкретными ограничениями.- Использовать скобки для группировки и захвата

r = re.search(".*'(\d+)'.*", data)

Определение символов:

. * Соответствует любому символу (кроме ограничителей строки), * означаетне может быть ни одного, или бесконечного количества
'соответствует символу'
\ d + соответствует хотя бы одной цифре (равно [0-9]);это та часть, которую мы захватили
(\ d +) Capturing Group;это означает захват части строки, где повторяется цифра, по крайней мере один
() используется для захвата, часть, которая соответствует шаблону в круглых скобках, сохраняется.

Захваченная часть (если есть) может быть позже доступна с помощью вызова r.groups() по результату re.search.
. Возвращает кортеж, содержащий захваченную информацию, или None (r относится к результатам.вызова функции re.search).

В нашем случае первым (и единственным) элементом кортежа являются цифры ...

captured_group = r.groups()[0] # that's the tuple containing our data (we captured...)

Теперь мы можем получить доступ к нашим данным, которые находятся в первом индексе кортежа (мы захватили только одну группу)

 print(captured_group[0]) # this will print out '379104'
0 голосов
/ 22 февраля 2019

Оба решения ниже предполагают регулярную / непротиворечивую структуру для атрибута onclick

Если может быть только одно совпадение, то что-то вроде следующего.

from bs4 import BeautifulSoup as bs

html ='''    
<div class="buttons_zoom"><div class="full_prod"><a href="javascript:void(0)" onclick="js:getProdID('https://www.XXXXXXX.co.il','{31F93B1D-449F-4AD7-BFB0-97A0A8E068F6}','379104')" title="לחם אחיד פרוס אנג'ל 750 גרם - פרטים נוספים"><img alt="פרטים נוספים" border="0" src="template/images/new_site/icon-view-prod-cartpage.png"/></a></div></div>

'''    
soup = bs(html, 'lxml')
element = soup.select_one('[onclick^="js:getProdID"]')
print(element['onclick'].split(',')[2].strip(')'))

Если более одного совпадения

from bs4 import BeautifulSoup as bs

html ='''
<div class="buttons_zoom"><div class="full_prod"><a href="javascript:void(0)" onclick="js:getProdID('https://www.XXXXXXX.co.il','{31F93B1D-449F-4AD7-BFB0-97A0A8E068F6}','379104')" title="לחם אחיד פרוס אנג'ל 750 גרם - פרטים נוספים"><img alt="פרטים נוספים" border="0" src="template/images/new_site/icon-view-prod-cartpage.png"/></a></div></div>
'''
soup = bs(html, 'lxml')
elements = soup.select('[onclick^="js:getProdID"]')
for element in elements:
    print(element['onclick'].split(',')[2].strip(')'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...