高效的web抓取Python

高效的web抓取Python,python,html,pandas,web-scraping,beautifulsoup,Python,Html,Pandas,Web Scraping,Beautifulsoup,嗨,我是一个新的网站刮,并想刮一个网站与beautifulsoop。现在我想知道 关于如何编写高效的代码。这是一个关于自行车的网站,他们有几辆自行车,每辆都有价格、状态、距离和持续时间的功能。他们都有相同的等级“产品专长”。将所有这些特性放入数据帧的最有效方法是什么?我特别提出这个问题,因为所有特性都具有相同的类,循环在我看来效率很低 <div class="product-smalltext"> <p class="product-feat&qu

嗨,我是一个新的网站刮,并想刮一个网站与beautifulsoop。现在我想知道 关于如何编写高效的代码。这是一个关于自行车的网站,他们有几辆自行车,每辆都有价格、状态、距离和持续时间的功能。他们都有相同的等级“产品专长”。将所有这些特性放入数据帧的最有效方法是什么?我特别提出这个问题,因为所有特性都具有相同的类,循环在我看来效率很低

<div class="product-smalltext">
<p class="product-feat">
<span>GBP 6'900 <small>(changeable)</small></span><br/> price
                </p>
<p class="product-feat">
<span>new</span><br/> state
                </p>
<p class="product-feat">
<span>10'000 km</span><br/> distance
                </p>
<p class="product-feat">
<span>48 months</span><br/> duration
                  </p>

您可以使用列表理解并直接构造数据帧:

pd.DataFrame([[y.text
    for y in x.select('p.product-feat > span')]
    for x in soup.select('div[class="product-smalltext"]')],
    columns=['price', 'state', 'distance', 'duration'])
pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])
输出(我又添加了一个
,以确保它可以处理每页多个项目):


更新:我们还可以从文本中提取产品功能的名称,并将其用作列名。如果缺少一些值,我们将在数据帧中获得
NaN
s:

pd.DataFrame([[y.text
    for y in x.select('p.product-feat > span')]
    for x in soup.select('div[class="product-smalltext"]')],
    columns=['price', 'state', 'distance', 'duration'])
pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])

使用特定网站更新2:

resp = requests.get('https://www.leasingmarkt.ch/listing')
soup = bs4.BeautifulSoup(resp.text)

df = pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])

df
输出:


                Anzahlung Erstzulassung Jährliche Fahrleistung  \
0       CHF 0 (anpassbar)      Neuwagen  10'000 km (anpassbar)   
1  CHF 13'250 (anpassbar)      Neuwagen  10'000 km (anpassbar)   
2   CHF 2'000 (anpassbar)      Neuwagen              10'000 km   
3  CHF 10'000 (anpassbar)      Neuwagen  15'000 km (anpassbar)   
4   CHF 1'500 (anpassbar)      Neuwagen              10'000 km   
5   CHF 3'500 (anpassbar)      Neuwagen              10'000 km   
6   CHF 6'900 (anpassbar)      Neuwagen              10'000 km   
7  CHF 10'500 (anpassbar)      Neuwagen  10'000 km (anpassbar)   
8       CHF 0 (anpassbar)       08/2015              10'000 km   
9       CHF 0 (anpassbar)      Neuwagen  10'000 km (anpassbar)   

                Laufzeit Kilometerstand                  Leistung  
0  48 Monate (anpassbar)           0 km  204 PS (150 kW), Elektro  
1  48 Monate (anpassbar)           0 km   245 PS (180 kW), Benzin  
2              48 Monate           0 km   190 PS (140 kW), Benzin  
3  48 Monate (anpassbar)           0 km   150 PS (110 kW), Benzin  
4              48 Monate           0 km  204 PS (150 kW), Elektro  
5              48 Monate           0 km   320 PS (235 kW), Benzin  
6              48 Monate           0 km    129 PS (95 kW), Benzin  
7  48 Monate (anpassbar)           0 km   184 PS (135 kW), Benzin  
8              48 Monate      46'000 km   190 PS (140 kW), Diesel  
9  48 Monate (anpassbar)           0 km   320 PS (235 kW), Benzin  

更新3:下面是关于
selenium

url = 'https://www.leasingmarkt.ch/listing'
driver = webdriver.Chrome()
driver.get(url)

html = driver.page_source
soup = bs4.BeautifulSoup(html)

df = pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])

您可以使用列表理解并直接构造数据帧:

pd.DataFrame([[y.text
    for y in x.select('p.product-feat > span')]
    for x in soup.select('div[class="product-smalltext"]')],
    columns=['price', 'state', 'distance', 'duration'])
pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])
输出(我又添加了一个
,以确保它可以处理每页多个项目):


更新:我们还可以从文本中提取产品功能的名称,并将其用作列名。如果缺少一些值,我们将在数据帧中获得
NaN
s:

pd.DataFrame([[y.text
    for y in x.select('p.product-feat > span')]
    for x in soup.select('div[class="product-smalltext"]')],
    columns=['price', 'state', 'distance', 'duration'])
pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])

使用特定网站更新2:

resp = requests.get('https://www.leasingmarkt.ch/listing')
soup = bs4.BeautifulSoup(resp.text)

df = pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])

df
输出:


                Anzahlung Erstzulassung Jährliche Fahrleistung  \
0       CHF 0 (anpassbar)      Neuwagen  10'000 km (anpassbar)   
1  CHF 13'250 (anpassbar)      Neuwagen  10'000 km (anpassbar)   
2   CHF 2'000 (anpassbar)      Neuwagen              10'000 km   
3  CHF 10'000 (anpassbar)      Neuwagen  15'000 km (anpassbar)   
4   CHF 1'500 (anpassbar)      Neuwagen              10'000 km   
5   CHF 3'500 (anpassbar)      Neuwagen              10'000 km   
6   CHF 6'900 (anpassbar)      Neuwagen              10'000 km   
7  CHF 10'500 (anpassbar)      Neuwagen  10'000 km (anpassbar)   
8       CHF 0 (anpassbar)       08/2015              10'000 km   
9       CHF 0 (anpassbar)      Neuwagen  10'000 km (anpassbar)   

                Laufzeit Kilometerstand                  Leistung  
0  48 Monate (anpassbar)           0 km  204 PS (150 kW), Elektro  
1  48 Monate (anpassbar)           0 km   245 PS (180 kW), Benzin  
2              48 Monate           0 km   190 PS (140 kW), Benzin  
3  48 Monate (anpassbar)           0 km   150 PS (110 kW), Benzin  
4              48 Monate           0 km  204 PS (150 kW), Elektro  
5              48 Monate           0 km   320 PS (235 kW), Benzin  
6              48 Monate           0 km    129 PS (95 kW), Benzin  
7  48 Monate (anpassbar)           0 km   184 PS (135 kW), Benzin  
8              48 Monate      46'000 km   190 PS (140 kW), Diesel  
9  48 Monate (anpassbar)           0 km   320 PS (235 kW), Benzin  

更新3:下面是关于
selenium

url = 'https://www.leasingmarkt.ch/listing'
driver = webdriver.Chrome()
driver.get(url)

html = driver.page_source
soup = bs4.BeautifulSoup(html)

df = pd.DataFrame([{y.find('br').next_sibling.strip(): y.find('span').text
    for y in x.select('p.product-feat')}
    for x in soup.select('div[class="product-smalltext"]')])

谢谢。我刚刚意识到,如果某些行的状态为空,您会怎么做?如何在数据帧中使其成为nan,以及如何避免所有值向左移动?@corianne1234请查看更新。这很好,谢谢。剩下的唯一一件事是,这不起作用,因为还有类“product smalltext listing”,所以soup.select('div.product-smalltext')])将同时提供product smalltext listing和product smalltext,并且只有product smalltext具有product feat。这在循环解决方案中起作用,但在这里您将如何执行?很酷,因此您希望将其指定为只有“product smalltext”类。您可以使用
…为汤中的x执行此操作。选择('div[class=“product smalltext”]”)]…
,请查看更新的带有
selenium的更新3(对我来说效果很好,与更新2中的输出相同),非常感谢。我刚刚意识到,如果某些行的状态为空,您会怎么做?如何在数据帧中使其成为nan,以及如何避免所有值向左移动?@corianne1234请查看更新。这很好,谢谢。剩下的唯一一件事是,这不起作用,因为还有类“product smalltext listing”,所以soup.select('div.product-smalltext')])将同时提供product smalltext listing和product smalltext,并且只有product smalltext具有product feat。这在循环解决方案中起作用,但在这里您将如何执行?很酷,因此您希望将其指定为只有“product smalltext”类。您可以使用
…为汤中的x执行此操作。选择('div[class=“product smalltext”]”)]…
,请查看更新的带有
selenium的更新3(对我来说效果很好,与更新2中的输出相同)