Processing data in different formats
# 没有列名,可以手动加上去
pd.read_csv('data2.csv', names=['a', 'b', 'c', 'd', 'message'])
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
# txt文件暴力读取
list(open('data3.txt'))
[' A B C\n',
'aaa -0.264438 -1.026059 -0.619500\n',
'bbb 0.927272 0.302904 -0.032399\n',
'ccc -0.264273 -0.386314 -0.217601\n',
'ddd -0.871858 -0.348382 1.100491\n']
result = pd.read_table('data3.txt', sep='\s+') # '\s+'表示可能有若干个空格或制表
print(result)
A B C
aaa -0.264438 -1.026059 -0.619500
bbb 0.927272 0.302904 -0.032399
ccc -0.264273 -0.386314 -0.217601
ddd -0.871858 -0.348382 1.100491
# 跳过某些行
pd.read_csv('data4.csv', skiprows=[0, 2, 3]) #跳过第0,2,3行
# 把数据写入文本格式
data.to_csv('out.csv')
# 缺省值填充Null
data.to_csv(sys.stdout, na_rep='NULL')
,something,a,b,c,d,message
0,one,1,2,3.0,4,NULL
1,two,5,6,NULL,8,world
2,three,9,10,11.0,12,foo
# 手动读写数据(pandas吃内存)
import csv
f = open('data7.csv')
reader = csv.reader(f)
for line in reader:
print(line)
['a', 'b', 'c']
['1', '2', '3']
['1', '2', '3', '4']
JSON formatted data
obj = \
"""
{"姓名": "张三",
"住处": ["天朝", "挖煤国", "万恶的资本主义日不落帝国"],
"宠物": null,
"兄弟": [{"姓名": "李四", "年龄": 25, "宠物": "汪星人"},
{"姓名": "王五", "年龄": 23, "宠物": "喵星人"}]
}
"""
import json
result = json.loads(obj)
{u'\u4f4f\u5904': [u'\u5929\u671d',
u'\u6316\u7164\u56fd',
u'\u4e07\u6076\u7684\u8d44\u672c\u4e3b\u4e49\u65e5\u4e0d\u843d\u5e1d\u56fd'],
u'\u5144\u5f1f': [{u'\u59d3\u540d': u'\u674e\u56db',
u'\u5ba0\u7269': u'\u6c6a\u661f\u4eba',
u'\u5e74\u9f84': 25},
{u'\u59d3\u540d': u'\u738b\u4e94',
u'\u5ba0\u7269': u'\u55b5\u661f\u4eba',
u'\u5e74\u9f84': 23}],
u'\u59d3\u540d': u'\u5f20\u4e09',
u'\u5ba0\u7269': None}
print json.dumps(result, encoding="UTF-8", ensure_ascii=False)
{"兄弟": [{"年龄": 25, "宠物": "汪星人", "姓名": "李四"}, {"年龄": 23, "宠物": "喵星人", "姓名": "王五"}], "住处": ["天朝", "挖煤国", "万恶的资本主义日不落帝国"], "宠物": null, "姓名": "张三"}
XML sum HTML
from lxml.html import parse
from urllib2 import urlopen
parsed = parse(urlopen('https://ask.julyedu.com/'))
doc = parsed.getroot() # 获得根节点
links = doc.findall('.//a') # 找到所有<a>节点
urls = [lnk.get('href') for lnk in doc.findall('.//a')] # 得到其中'href'属性
# 解析XML
from lxml import objectify
path = 'Performance_MNR.xml'
parsed = objectify.parse(open(path))
root = parsed.getroot()
data = []
skip_fields = ['PARENT_SEQ', 'INDICATOR_SEQ',
'DESIRED_CHANGE', 'DECIMAL_PLACES']
for elt in root.INDICATOR: # 将XML放入pandas处理
el_data = {}
for child in elt.getchildren():
if child.tag in skip_fields:
continue
el_data[child.tag] = child.pyval
data.append(el_data)
perf = DataFrame(data)
Binary format
frame = pd.read_csv('data1.csv')
frame.to_pickle('frame_pickle')
pd.read_pickle('frame_pickle')
pickle:保持原来格式不动,以二进制形式输入
HDF5 format
store = pd.HDFStore('mydata.h5')
store['obj1'] = frame
store['obj1_col'] = frame['a']
Database-related actions
request and reptiles Technical Overview
The following code has been running outdated versions of some illogical
import requests
result = requests.get("http://news.qq.com/")
print(result.status_code) # 200是正常的
result.encoding #查看网页编码格式 GB2312
content = result.content
print(content[:1000]) # 网页前1000个字符
# BeautifulSoup库
import warnings
warnings.filterwarnings("ignore")
from bs4 import BeautifulSoup
soup = BeautifulSoup(content, from_encoding="GB2312") #注意这个地方
samples = soup.find_all("a", "linkto")
print(samples[0])
<a class="linkto" href="http://news.qq.com/a/20170421/002667.htm" target="_blank">\u5929\u821f\u4e00\u53f7\u53ef\u7528\u4e8e\u7a7a\u95f4\u7ad9\u8865\u7ed9 \u6fb3\u4e13\u5bb6\uff1a\u7f8e\u56fd\u90fd\u6ca1\u505a\u5230</a>
# 我们需要的是新闻的标题,因此直接取出sample的文本内容。我们通过sample.string完成这个操作。
print samples[0].string.encode('utf8')
# 如果我们需要把所有的标题都取出来,只需要对刚才的samples做一个解析就可以了。
for sample in samples:
print sample.string
# 取出所有链接
for sample in samples:
print sample.attrs['href']
Passing parameters in URLs
# 有时候我们需要在URL中传递参数,比如在采集百度搜索结果时,我们wd参数(搜索词)和rn参数(搜素结果数量),你可以手工组成URL
payload = {'wd': 'python', 'rn': '10'}
r = requests.get("http://www.baidu.com/s", params=payload)
print(r.url)
Set the timeout
# 通过timeout属性设置超时时间,一旦超过这个时间还没获得响应内容,就会提示错误
requests.get('http://github.com', timeout=0.001)
Add Agent
# 爬虫爬取数据时为避免被封IP,经常会使用代理。requests也有相应的proxies属性
import requests
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
requests.get("http://www.zhidaow.com", proxies=proxies)
# 如果代理需要账户和密码,则需这样
proxies = {
"http": "http://user:[email protected]:3128/",
}
Request header content
r.request.headers
Simulated landing
s = requests.session()
data = {'user':'用户名','passdw':'密码'}
#post 换成登录的地址,
res=s.post('http://www.xxx.net/index.php?action=login',data);
#换成抓取的地址
s.get('http://www.xxx.net/archives/155/');
Reptiles crawl and analysis: chain of home network case
# 导入库
import requests
import time
from bs4 import BeautifulSoup
# 抓取列表页
# 首先了解一下目标网站URL结构
'''
链家网的二手房列表页面共有100个,URL结构为http://bj.lianjia.com/ershoufang/pg9/ 其中
bj表示城市
/ershoufang/是频道名称
pg9是页面码。
'''
'''
我们要抓取的是北京的二手房频道,所以前面的部分不会变,属于固定部分,
后面的页面码需要在1-100间变化,属于可变部分。将URL分为两部分,
前面的固定部分赋值给url,后面的可变部分使用for循环遍历页面
'''
#设置列表页URL的固定部分
url='http://bj.lianjia.com/ershoufang/'
#设置页面页的可变部分
page=('pg')
# 最好在http请求中设置一个头部信息,否则很容易被封ip。头部信息网上有很多现成的,也可以使用httpwatch等工具来查看
#设置请求头部信息
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept':'text/html;q=0.9,*/*;q=0.8',
'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding':'gzip',
'Connection':'close',
'Referer':'http://www.baidu.com/link?url=_andhfsjjjKRgEWkj7i9cFmYYGsisrnm2A-TN3XZDQXxvGsM9k9ZZSnikW2Yds4s&amp;wd=&amp;eqid=c3435a7d00146bd600000003582bfd1f'
}
# 使用for循环生成1-100的数字,转化格式后与前面的URL固定部分拼成要抓取的URL。这里我们设置每两个页面间隔0.5秒。抓取到的页面保存在html中
#循环抓取列表页信息
for i in range(1,101):
if i == 1:
i=str(i)
a=(url+page+i+'/')
r=requests.get(url=a,headers=headers)
html=r.content
else:
i=str(i)
a=(url+page+i+'/')
r=requests.get(url=a,headers=headers)
html2=r.content
html = html + html2
#每次间隔1秒
time.sleep(1)
# 使用BeautifulSoup进行页面解析
#解析抓取的页面内容
lj=BeautifulSoup(html,'html.parser')
# 我们分别对房源的总价,房源信息和关注度三部分进行提取。 把页面div标签中class=totalPrice的部分提取出来,并使用for循环将其中每个房源的总价数据存在tp中。
#提取房源总价
price=lj.find_all('div','totalPrice')
tp=[]
for a in price:
totalPrice=a.span.string
tp.append(totalPrice)
# 房源信息存储在hi中,关注度存储在fi中
#提取房源信息
houseInfo=lj.find_all('div',attrs={'class':'houseInfo'})
hi=[]
for b in houseInfo:
house=b.get_text()
hi.append(house)
#提取房源关注度
followInfo=lj.find_all('div',attrs={'class':'followInfo'})
fi=[]
for c in followInfo:
follow=c.get_text()
fi.append(follow)
# 清洗数据并整理到数据表中
# 将之前爬取到的信息进行汇总,并导入pandas之中生成数据表。便于后面的分析
#导入pandas库
import pandas as pd
# 防止输出带省略号
pd.set_option('display.max_columns',200) #设置显示列数
pd.set_option('display.max_rows',100) #设置显示行数
#创建数据表
house=pd.DataFrame({'totalprice':tp,'houseinfo':hi,'followinfo':fi})
#查看数据表的内容
print(house.head())
totalprice houseinfo \
0 1470 3室3厅 | 144.35平米 | 南 | 精装 | 中楼层(共10层) | 2010年建 ...
1 278 1室1厅 | 51.91平米 | 北 | 简装 | 底层(共10层) | 2007年建 | 板楼
2 345 2室1厅 | 62平米 | 南 北 | 简装 | 低楼层(共6层) | 1985年建 | 板楼
3 635 2室1厅 | 84.77平米 | 南 | 精装 | 低楼层(共21层) | 2002年建 |...
4 410 1室0厅 | 38.54平米 | 西北 | 简装 | 中楼层(共18层) | 2005年建 ...
followinfo
0 281人关注 / 2个月以前发布
1 202人关注 / 2个月以前发布
2 32人关注 / 1个月以前发布
3 121人关注 / 3个月以前发布
4 6人关注 / 1个月以前发布
# 可以看到,很多信息是糊在一块的,不能直接使用,所以咱们再做一些数据提取和清洗的工作。如房源信息,在表中每个房源的户型,面积,朝向等信息都在一个字段中,无法直接使用。需要先进行分列操作。这里的规则比较明显,每个信息间都是以竖线分割的,因此我们只需要以竖线进行分列即可。
#对房源信息进行分列
houseinfo_split = pd.DataFrame((x.split('|') for x in house.houseinfo),index=house.index,columns=['户型','面积','朝向','装修','楼层','时间','结构'])
#查看分列结果
print(houseinfo_split.head())
户型 面积 朝向 装修 楼层 时间 结构
0 3室3厅 144.35平米 南 精装 中楼层(共10层) 2010年建 板楼
1 1室1厅 51.91平米 北 简装 底层(共10层) 2007年建 板楼
2 2室1厅 62平米 南 北 简装 低楼层(共6层) 1985年建 板楼
3 2室1厅 84.77平米 南 精装 低楼层(共21层) 2002年建 板塔结合
4 1室0厅 38.54平米 西北 简装 中楼层(共18层) 2005年建 板塔结合
#将分列结果拼接回原数据表
house=pd.merge(house,houseinfo_split,right_index=True, left_index=True)
# 使用相同的方法对房源关注度字段进行分列和拼接操作。这里的分列规则是斜杠
#对房源关注度进行分列
followinfo_split = pd.DataFrame((x.split('/') for x in house.followinfo),index=house.index,columns=['关注','发布时间'])
#将分列后的关注度信息拼接回原数据表
house=pd.merge(house,followinfo_split,right_index=True, left_index=True)
print(house.head())
followinfo 户型 面积 朝向 装修 楼层 时间 \
0 281人关注 / 2个月以前发布 3室3厅 144.35平米 南 精装 中楼层(共10层) 2010年建
1 202人关注 / 2个月以前发布 1室1厅 51.91平米 北 简装 底层(共10层) 2007年建
2 32人关注 / 1个月以前发布 2室1厅 62平米 南 北 简装 低楼层(共6层) 1985年建
3 121人关注 / 3个月以前发布 2室1厅 84.77平米 南 精装 低楼层(共21层) 2002年建
4 6人关注 / 1个月以前发布 1室0厅 38.54平米 西北 简装 中楼层(共18层) 2005年建
结构 关注 发布时间
0 板楼 281人关注 2个月以前发布
1 板楼 202人关注 2个月以前发布
2 板楼 32人关注 1个月以前发布
3 板塔结合 121人关注 3个月以前发布
4 板塔结合 6人关注 1个月以前发布