D3临摹作业_数据采集(西安交大国家艺术基金数据可视化培训第27天)

第十一章  数据可视化之数据采集

第一节 python爬虫基础

一 、爬虫概述

URL由三部分构成:协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志

二、数据获取

1 网络请求request库安装

Requests是用python语言基于urllib库编写、封装的。

方法解释代码
requests.request()构造一个请求,支持以下各种方法 
requests.get()获取html的主要方法
r = requests.head("http://httpbin.org/get")
requests.head()获取html头部信息的主要方法 
requests.post()向html网页提交post请求的方法 
requests.put()向html网页提交put请求的方法
r = requests.put("http://httpbin.org/put")
requests.patch()向html提交局部修改的请求 
requests.delete()向html提交删除请求
r = requests.delete("http://httpbin.org/delete")
requests.options() 
r = requests.options("http://httpbin.org/get")

案例:来源:[简书]

import requests
url='http://www.httpbin.org'
r=requests.get(url).text
print(r)

# 导入requests库
import requests

# 定义base_url作为基础被测URL
base_url = 'http://httpbin.org'

# 发送get请求;打印响应状态码
r = requests.get(base_url+'/get')
print(r.status_code)

# 发送POST请求;打印响应状态码
r = requests.post(base_url+'/post')
print(r.status_code)

# 发送PUT请求;打印响应状态码
r = requests.put(base_url+'/put')
print(r.status_code)

# 发送DELETE请求,打印响应状态码
r = requests.delete(base_url+'/delete')
print(r.status_code)

2 参数传递

Requests库允许使用params关键词传递URL参数,以字符串字典来提供这些参数。如在GET请求中使用查询字符串(Query String)传递参数,在POST请求的请求体(Request Body)中传递参数

参数含义代码
params字典或字节序列, 作为参数增加到url中,使用这个参数可以把一些键值对以?key1=value1&key2=value2的模式增加到url中params= {'key1':' values', 'key2': 'values'} 
r = requests.get('http://www.httpbin.org/get', params=params)
data字典,字节序或文件对象,重点作为向服务器提供或提交资源是提交,作为request的内容,与params不同的是,data提交的数据并不放在url链接里, 而是放在url链接对应位置的地方作为数据来存储。它也可以接受一个字符串对象。 
jsonjson格式的数据, json合适在相关的html,http相关的web开发中非常常见, 也是http最经常使用的数据格式, 他是作为内容部分可以向服务器提交。 
headers字典是http的相关语,对应了向某个url访问时所发起的http的头i字段, 可以用这个字段来定义http的访问的http头,可以用来模拟任何我们想模拟的浏览器来对url发起访问。hd = {'user-agent': 'Chrome/10'} 
r = requests.post('http://www.httpbin.org', headers=hd)
cookies字典或CookieJar,指的是从http中解析cookie 
auth元组,用来支持http认证功能 
files字典, 是用来向服务器传输文件时使用的字段。fs = {'files': open('data.txt', 'rb')} 
r = requests.post('http://python123.io/ws', files=fs)

案例:来源:[简书]

# 导入requests库
import requests

# 定义base_url作为基础被测URL
base_url = 'http://httpbin.org'

# 定义请求所需的参数,参数之间以英文逗号隔开
param_data = {'uname':'Test00001','pwd':'123456'}
# 发送GET请求,格式如:requests.get(url,params)
r = requests.get(base_url+'/get',params=param_data)
print(r.url)    # 输出请求的url
print(r.status_code)    #输出响应的状态码
import requests
base_url = 'http://httpbin.org'

form_data = {'uname':'Test00002','pwd':'123456'}
# 发送POST请求,格式如:requests.post(url,data)
r = requests.post(base_url+'/post',data=form_data)
print(r.text)   # 返回响应内容

案例:传递header参数,模拟浏览器的访问行为,以应对网站的反爬虫策略 

import requests
header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
r = requests.get('https://www.zhihu.com/explore',headers=header)
print(r.text)

3 属性

属性说明
r.status_codehttp请求的返回状态,若为200则表示请求成功。
r.texthttp响应内容的字符串形式,即返回的页面内容
r.encoding从http header 中猜测的相应内容编码方式
r.apparent_encoding从内容中分析出的响应内容编码方式(备选编码方式)
r.contenthttp响应内容的二进制形式

案例:

import requests
r = requests.get(url='https://api.github.com/events')
print(r)
print(r.status_code)
print(r.encoding)
print(r.apparent_encoding)
print(r.json)
print(r.content)

案例:爬取网页通用代码

try:
    r=requests.get(url,timeout=30)#请求超时时间为30秒
    r.raise_for_status()#如果状态不是200,则引发异常
    r.encoding=r.apparent_encoding #配置编码
    return r.text
except:
    return "产生异常"

案例:爬虫网页、图片及文件[源码]

import requests

keyword ='html_image'
try:
    keyword={'f':keyword}
    r = requests.get("http://www.w3school.com.cn/tiy/t.asp",params = keyword)
    print(r.url)
    print(r.text)
except:
    print("error")

 

import requests

keyword ='html_image'
print(keyword)
try:
    keyword={'f':keyword}
    r = requests.get("http://www.w3school.com.cn//i/eg_mouse.jpg")
    print(r.url)
    print(r.content)
    f = open('w3c.jpg', 'wb')
    f.write(r.content)
    f.close()
except:
    print("error")

案例:使用r.encoding解决requests库中文乱码[源码]

import requests
 
response = requests.get('http://www.dytt8.net/index.htm')

# 使用apparent_encoding可以获得真实编码
# response.encoding = response.apparent_encoding 
response.encoding = 'gb2312'
print(response.text[200:300])

案例:使用open函数保存豆瓣短评[源码]

import requests
from lxml import etree
 
#发送Request请求
url = 'https://book.douban.com/subject/1054917/comments/'
head = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36'}
 
#解析HTML
r = requests.get(url, headers=head)
s = etree.HTML(r.text)
comments = s.xpath('//div[@class="comment"]/p/text()')
#print(str(comments))#在写代码的时候可以将读取的内容打印一下
 

#保存数据open函数
with open('E:/alienbrain/Projects/Asm/D3/pinglun.txt','w',encoding='utf-8') as f:#使用with open()新建对象f
    for i in comments:
        print(i)
        f.write(i+'\n')#写入数据,文件保存在上面指定的目录,加\n为了换行更方便阅读

 


第二节 数据解析

BeautifulSoup用于从html/xml中提取数据,实现文档导航、查找、修改。

1 基本API

eautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。

解析返回的4种对象

对象属性代码
Tag有两个重要的属性,name 和 attrsprint soup.name
print soup.a.name
print soup.attrs
print soup.p.attrs #在这里,我们把 p 标签的所有属性打印输出了出来,得到的类型是一个字典。
print soup.p['class'] #单独获取某个属性
print soup.p.get('class') ##单独获取某个属性 跟上面一样的
NavigableString获取标签内部的文字print soup.p.string

print type(soup.p.string)

#<class 'bs4.element.NavigableString'>

BeautifulSoup对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称:

print type(soup.name)

#<type 'unicode'>

print soup.name

# [document]

print soup.attrs

#{} 空字典

Comment其实输出的内容仍然不包括注释符号

#判断代码如下:

if type(soup.a.string)==bs4.element.Comment:

print soup.a.string

 

print soup.a

print soup.a.string

print type(soup.a.string)

搜索文档树

(1)find_all( name , attrs , recursive , text , **kwargs )

find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件,可以根据标签名,属性,内容查找文档。

其他一些类似的用法:
find_parents()返回所有祖先节点,find_parent()返回直接父节点。
find_next_siblings()返回后面所有兄弟节点,find_next_sibling()返回后面第一个兄弟节点。
find_previous_siblings()返回前面所有兄弟节点,find_previous_sibling()返回前面第一个兄弟节点。
find_all_next()返回节点后所有符合条件的节点, find_next()返回第一个符合条件的节点
find_all_previous()返回节点后所有符合条件的节点, find_previous()返回第一个符合条件的节点

(2)CSS选择器

 CSS 时标签名不加任何修饰,类名前加点,id名前加 #,在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list

.表示class #表示id
标签1,标签2 找到所有的标签1和标签2
标签1 标签2 找到标签1内部的所有的标签2
[attr] 可以通过这种方法找到具有某个属性的所有标签
[atrr=value] 例子[target=_blank]表示查找所有target=_blank的标签

案例:[源码]

#导入库 bs4   lxml  requests
from bs4 import BeautifulSoup
import re

#使用官方字符串来演示
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""

#创建 beautifulsoup 对象:
soup = BeautifulSoup(html,'lxml') 

#传正则表达式
for tag in soup.find_all(re.compile("^b")):  
   print(tag.name)
    
#列表
soup.find_all(["a", "b"])
print(tag.name)

#可以匹配任何值,
for tag in soup.find_all(True):
    print(tag.name)
      
#CSS   
#通过标签名查找    
print(soup.select('title'))
print (soup.select('a'))
print (soup.select('#link1'))                
print (soup.select('p #link1'))

案例:[源码]

from bs4 import BeautifulSoup
import requests
try:
    r=requests.get("http://www.w3school.com.cn/tiy/t.asp?f=jseg_text")
    soup = BeautifulSoup(r.text,'html.parser')
    href=soup.find_all('a')
    print(href)
except:
    print("error")

案例:[源码]

import re
str='data=["中国","美国","日本","英国"];city=["广州","北京","上海","深圳"];'
result = re.match(r'data=(.*?);',str)
print(result.group(1))

第三节 数据存储和知识图谱可视化

一 存储数据

1 存储为文本文件

data=["学生成绩花名册",
      "姓名 语文 数学",
      "张三 100 98",
      "李四 99  100",
      "王五 99 99"]
with open('data.txt','w+',encoding='utf-8') as f:
	for d in data:
		f.writelines(d+'\n')

2 对mysql数据库的操作

python3使用pymysql连接mysql服务器。
注:
spyder3中运行import pymysql 报错 
解决:安装pymysql
anacoda的cmd中输入 conda install pymysql

爬虫只对数据库进行增删改查(CRUD)操作,因此需要先创建数据库及表。
案例:[源码]
创建一个数据库spiderDB,初始账号root,密码123456,在MySQL-Front中创建如下表格:


 

import pymysql

data=[['张三', '100', '99','97'],
      ['李四', '97', '98','99'],
      ['王五', '99', '100','100'],
      ['赵六','100','99','98']]

# pymysql.connect(数据库url,用户名,密码,数据库名 )
db = pymysql.connect("localhost", "root", "123456", "spiderdb", charset = 'utf8')
cursor = db.cursor()
try:
    for d in data:
        cursor.execute("INSERT INTO scores2019(name,Chinese,Maths,English) VALUES(%s,%s,%s,%s)", (d[0], d[1], d[2],d[3]))
        print("ok")
        db.commit()
except:
    db.rollback()
db.close()

效果

3 对json操作

案例:写入json字典

#dict写入json
import json

dictObj = {  
    '张三':{  
        'age': 23,  
        'city': '武汉',  
        'skill': 'python'  
    },  
    '李四': {  
        'age': 33,  
        'city': '北京',  
        'skill': 'js'  
    }  
}  
  
jsObj = json.dumps(dictObj)  
  
fileObject = open('写入json.json', 'w+',encoding='utf-8')  
fileObject.write(jsObj)  
fileObject.close()  

4  用pandas库读取和存储数据[原文链接]

   pandas库是python数据处理领域非常重要也是非常强大的一个库。
    使用pandas库读取数据的常用函数:

import pandas as pd
table = pd.read_table('http:\\somelink.csv')  # 读取任一结构型文本数据
csv = pd.read_csv(r'c:\data.csv')  # 读取csv文件
excel = pd.read_excel(r'c:\data.xlsx')  # 读取Excel文件

使用 pd.read_table( ) 函数时,可以通过sep变量自定义数据的分割符,从而方便地对txt文本数据进行结构化读取:

df = pd.read_table(path, sep = '|')  # 用“|”对每行数据拆分

此外,还可以自定义表格的标题行:

user_cols = ["Name", 'Data_A', 'Data_B']
df = pd.read_table(path, sep = '|', head = None, names = user_cols)

还可以自定义读取表格的某些行和列:

# 读取特定的列(按顺序编号)
df = pd.read_excel(filename, sheetname, usecols = [0,1,4,5,6,7,12,13])

# 跳过特定行
df = pd.read_excel(filename, sheetname, skiprows=[0]) # 跳过第一行

对于导入的 df 数据,可以通过向屏幕打印如下参数来对数据的导入结果进行快速检验:

df.head()      # 返回DataFrame的前几行
df.describe()  # 返回DataFrame中数字部分的概要信息
df.shape()     # 返回DataFrame的大小(列数x行数)
df.dtypes()    # 返回DataFrame中各列的数据类型

pandas库的 pd.read_sql_query 函数读取PostSQL数据库中的数据:
注:anaocoda可能需要 pip install psycopg2,或者升级anacoda到新版本,会自动升级psycopg2

import psycopg2      # 用psycopg2库连接数据库
import pandas as pd  # 用pd.read_sql_query在本地创建数据表

# 定义数据库的名称,用户名,密码,链接地址和接口
dbname = 'database'
username = "admin"    
password = "password"
hosturl = "test.redshift.amazonaws.com"
portnum = '5400'

# 连接数据库,返回一个数据库对象
try:
    conn = psycopg2.connect("dbname=%s port=%s user=%s host=%s password=%s" %(dbname, portnum, username, hosturl, password))
except:
    print("Fail in connect the database!")  #如果连接失败,打印该语句到屏幕上

# 定义查询语句query
# 这里需要注意:
# 1. 查询语句和SQLWorkbench中的几乎一模一样,唯一的区别是语句的最后要以英文分号结尾
# 2. 在Python中无法在字符串中直接输入单引号,要在单引号前加上反斜杠 \
query = 'SELECT data, teststep FROM db.database WHERE rownumber < 100;')

# 根据query的语句到conn数据库中查询,并将结果返回给data这个DataFrame
df = pd.read_sql_query(query, conn) # 两个参数:检索语句和连接的数据库对象

pandas库导出数据到Excel的方法如下:[源码]

#导入包import pandas as pd
import numpy as np
import pandas as pd
 
df = pd.DataFrame(np.random.randn(10,4))#创建随机值
 
#print(df.head(2))#查看数据框的头部数据,默认不写为前5行,小于5行时全部显示;也可以自定义查看几行
print(df.tail())##查看数据框的尾部数据,默认不写为倒数5行,小于5行时全部显示;也可以自定义查看倒数几行
 
df.to_csv('E:/Projects/PandasNumpy.csv')#存储到CSV中

#df.to_excel('E:/Projects/PandasNumpy.xlsx')#存储到Excel中(需要提前导入库 pip install openpyxl)

案例:爬取豆瓣书评,并保存为excel[源码]

# -*- coding: utf-8 -*-
"""
Created on Fri Jul 26 00:35:08 2019

@author: Administrator
"""
import requests
from lxml import etree
 
#发送Request请求
url = 'https://book.douban.com/subject/1054917/comments/'
head = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36'}
 
#解析HTML
r = requests.get(url, headers=head)
s = etree.HTML(r.text)
comments = s.xpath('//div[@class="comment"]/p/text()')
#print(str(comments))#在写代码的时候可以将读取的内容打印一下
 
 
#保存数据pandas函数   到CSV 和Excel
import pandas as pd

df = pd.DataFrame(comments)
#print(df.head())#head()默认为前5行
df.to_csv('E:/alienbrain/Projects/Asm/D3/PandasNumpyCSV.csv')
#df.to_excel('E:/alienbrain/Projects/Asm/PandasNumpyEx.xlsx')

如果需要在一个Excel中保存多个sheet,需要先定义一个指向Excel路径的对象,然后向该对象中添加sheet,最后将Excel保存并关闭:

writer = pd.ExcelWriter(filename)  # 定义一个向Excel写入数据的对象
df1.to_excel(writer,'Data1')  # 向该Excel中写入df1到Data1这个sheet
df2.to_excel(writer,'Data2')  # 向该Excel中写入df2到Data2这个sheet
writer.save()  # 保存Excel表格
writer.close()  # 关闭Excel表格

在输出数据的时候,还可以自定义输出时列的先后顺序:

# 写入数据到sheet中,并按output_cols的顺序对列进行排序
output_cols = ['Data_A', 'Data_B', 'Name']
df.to_excel(writer,'Data', columns = output_cols)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值