python爬虫学习笔记(2)
Get与Post请求
get和post就是两种获取信息的方式,它不会显示的表现出来是get还是post请求,这个不同是体现在请求的方法之中的。
get
之前所学习的就全都时get相关的请求,从一个网站中获取某些信息,get想要请求的信息都将显现的展示在url上,就比说百度搜索时,你所搜索的内容就会变成wd=。。。而放在url上面。
post
post请求是要向网址递交你的一些信息,然后获取相应信息。就比如说是在某个网页上进行登录,你就需要post时附上账号及密码信息,并通过加密传输。
而post就目前所学就是向请求体中加入data,请求体原本我们是有url和headers,然后就在这个之上在传一个参数进去——data,就比如说在有道翻译上输入要翻译的信息,那我们就可以通过在data中放入该信息后,通过post获得翻译的结果,
import urllib.request
import urllib.parse
import json
# 接收用户输入,对 data 进行转码(字节流)
key = input("请输入要翻译的内容:")
data = {
"i":key,#在data中放入所要翻译的内容
"from":"AUTO",
"to":"AUTO",
"smartresult":"dict",
"client":"fanyideskweb",
"salt":"1542876206627",
"sign":"6903dad5191ed03cdc87868f0ef748dc",
"doctype":"json",
"version":"2.1",
"keyfrom":"fanyi.web",
"action":"FY_BY_REALTIME",
"typoResult":"false"
}
#先把Form表单数据整理成字典
#然后通过urlencode将其转换成字符串,再encode通过utf-8编码将其转换为字节流
data = urllib.parse.urlencode(data).encode("utf-8")
# 发请求,获响应
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
headers = {"User-Agent":"Mozilla/5.0"}
req = urllib.request.Request(url,data=data,headers=headers)
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
# 有道翻译返回的信息时json格式的,所以html为json格式的字符串
r_dict = json.loads(html)
#loads将json字符串转为python字典格式
#print(type(r_dict))
print(r_dict["translateResult"][0][0]["tgt"])
正则表达式
我们知道再网页的html源码中有大量的代码,如果将其全部提取出来,我们看代码来寻找信息的话非常麻烦的,所以正则表达式就可以解决这个问题,我们可以通过正则表达式与相应格式的字符串进行匹配,从而获取要找的信息。
下面有几个简单的元字符
| 元字符 | 描述 |
|---|---|
| \ | 转义作用 |
| ^ | 匹配行首 |
| $ | 匹配行尾 |
| . | 匹配\n和\r外的任意字符 |
| \w | 匹配包括下划线的任意字母 |
| \s | 匹配任意不可见字符 |
| … | … |
更多相关内容可以参考百度百科.
正则表达式匹配有分为贪婪匹配和非贪婪匹配,而其关键不同就在于 .* 与 .*? 的使用。其中.的意思时任意字符除\n、\r外,*的意思时任意个,那么.*的意思时匹配任意个任意字符除\n、\r外。
同样,在正则表达式中由于有一些字符本身具有特定意义,所以如果要用该字符的原意取进行匹配时,比如要匹配存在.的字符串,就需要用到转义字符,即可使用.去匹配. 。
贪婪匹配
贪婪匹配,顾名思义就是进可能匹配多的字符,对于一个字符串123abc456def456,进行贪婪匹配的话,使用正则表达式123.*456匹配,最后匹配结果就是123abc456def456。
非贪婪匹配
那么非贪婪匹配就是尽可能匹配少的字符,上面例子,字符串123abc456def456,使用正则表达式123.*?456匹配时,匹配结果就是123abc456。可见两者差异主要就是在于 .* 和 .*? 。
最后,有一个在线正则表达式,可以用作练习。
re的简单使用(获取想要的信息)
再python之中我们就可以通过re库使用正则表达式取匹配字符串了。
match
match就是必须从字符串的头开始匹配,只要匹配失败了,就直接返回None。就比如说字符串123abc456def456,使用表达式123.*?456去匹配,
import re
s = "123abc456def456"
result = re.match('123.*?456', s)
#在s中从头寻找与之匹配的字符串
print(result)
#返回结果
print(result.group())
#返回匹配到的字符串
print(result.span())
#返回位置区间
运行结果如下
<_sre.SRE_Match object; span=(0, 8), match=‘123abc456’>
123abc456
(0, 8)
match所返回的时一长串东西,其中第一个时SRE_Match对象,这说明匹成功了,接下来时span,表示的时匹配结果的首尾坐标位置,match表示的是匹配到的内容。
其中我们可以通过结果调用group()和span()函数分别获取match以及span。
search
但是呢,match只能从头匹配,如果想匹配中间的东西,就要用到search函数了,search函数就提供了从字符串任意位置匹配,返回最先匹配到的字符串。就比如说字符串123abc456def456,使用表达式abc(.*?)5(.*?)def去匹配,
import re
s = "123abc456def456"
result = re.search('abc(.\*?)5(.*?)def', s)
print(result)
print(result.group())
print(result.span())
print(result.group(1))
#返回第一个()中匹配到的内容
print(result.group(2))
#返回第二个()中匹配到的内容
运行结果如下
<_sre.SRE_Match object; span=(3, 11), match=‘abc456def’>
abc456def
(0, 8)
4
6
这里在正则表达式中使用了(),起作用就是可以将括号中的特定信息提取,就比如上面例子中有俩括号,进行匹配后一个匹配到了4,一个匹配到了6,在之后就可以通过group(i)来获取第i个括号中的内容信息。
findall
之前两个函数都是找到一个匹配的字符串就返回,但如果要想在内容中把所有可以匹配的字符串全找出来,就需要用findall了。它可以将所有与之匹配的内容形成一个列表返回,列表中每一行都是特定字符,即()中需要匹配到的字符的集合。
import re
s = "“”123abc456def456
123abc657def456
123abc758def456"“”
results = re.findall('abc(.\*?)5(.*?)def', s,re.S)
#返回s中所有与之匹配的字符串,并且匹配包括换行符所有字符
print(results)
for result in results:
print(result)
print(result[0], result[1])
#将列表中的所有结果进行输出
运行结果如下
[(‘4’,‘6’),(‘6’,‘7’),(‘7’,‘8’)]
(‘4’,‘6’)
4 6
(‘6’,‘7’)
6 7
(‘7’,‘8’)
7 8
在以上的例子中,在findall函数中,加了一个re.S参数,这个是一个匹配的修饰符,由于.*?是不能匹配换行符的,而re.S的作用就是使得匹配可以存在换行符,同样还有很多其他的修饰符。
| 修饰符 | 描述 |
|---|---|
| re.I | 使匹配对大小写不敏感 |
| re.L | 做本地化识别(locale-aware)匹配 |
| re.M | 多行匹配,对^和$有影响 |
| re.S | 是匹配包括换行符在内的所有字符 |
| re.U | 根据Unicode字符集解析字符,对\w、\W、\b和\B有影响 |
| re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解 |
需要说明的使修饰符中,re后面跟的字母全为大写字母。
compile
该函数可以将正则字符串编译成正则表达式对象,这样就可以方便在之后对于该表达式的使用了。那么上一个例子的代码就等价于
import re
s = """123abc456def456
123abc657def456
123abc758def456"""
exp = re.compile('abc(.\*?)5(.*?)def',re.S)
#设定正则表达式对象,其中可以包括re.S的设定
results = re.findall(exp, s)
print(results)
for result in results:
print(result)
print(result[0], result[1])
sub
该函数可以将所提取的字符串进行修改。
使用方法十分简单
import re
s = '123abc456def456'
s = re.sub('\d+', '', s)
#其中\d+表示的是1个及以上的数字,而后面的‘’之间没有任何东西。
#该sub函数实际就是将s中的所有数字全部转换成‘’,就是删除
print(content)
运行结果如下:
abcdef
出现问题
post请求中的data参数设定
对于post中data具体是要怎么写的存在疑惑。
未解决
此次学习主要参考于Spider(二) ——爬虫基础
561

被折叠的 条评论
为什么被折叠?



