urllib库

request模块

get请求

1
2
3
4
5
6
7
8
9
10
11
12
13
from urllib import request,error,parse
url ='http://www.pm25x.com/city/beijing.htm'
#request中的urlopen方法主要用来打开一个链接
html = request.urlopen(url)
#返回一个对象
# rs = html.read()
#可以直接用read方法读取对象内容
#也可以使用decode方法进行解码
rs2 = html.read().decode('utf-8')
# print(rs)
print(rs2)
### urlopen( url,data,proxies ) :用于打开 url
#proxies参数为设置ip代理

post请求

打开url的操作是一次get的访问。那么如果要传post数据如何做到?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
url = "http://www.baidu.com"
#设置数据参数
data = {
'a':'a'
}
#将数据进行编码 a=a
data = parse.urlencode(data).encode("utf-8")
#设置请求头信息
headers = {
"a":"a"
}
# 封装成req对象
req = request.Request(url=url,data=data,headers=headers)
#访问目标网站
rs = request.urlopen(req)
#对返回对象进行解码
html = rs.read().decode('utf-8')
print(html)

urlopen返回一些信息

  • getcode() 返回http状态码
  • info()返回头部信息
  • geturl() 返回当前url
  • read() 返回对象内容

parse模块

可以使用parse对url进行解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from urllib import request,error,parse
#可以解析网址
url ='http://www.pm25x.com/city/beijing.htm'
o = parse.urlparse(url)
#得到解析结果以后
print(o)
print("scheme={}".format(o.scheme)) #协议
print("netloc={}".format(o.netloc)) #域名
print("path={}".format(o.path))#文件路径
print("params={}".format(o.params))#参数
print("query={}".format(o.query))
print("fragment={}".format(o.fragment))
###########################输出如下
ParseResult(scheme='http', netloc='www.pm25x.com', path='/city/beijing.htm', params='', query='', fragment='')
scheme=http
netloc=www.pm25x.com
path=/city/beijing.htm
params=
query=
fragment=

error模块

error模块其实就使用一个异常处理类

1
2
3
4
5
6
7
8
9
10
11
from urllib import request,error,parse
url = "http://www.efgiegfik.com/"
try:
rs = request.urlopen(url)
except error.HTTPError as e:
print("Http error : {}".format(e.reason))
#由于url不存在于是执行urlerror
except error.URLError as e:
print("URL error : {}".format(e.reason))
except Exception as e:
print("Something wrong: {}".format(e))

requests库

request库比较强大,底层使用urllib3实现。

get请求

使用 request.get()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import  requests
url = 'http://www.baidu.com'
data = {'a':'a'}
rs = requests.get(url=url,params=data)
#比urllib的urlioen方便多了
#查看源码可以发现最终调用的是
def request(self, method, url,
params=None, data=None, headers=None, cookies=None, files=None,
auth=None, timeout=None, allow_redirects=True, proxies=None,
hooks=None, stream=None, verify=None, cert=None, json=None):
# 那么post和get的发包方式差别就不大了。
# 调用 rs.url可以查看url。
print(rs.url)
#http://www.baidu.com/?a=a

post请求

1
2
3
4
5
6
7
8
9
10
import  requests

url = 'http://www.baidu.com'
data = {'a':'a'}
#这里是data
#get的是params
rs = requests.post(url=url,data=data)
rs.encoding='utf-8'
print(rs.text)
#同样的可以设置headers cookie等

同样的可以查看一些返回值,例如cookie,状态码,响应头等

1
2
3
4
5
6
7
8
9
10
11
12
13
rs = requests.get(url=url)
# 查看cookie cookie返回时一个对象
print(rs.cookies['BDORZ'])
# 查看返回头
print(rs.headers)
# 查看状态码
print(rs.status_code)
# 查看编码
print(rs.encoding)
#查看url
print(rs.url)
# 查看重定向
print(rs.history)

还有一个session机制

1
2
3
import request
session = requests.session()
#用来保证接下里的程序使用同一个会话

BeautifulSoup库

参考资料

不管是urllib还是request的提供了方便的访问网页的机制,但是对数据提取来说BeautifulSoup是很强大的

1
2
3
4
5
6
7
8
from bs4 import BeautifulSoup
url ='http://www.baidu.com'
#创建一个返回实例
rs = requests.get(url)
#解析为lxml
soup = BeautifulSoup(rs.text,'lxml')
print(soup.prettify())
#格式化输出

对象种类

tag 就是一个html的一个标签

1
2
3
4
5
6
#输出input标签
print(soup.input)
#<input name="bdorz_come" type="hidden" value="1"/>
#输出title标签
print(soup.title)
#<title>百度一下,你就知道</title>

tag标签的属性:

attrs 是一个字典,表示标签里的属性

1
2
3
4
5
print(soup.meta.attrs)
#{'http-equiv': 'content-type', 'content': 'text/html;charset=utf-8'}
#既然是字段就可以使用字典的方式访问值
print(soup.meta.attrs['http-equiv'])
#content-type

name 返回的是标签本身的名字

1
2
print(soup.link.name)
#link

值得注意到是soup对象的name是document的

1
2
print(soup.name)
#[document]

string可以返回标签的内容

1
2
3
4
5
print(soup.a.string)
print(type(soup.a.string))
#<class 'bs4.element.NavigableString'>
#可以看出string是NavigableString的属性
#而text是标签的属性

搜索文档树

可以使用findall或者find。区别在于findall返回该所以标签的一个列表。而find是一条记录

1
2
3
4
5
6
7
8
9
url ='http://www.baidu.com'
rs = requests.get(url)
rs.encoding='utf-8'
soup = BeautifulSoup(rs.text,'html.parser')
a = soup.find_all('a') #那么久可以访问
# print(a)
for i in a:
# print(type(i)) 可以看出它是个tag对象
print(i.attrs['href']) #那么就可以用attrs去访问元素

还可以使用CSS选择器的方式搜索文档

使用CSS选择比用tag标签的方式方便非常多。通常一类数据用一类的CSS选择器修饰。

1
2
3
4
5
6
7
8
9
10
11
#标签选择器
print bs.select('a')
#类名选择器
print bs.select('.css')
#id选择器
print bs.select('#css')
#属性选择器
print bs.select('a[class="css"]')
#遍历
for tag in bs.select('a'):
print tag.get_text()

一个demo: 获取天气预报网上的信息

写了一小段获取天气信息并发送邮箱的小demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from bs4 import BeautifulSoup
import requests
import Email #Email是自己写的邮件发送功能
#目标网址
url = 'http://www.weather.com.cn/weather/101230601.shtml'
rs = requests.get(url)
rs.encoding='utf-8'
# print(rs.text)
soup = BeautifulSoup(rs.text,'html.parser')

#分析网页会发现日期是h1标签之中
h1 = soup.find_all('h1')
# 用css选择器来获取天气状况,由于用标签比css选择器复杂的多所以不选用
where = soup.select('p[class="wea"]')
#选取温度
temp = soup.select('p[class ="tem"]')
T = []
#对取到的温度进行处理
for t in temp:
# print(t.text.replace('\n',''))
T.append(t.text.replace('\n',''))
# 一下是邮件内容的构建并且发送
Text = "{}这时候的温度是{},天气状况是:{};\n".format(h1[0].text,T[0] ,where[0].text)
Text+="{}的时候,天气状况是{},气温是{};\n".format(h1[1].text,where[1].text,T[1])
Text+="{}的时候,天气状况是{},气温是{};\n".format(h1[2].text,where[2].text,T[2])
Text+="{}的时候,天气状况是{},气温是{};\n".format(h1[3].text,where[3].text,T[3])
Text+="{}的时候,天气状况是{},气温是{};\n".format(h1[4].text,where[4].text,T[4])
Text+="{}的时候,天气状况是{},气温是{};\n".format(h1[5].text,where[5].text,T[5])
Text+="{}的时候,天气状况是{},气温是{};\n".format(h1[6].text,where[6].text,T[6])
# print(Text)
From = 'sd@qq.com'
Title = '天气预报'
To = 'zhhhy'
From_addr = 'sd@qq.com'
from_pwd = 'ssdasd'
To_addr = 'ds@qq.com'

try:
msg = Email.build_Text(text=Text, From=From, title=Title, To=To)
Email.send_Email(text=Text, from_addr=From_addr, from_pwd=from_pwd, to_addr=To_addr, msg=msg)
print("邮件发送成功!")
except Exception as e:
print("邮件发送失败:", e)