【问题标题】:Issue with html tags while scraping data using beautiful soup使用漂亮的汤抓取数据时出现 html 标签问题
【发布时间】:2012-12-16 19:18:47
【问题描述】:

普通代码:

# -*- coding: cp1252 -*-
import csv
import urllib2
import sys
import time
from bs4 import BeautifulSoup
from itertools import islice

page = urllib2.urlopen('http://www.vodafone.de/privat/tarife/red-smartphone-tarife.html').read()
soup = BeautifulSoup(page)
prices = soup.findAll('div', {"class": "price"})

在此之后,我尝试使用以下代码来获取数据: 代码 1:

for price in prices:
    print unicode(price.string).encode('utf8')

Output1:无输出,代码运行没有任何错误并且什么也不打印。

代码 2:

for price in prices:
    textcontent3= u' '.join(price.stripped_strings)
    if textcontent3:
        print textcontent3

Output2:再次没有输出,和Output1一样。

代码 3:

for price in prices:
    fonttag = price.find('div')
    if fonttag is not None:
        print unicode(fonttag.string).encode('utf8').strip()

Output3:无输出,和Output1一样

在此之后,我尝试打印 html 的相关部分:

代码 4:

print prices

输出4:

</span></div>, <div class="price">
<span id="price"><br/>
</span></div>, <div class="price">
<span id="price"><br/>
</span></div>]

从 Output4 中可以看出,html 漂亮的汤正在为我刮花,没有任何价格价值。在网页上,此 html 结构如下所示:

<div class="price"><span id="price">49,90 €</span><br>einmalig</div>

Beautiful soup 没有提取 html 页面中提到的价格值,因此我无法抓取价格数据。 请帮助我解决这个问题并原谅我的无知,因为我是编程新手。

【问题讨论】:

  • 页面使用 JavaScript 将 &lt;span id="price"&gt; 元素替换为页面中嵌入的大量 JavaScript 数据的价格。您需要从那里提取它。
  • 我该怎么做?有什么我可以立即学习或使用的东西吗?我没有 Javascript 和 html 的背景。

标签: python-2.7 html-parsing screen-scraping beautifulsoup html


【解决方案1】:

该页面使用大型 JavaScript 结构来加载价格。您可以只加载该结构:

scripts = soup.find_all('script')
script = next(s.text for s in scripts if s.string and 'window.rates' in s.string)
datastring = script.split('phones=')[1].split(';window.')[0]

这会产生一个较大的 JavaScript 结构,开头为:

{sku844082:{name:"Samsung Galaxy SII",image:"/images/m677391_300468.jpg",deliveryTime:"Vorauss. verf&#252;gbar ab Anfang Januar",sku1444291:{p:"prod954312",e:"19.90"},sku1444286:{p:"prod954312",e:"19.90"},sku1444283:{p:"prod954312",e:"39.90"},sku1444275:{p:"prod954312",e:"59.90"},sku1104261:{p:"prod954312",e:"99.90"}},sku894279:{name:"BlackBerry Torch 9810",image:"/images/m727477_300464.jpg",deliveryTime:"Lieferbar innerhalb 48 Stunden",sku1444275:{p:"prod1004495",e:"179.90"},sku1104261:{p:"prod1004495",e:"259.90"},sku1444291:{p:"prod1004495",e:"29.90"},sku1444286:{p:"prod1004495",e:"29.90"},sku1444283:{p:"prod1004495",e:"49.90"}},sku864221:{name:"BlackBerry Bold 9900",image:"/images/m707491_300465.jpg",deliveryTime:"Lieferbar innerhalb 48 Stunden",sku1444275:{p:"prod974431",e:"129.90"},sku1104261:{p:"prod974431",e:"169.90"},sku1444291:{p:"prod974431",e:"49.90"},sku1444286:{p:"prod974431",e:"49.90"},sku1444283:{p:"prod974431",e:"89.90"}}

不幸的是,json 模块不能直接加载它;尽管是有效的 JavaScript,但在没有引用键的情况下它不是有效的 JSON。您需要使用正则表达式来进一步清理它,或者直接从该字符串中获取 p:"someprice" 信息。

幸运的是,结构可以通过少量的正则表达式来修复:

import re
import json

datastring = re.sub(ur'([{,])([a-z]\w*):', ur'\1"\2":', datastring)
data = json.loads(datastring)

这为您提供了一个大字典,其中包含 SKU 键和带有嵌套字典的字典作为数据,包括带有 p 产品代码和 e 价格的嵌套 SKU:

>>> from pprint import pprint
>>> pprint(data['sku864221'])
{u'deliveryTime': u'Lieferbar innerhalb 48 Stunden',
 u'image': u'/images/m707491_300465.jpg',
 u'name': u'BlackBerry Bold 9900',
 u'sku1104261': {u'e': u'169.90', u'p': u'prod974431'},
 u'sku1444275': {u'e': u'129.90', u'p': u'prod974431'},
 u'sku1444283': {u'e': u'89.90', u'p': u'prod974431'},
 u'sku1444286': {u'e': u'49.90', u'p': u'prod974431'},
 u'sku1444291': {u'e': u'49.90', u'p': u'prod974431'}}

【讨论】:

  • 但是,我如何从这个大字典中获取设备名称及其各自的价格并以 csv 格式输出。我需要为每个具有 5 种不同价格的设备设置 5 行。
  • @atams:SO 不是为您提供切割和干燥的解决方案;我很乐意帮助您解决个别问题,但在某些时候您也必须做一些工作。遍历字典并以特定形式提取一些数据并不难,不是吗?在 python 解释器提示符下进行实验,直到您更好地理解所涉及的结构。
  • 是的,说得对。会这样做。但是现在我被这个问题困住了stackoverflow.com/questions/14135190/…你能通过这个吗?
猜你喜欢
  • 1970-01-01
  • 2012-12-08
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 2021-01-12
  • 1970-01-01
相关资源
最近更新 更多