Python 2.7 使用beautiful soup抓取数据时出现html标记问题

Python 2.7 使用beautiful soup抓取数据时出现html标记问题,python-2.7,html-parsing,screen-scraping,beautifulsoup,html,Python 2.7,Html Parsing,Screen Scraping,Beautifulsoup,Html,通用代码: # -*- 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 = Beauti

通用代码:

# -*- 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>]

,
]
从输出4可以看出,漂亮的汤对我来说毫无价值。在网页上,此html结构如下所示:

<div class="price"><span id="price">49,90 €</span><br>einmalig</div>
49,90€
einmalig
Beauty soup没有提取html页面中提到的价格值,因此我无法获取价格数据。
请帮助我解决这个问题&请原谅我的无知,因为我是编程新手。

该页面使用大型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键和以嵌套DICT为数据的字典,包括带有
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'}}

页面使用大型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键和以嵌套DICT为数据的字典,包括带有
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'}}

该页面使用JavaScript将
元素替换为嵌入页面中的大量JavaScript数据块的价格。你需要从那里提取出来,我怎么做?有什么我可以立即学习或使用的吗?我对Javascript和html都没有任何背景知识。该页面使用Javascript替换
元素,价格来自嵌入页面中的大量Javascript数据块。你需要从那里提取出来,我怎么做?有什么我可以立即学习或使用的吗?我对Javascript和html都并没有背景知识。但,我如何从这本大词典中获取设备名称及其各自的价格,并以csv格式输出它们呢。我需要为每台设备设置5行,每个设备有5种不同的价格。@atams:因此,这不是为您提供简单的解决方案;我很乐意帮助你解决个人问题,但有时你也需要做一些工作。在字典上循环并提取特定形式的数据并没有那么难,是吗?在python解释器提示符上进行实验,直到您更好地理解所涉及的结构。是的,说得对。我会的。但是现在我被这个问题困住了。你能看一下这个吗。但是,我如何从这本大词典中获取设备名称及其各自的价格,并以csv格式输出它们呢。我需要为每台设备设置5行,每个设备有5种不同的价格。@atams:因此,这不是为您提供简单的解决方案;我很乐意帮助你解决个人问题,但有时你也需要做一些工作。在字典上循环并提取特定形式的数据并没有那么难,是吗?在python解释器提示符上进行实验,直到您更好地理解所涉及的结构。是的,说得对。我会的。但是现在我被这个问题难住了,你能帮我解决一下吗。