Beautiful Soup网站抓取:我如何抓取此特定的html结构

时间:2019-11-20 08:31:30

标签: python web-scraping beautifulsoup

我正尝试在具有以下html结构的Webpg上搜寻商店名称及其以下商店地址:

<div class="post_content entry-content" itemprop="articleBody">
<p>...</p>
<p>...</p>
<h2>1. SHOP NAME</h2>
<p>...</p>
<p>...</p>
<p><strong>Address</strong>: Dhoby Ghaut 238889<br />
<strong>Prices: </strong>Starting from SGD3.50 <br />
<strong>Websites</strong>:<a href="https://..." target="_blank" rel="noopener"></a></p>

<h2>2. SHOP NAME</h2>
.
.
<h2>3. SHOP NAME</h2>
.
.
</div>

他们没有为每个商店展示使用类。我在尝试删除地址时遇到问题,有人知道怎么做吗?

这是我获取商店名称的代码:

url= requests.get('https://avenueone.sg/recipes-food/bubble-tea-brands-singapore/').text

shop= []
address= []

soup = BeautifulSoup(url,'lxml')

for row in soup.find_all("h2"): 
    shop.append(row.text)
    for line in row.find_all(string='Address'):
        address.append(line.text)
import re
for i in soup.find('div', class_='post_content entry-content'):
    for x in soup.find_all(re.compile("^Address")):
        address.append(line.text)

我可以将“商店名称”列表检索到一个数据框中,但不能将其对应的地址检索到一个数据框中。 有人可以帮我吗?

3 个答案:

答案 0 :(得分:1)

由于没有类,因此我不会使用BeautifulSoup并回退到正则表达式以在响应中找到地址。如果格式稳定且符合您在问题中所描述的格式,我们可以使用以下正则表达式:

import re


address_pattern = "<strong>Address</strong>:(.+?)<br />"
addresses = re.findall(address_pattern, url)

我们仍然需要将地址与商店名称相关联,但是如何进行取决于您尚未给出的一些假设。如果每个商店正好有一个地址,并且这些商店都存储在变量shops中,那么我们就可以zip(shops, addresses)

如果我们必须考虑某些商店名称下的缺失或多个地址,我们可以将响应分为多个商店条目,然后分别在每个商店名称下查找地址:

addresses = [
    re.findall(address_pattern, chunk) 
    for chunk in url.split("<h2>")[1:]
]

现在,我们有了一个列表列表(可能有多个地址或没有地址),它们位于两个"<h2>"标签之间。现在zip(shops, addresses)将为我们提供一个元组的迭代器,其中第一个元素是商店名称,第二个元素是地址列表(可能为空)。

答案 1 :(得分:1)

您可以使用以下CSS选择器和正则表达式。正则表达式仅用于检查地址是否实际指向网站网址,如果是,则检索该网址。需要bs4 4.7.1 +,因为我使用:contains定位地址强标签/

from bs4 import BeautifulSoup as bs
import requests, re

r = requests.get('https://avenueone.sg/recipes-food/bubble-tea-brands-singapore/')
soup = bs(r.content, 'lxml')
names = [i.text.replace('\xa0',' ') for i in soup.select('.post_content p + h2')]
addresses = [i.next_sibling.replace('\xa0','').replace(':','').strip() if not re.search(r'See this|See their',i.next_sibling) else i.parent.a['href'] for i in soup.select('strong:contains("Address")') ]
results = dict(zip(names,addresses))
print(results)

结果示例:

enter image description here

答案 2 :(得分:0)

要获取地址,您可以执行类似于下面给出的逻辑

>>> for row in soup.find_all('div', {'class':'post_content entry-content'}):
    for el in row.find_all('p'):
        if 'Address' in el.get_text():
            print(el.get_text().split('\n')[0])
            break # remove break in your actual code.


Address: Dhoby Ghaut MRT, 60 Orchard Road, #B2-06, Dhoby Ghaut 238889