requests库的相关用法
GET与POST
经典用法:
import requests
r = requests.get('https://www.baidu.com')
如果我们想要添加相应的参数,我们可以使用params这个参数。
import requests
data = {'name':'linhong','age':'20'}
r = requests.get('http://httpbin.org/get',params = data)
添加headers
import requests
headrs = {'User-Agent':'Mozilla/5.0'}
r = requests.get('https://www.zhihu.com/explore',headers=headers)
POST请求的实现和GET请求的实现十分类似
import requests
data = {'name':'sushuo','age':'21'}
r = requests.post('http://httpbin.org/post',data=data)
响应
常用的有以下几种相应类型
import requests
r = requests.get('http://www.baidu.com')
print(type(r.status_code),r.status_code)
print(type(r.headers),r.headers)
print(type(r.cookies),r.cookies)
print(type(r.url),r.url)
print(r.content)
print(r.text)
会话维持
假如我们第一个请求利用post()方法登录了网站,再想要用get()方法请求个人信息页面。实际上,这相当于打开了两个浏览器,是两个完全不相干的会话,所以是完全帮你获取个人信息的。这时我们就需要会话维持了。利用session我们可以轻易的做到这点而不用去进行繁琐的cookies操作。
import requests
s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456')
s.get('http://httpbin.org/cookies')
此时,进行的两个get请求是在同一个会话中进行的。
代理设置
如果我们需要设置代理,我们可以使用proxies参数。
import requests
proxies = {'http':'http://10.10.1.10:3128','https':'http://10.10.1.10:1080'}
requests.get('https://www.taobao.com',proxies=proxies)
超时设置
实际上,当我们直接写get请求时,如果服务器响应时间很久,此时对我们的爬虫影响很大,但它却永远也不会返回超时错误。
如果我们要求对服务器的响应时间进行一个限制,我们就需要用到一个参数timeout。
import requests
r = requests.get('https://www.baidu.com',timeout=1)
如果在1秒内程序没有相应,那么它会抛出一个异常。
实际上,请求分为两个阶段,连接和读取。上面设置的timeout是二者的时间总和,如果我们想要进行分别指定,可以采用以下方法
import requests
r = requests.get('https://www.baidu.com',timeout=(5,30))
如果想要永久等待,我们可以讲timeout设置为None,这也就和不加参数是一样的情况了。
身份验证
当我们遇到验证界面时,我们可以使用requests的验证功能。
import requests
r = requests.get('http://127.0.0.1:5000',auth=HTTPBasicAuth('linhong','1336659194'))
requests还提供了一个更简单的写法,可以直接传一个元组,它会默认使用HTTPBasicAuth这个类进行验证。
import requests
r = requests.get('http://127.0.0.1:5000',auth=('linhong','1336659194'))
re库与正则表达式
常用匹配规则
模式 | 描述 |
---|---|
\w | 匹配字母,数字及下划线 |
\W | 匹配不是字母,数字及下划线的字符 |
\s | 匹配任意空白字符(\t\n\r\f) |
\S | 匹配任意非空白字符 |
\d | 匹配任意数字 |
\D | 匹配任意非数字的字符 |
^ | 匹配一行字符串的开头 |
$ | 匹配一行字符串的结尾 |
. | 匹配任意字符 |
[…] | 用来匹配一组字符,如[abc]就是匹配a或b或c |
[^…] | 匹配不在[]中的字符,如[^abc]就是匹配非a,b,c的字符 |
* | 匹配0个或多个表达式 |
+ | 匹配1个或多个表达式 |
? | 匹配0个或1个表达式 |
{n} | 匹配n个前面的表达式 |
{n,m} | 匹配n到m次前面的表达式 |
match()
import re
STR = 'su_shuo shi sha_bi'
result = re.match('su\w{4}',STR)
print(result)
print(result.group())
print(result.span())
运行结果如下:
<re.Match object; span=(0, 6), match='su_shu'>
su_shu
(0, 6)
可以看出,在match()方法中,第一个参数传入正则表达式,第二个参数传入要匹配的字符串。它会返回一个SRE_Match对象。该对象有两个方法,group()方法可以输出匹配到的内容,span()方法可以输出匹配的范围了。
多层匹配
import re
STR = 'su_shuo shi sha_bi'
result = re.match('su(\w{4})',STR)
print(result.group())
print(result.group(1))
我们可以在一个正则匹配式中用()包围其中一些语句从而形成多个分区,然后可以用group(1),group(2)……输出这些分区结果。
通用匹配
我们常用.*来匹配一切字符。需要注意的有以下两点。
在字符串中间我们尽量使用非贪婪匹配,也就是用.*?来代替.*,避免匹配缺失的情况。
如果匹配的结果在字符串结尾,.*?就有可能匹配不到任何内容了。
修饰符
.只是匹配除了换行符的其他所有字符,当遇到换行符的时候它就不会匹配了,有时候我们需要让它匹配所有字符。这个时候我们就需要用到换行符。
result = re.match('.*?',re.S)
此时.便可以匹配所有字符了。常用的修饰符还有re.I,它可以使匹配对大小写不敏感。
search()
match()方法是从字符串开头开始匹配的,一旦开头不匹配,匹配就失败了。 所以我们一般使用search()方法进行匹配,search()方法的使用和match()类似,不再赘述。
findall()
前面所讲的match()还是search()都只能匹配正则表达式的第一个内容。如果我们想要获取匹配正则表达式的所有内容,我们就要借助findall()方法了。 它会将所有符合条件的字符串结果以一个数组的形式返回出来。
sub()
我们还可以用正则表达式来修改文本。这时我们就需要借助sub()方法了。
STR = 'ku_zhi_wen_ 666 kkkkk'
STR = re.sub('\d+','',content)
这里第一个参数传入需要匹配的正则表达式,第二个传入需要替换成的字符,第三个参数传入原字符。
compile()
compile()方法可以将正则表达式编译成正则表达式对象,在后面的过程可以直接引用。
pattern = re.compile('\d')
result = re.sub(pattern,'',html)
爬虫小练习(抓取猫眼电影排行)
这次的练习就不说出详细的过程了,直接上代码吧。
import json
import requests
from requests.exceptions import RequestException
import re
import time
# 通用抓取网页
def get_one_page(url):
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_one_page(html):
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
+ '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
+ '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
for item in items:
yield {
'index': item[0],
'image': item[1],
'title': item[2],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5] + item[6]
}
def write_to_file(content):
with open('result.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
def main(offset):
url = 'http://maoyan.com/board/4?offset=' + str(offset)
html = get_one_page(url)
for item in parse_one_page(html):
print(item)
write_to_file(item)
if __name__ == '__main__':
for i in range(10):
main(offset=i * 10)
time.sleep(1)
觉得主要写这个爬虫关键就是写好正则,正则写好了其他都不是问题。。。。