read_html():获取网页表格数据
-
当数据量不多时: 快速抓取法
-
当数据量较多时: 完整爬虫抓取法
JSON数据
JSON(JavaScript Object Notation的简称)已经成为通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。它是一种比表格型文本格式(如CSV)灵活得多的数据格式。
注意:全都要用英文输入模式下的双引号 “
obj="""
{"name":"Wes",
"places_lived":["USA","Spain","China"],
"pet":null,
"siblings":[{"name":"Scott","age":25,"pet":"Zuko"},
{"name":"Katie","age":33,"pet":"Cisco"}]
}
"""
除了空值null和一些其他的细微差别(如列表末尾不允许存在多余的逗号)之外,JSON非常接近于有效的Python代码。 基本类型有对象(字典)、数组(列表)、字符串、数值、布尔值以及null。对象中所有的键都必须是字符串。许多Python库都可以读写JSON数据。我将使用json
,因为它是构建于Python标准库中的。通过json.loads
即可将JSON字符串转换成Python形式:
import json
result=json.loads(obj)
result
# {'name': 'Wes',
# 'places_lived': ['USA', 'Spain', 'China'],
# 'pet': None,
# 'siblings': [{'name': 'Scott', 'age': 25, 'pet': 'Zuko'},
# {'name': 'Katie', 'age': 33, 'pet': 'Cisco'}]}
相反,json.dumps
则将Python对象转换成JSON格式:
asjson=json.dumps(result)
asjson
# '{"name": "Wes",
# "places_lived": ["USA", "Spain", "China"],
# "pet": null,
# "siblings": [{"name": "Scott", "age": 25, "pet": "Zuko"},
# {"name": "Katie", "age": 33, "pet": "Cisco"}]}'
如何将(一个或一组)JSON对象转换为DataFrame或其他便于分析的数据结构就由你决定了。最简单的方式:向DataFrame构造器传入一组JSON对象,并选取数据字段的子集。
import pandas as pd
import json
result=json.loads(obj)
siblings=pd.DataFrame(result['siblings'],columns=['name','age'])
siblings
name | age | |
0 | Scott | 25 |
1 | Katie | 33 |
XML和HTML:Web信息收集
Python有许多可以读写XML和HTML格式数据的库。lxml(http://lxml.de)就是其中之一,它能高效且可靠地解析大文件,lxml有多个编程接口。首先,我们要用lxml.html
处理html
,然后再用lxml.objectify
做一些XML处理。
首先,找到希望获取数据的URL,利用urllib2
将其打开,然后用lxml
解析得到的数据流:
from lxml.html import parse
from urllib import request
parsed=parse(request.urlopen('http://www.baidu.com'))
# <lxml.etree._ElementTree at 0xf74dd28>
doc=parsed.getroot() # <Element html at 0xf7be960>
links=doc.findall('.//a')
links[15:20]
# [<Element a at 0xf7bed80>,
# <Element a at 0xf7bedb0>,
# <Element a at 0xf7bede0>,
# <Element a at 0xf7bee10>,
# <Element a at 0xf7bee40>]
lnk=links[28] # <Element html at 0xf7be960>
lnk.get('href')
lnk.text_content() # '\ue619换一换'
编写下面这条列表推导式(list comprehension)即可获取文档中的全部URL:
urls=[lnk.get('href') for lnk in doc.findall('.//a')]
urls[-10:]
# ['https://beian.miit.gov.cn',
# 'https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news',
# 'http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&ie=utf-8',
# 'http://image.baidu.com/i?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8',
# 'http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&fr=wwwt',
# 'http://wenku.baidu.com/search?lm=0&od=0&ie=utf-8',
# 'http://tieba.baidu.com/f?fr=wwwt',
# 'https://map.baidu.com/?newmap=1&ie=utf-8&s=s',
# 'https://b2b.baidu.com/s?fr=wwwt',
# 'http://www.baidu.com/more/']
从文档中找出正确表格的方法:反复试验。
# 只是示例,baidu的网站没有table
tables=doc.findall('.//table')
calls,puts=tables[9],tables[3]
# 表格的标题行th,数据行td
rows=calls.findall('.//tr')
def _unpack(row,kind='td'):
elts=row.findall('.//%s'%kind)
return [val.text_content() for val in elts]
_unpack(rows[0],kind='th') #['strike','symbol','last']
_unpack(rows[1],kind='td') #['295.00','AAPL12082313','310.40']
现在整合所有步骤,将数据转化成一个DataFrame。由于数值型数据仍是字符串格式,我们希望将部分列(可能不是全部)转换为浮点数格式。 pandas恰好有一个TextParser
类可以用于自动类型转换(read_csv和其他解析函数其实在内部都用到了它)。
from pandas.io.parsers import TextParser
def parse_options_data(table):
rows=table.findall('.//tr')
header=_unpack(rows[0],kind='th')
data=[_unpack(r) for r in rows[1:]]
return TextParser(data,names=header).get_chunk()
call_data=parse_options_data(calls)
put_data=parse_options_data(puts)
call_data[:8]
使用HTML和Web API
许多网站都有一些通过json或其他格式提供的数据公共API,一个简单易用的方法是用request
包。
import request