Python爬虫日记2——使用requests

1基本用法

import requests

url = 'https://www.baidu.com/'
r = requests.get(url)
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.text)
print(r.cookies)
"""
调用get()方法,输出response的类型、状态码、响应体的类型、响应内容以及cookies
r.text # 返回响应内容
"""

r.text,网页返回内容是str类型,如要直接解析返回结果,得到一个字典格式的话,可直接调用json()方法。r.json()

1.1添加参数

---snip---
data = {
    'name': 'germey',
    'age': 22
}
r = requests.get(url, params=data)	# 利用params参数

1.2抓取网页

import requests
import re

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Inter Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
r = requests.get("https://www.zhihu.com/explore", headers=headers)
pattern = re.compile('explore-feed.*?question_link.*?>(.*?)</a>', re.S)
title = re.findall(pattern, r.text)
print(title)
"""
输出结果就一个[],问题还未解决
"""

1.3抓取二进制数据,抓取图片

图片、音频、视频这些文件本质上都是由二进制码组成,想要抓取他们,就要拿到他们的二进制码。

import requests

r = requests.get("https://g.alicdn.com/tb/login/0.4.7/weibo/css/images/ico-taobao.png")
# print(r.text)
# print(r.content)
with open('taobao.png', 'wb') as f:
    f.write(r.content)

GET 请求页面,并返回页面内容
POST 大多用于提交表单或上传文件,数据包含在请求体中

1.4PSOT请求,并写入文件

import requests

data = {'name': 'germey', 'age': '22'}
r = requests.post('http://httpbin.org/post', data=data)
print(type(r.text))
print(type(r.content))
with open('filename.txt', 'w') as f:
    f.write(r.text)
with open('filename2.txt', 'wb') as f:
    f.write(r.content)

"""
<class 'str'>
<class 'bytes'>
r.text 返回响应类型为str,r.content返回响应类型为bytes
with open('filename.txt', 'wb') as f:		# 用open()方法,他的第一个参数是文件名称,第二个参数代表以二进制写的形式打开,可以向文件里写入二进制数据。
"""

1.5requests内置的状态码查询对象requests.codes

import requests

r = requests.get('https://www.jianshu.com')
exit() if not r.status_code == requests.codes.ok else print('Request Successfully')

2高级用法

2.1上传文件

import requests

files = {'file': open('favicon.ico', 'rb')}     # 这是一个字典,file为键,:后面为值
r = requests.post('http://httpbin.org/post', files=files)   # requests模拟提交数据
print(r.text)

(读取文件)下面的程序打开并读取文件,再将其内容显示到屏幕上:

with open('wenjian.txt') as file: 
 contents = file.read() 
 print(contents)

2.2Cookies

用requests可以轻松处理cookies,这里以news.baidu.com为例

import requests

r = requests.get('http://news.baidu.com')
print(r.cookies)	# 调用cookies属性,便可得到Cookies。运行发现它是一个RequestsCookieJar类型
for key, value in r.cookies.items():	# items()方法将其转换为元组组成的列表,遍历每一个Cookies的名称和值,实现Cookies的遍历解析。
    print(key + '=' + value)

2.3 用Cookies来维持登录状态

这里测试失败,后期补充

2.3.1 会话维持

Session() 对象,维持一个会话

import requests

requests.get('http://httpbin.org/cookies/set/number/123456789')
r = requests.get('http://httpbin.org/cookies')
print(r.text)

s = requests.Session()      # 创建一个实例
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text)

2.4 SSL证书验证

通常verify参数默认设置为True,如果证书验证错误导致访问失败,可以把vertify设置为False。但是会产生警告
r = requests.get(url, vertify=False)

设置忽视警告
import urllib3
urllib3.disable_warnings()
或者捕获警告到日志
import logging
logging.captureWarnings(True)

2.5 代理设置

import requests

url = 'http://...'
proxies = {
    "http": "http://user:password@host:port"
}
r = requests.get(url, proxies=proxies)

2.6 超时设置

timeout()

import requests

r = requests.get('https://www.baidu.com', timeout=1)
print(r.status_code)
"""
timeout=1	# 这个设置将用作连接和读取的timeout总和
timeout=(5,1)	# 设置一个元组,分别指示连接和读取的时间
如果想要永久等待,可以将timeout的值设置为None,或者不设置直接留空,默认是None
"""

2.7 身份认证

访问网站时,有时会遇到身份认证页面,此时可以使用requests自带的身份认证功能:

import requests
from requests.auth import HTTPBasicAuth

r = requests.get('http://localhost:5000', auth=HTTPBasicAuth('username', 'password'))
print(r.status_code)
"""
如果密码和用户名正确,会返回200;如果认证失败,返回401。
"""
"""
出错未解决:[WinError 10061] 由于目标计算机积极拒绝,无法连接。
"""

3 正则表达式,re库,match()方法

开源中国提供的正则表达式测试工具https://tool.oschina.net/regex/
Python的re库提供了整个正则表达式的实现。

3.1 实例

一个常用的匹配方法一match (),向它传人要匹配的字符串以及正表达式即可检测。
在 match ()方法中,第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串

import re

content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}', content)		#  match ()方法,第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串
print(result)
print(result.group())	# 方法group()可以输出匹配到的内容
print(result.span())	# 方法span()可以输出匹配的范围

3.2 match(),通用匹配.*

match()方法会尝试从字符串的起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配,就返回None

匹配目标:使用()括号将想要的子字符串括起来

import re

content = 'Hello 1234567 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello\s(\d+)\s(\w{5})', content)      # 使用()括号将想要提取的子字符串括起来,()标记了一个子表达式的开始和结束位置
print(result)
print(result.group())
print(result.group(1))      # 调用group(1)来获得匹配结果
print(result.group(2))
print(result.span())
"""
40
<re.Match object; span=(0, 19), match='Hello 1234567 World'>
Hello 1234567 World
1234567
World
(0, 19)
"""

3.2.1 非贪婪匹配 .*?

贪婪匹配是尽可能匹配多的字符,非贪婪匹配是尽可能匹配少的字符
字符串中间尽量使用非贪婪匹配,即用.*?来代替.*,以,避免匹配缺少
字符串结尾尽量使用.*,以避免匹配不到结果

3.2.2 修饰符 re.S, re.I

. 匹配的是除换行符之外的任意字符,当遇到换行符时,.*? 就不能匹配了,所以导致匹配失败,这里只需加一个修饰符 re.S ,即可修正。

import re

content = '''Hello 1234567 World_This
is a Regex Demo
'''
print(len(content))
result = re.match('^He.*?(\d+).*?Demo$', content, re.S)      # 使用()括号将想要提取的子字符串括起来,()标记了一个子表达式的开始和结束位置
print(result)
print(result.group(1))
print(result.span())
# .*通用匹配
# .*?非贪婪匹配
# re.S 使.匹配包括换行符在内的所有字符

3.2.3 转义匹配

当遇到用于正则匹配模式的特殊字符时,在前面加反斜线转义一下即可。

3.3 searach()

方法search (),它在匹配时会扫描整个字符串,然后返回第一个成功匹配的结 。即正则表达式可以是字符串的一部分,在匹配时,search ()方法会依次扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容,如果搜索完了还没有找到,就返回 None。
**search()**方法只返回匹配正则表达式的第一个内容

import re

content = 'Extra stings Hello 1234567 World_This is a Regex Demo'

print(len(content))
result = re.search('Hello.*?(\d+).*?Demo', content)      # 使用()括号将想要提取的子字符串括起来,()标记了一个子表达式的开始和结束位置
# 方法search()
# .*通用匹配
# .*?非贪婪匹配
# 使用search(),不需要再加^和$
print(result)
print(result.group())   # 方法group()可以输出匹配到的内容
print(result.group(1))  # 方法span()可以输出匹配的范围
print(result.span())

3.4 findall()

search()方法可以返回匹配正则表达式的第一个内容,findall()可以获取匹配正则表达式的所有内容。

findall()方法,如果有返回结果,则结果是列表类型,可以遍历列表获取每组内容。

3.5 sub()

修改文本

import re

content = '54gfgfdsg56dsag'
content = re.sub('\d+', '', content)	# 第一个参数\d+来匹配所有的数字,第二个参数为替换成的字符串(去掉参数的话,赋值为空),第三个参数是原字符串
print(content)

3.6 compile()

compile()将正则表达式编译成一个正则表达式对象,以便复用

爬取猫眼电影名称

import requests
import re


def get_one_page(url):
    headers = {
        'User_Agent': 'Mozilla/5.0 (Macintosh; Inter Mac OS X 10_11_4) 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:
        response.encoding = 'utf8'      # 如果不加这条语句,输出爬取的信息为乱码!
        # 爬取下来的编码是ISO-8859-1格式,需要转化为utf-8格式,加一句response.encoding = “utf8”
        return response.text
    return None


def parse_one_page(html):
    pattern = re.compile('<head>.*?>(.*?)<', re.S)
    items = re.findall(pattern, html)
    print(items)
    with open('filename.txt', 'w') as f:
        f.write(str(items))


def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    print(html)
    parse_one_page(html)

main()

# 在network的response中查看原始请求得到的源码
"""
1、一部电影信息对应的源代码是一个dd节点,排名信息在class为borad-index的i节点内,利用非贪婪模式来提取i节点内的信息,正则表达式:<dd>.*?board-index.*?>(.*?)</i>
2、提取电影的图片,在a节点后,其内部有两个img节点,第二个img节点的data-src属性是图片的链接,提取这个属性,正则表达式:<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)"
3、提取电影的名称,在p节点后,class为name,正则表达式:<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>
4、提取其他内容方法类似
"""

爬取小说《灵武封神》第一章

小点:findall()和search()的区别

import requests
import re


def get_one_page(url):
    headers = {
        'User_Agent': 'Mozilla/5.0 (Macintosh; Inter Mac OS X 10_11_4) 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:
        response.encoding = 'utf8'      # 如果不加这条语句,输出爬取的信息为乱码!
        # 爬取下来的编码是ISO-8859-1格式,需要转化为utf-8格式,加一句response.encoding = “utf8”
        return response.text
    return None


def parse_one_page(html):
    pattern = re.compile('<title>(.*?)</title>', re.S)
    items = re.findall(pattern, html)       # findall()匹配的是正则表达式()里的内容,如果有返回结果的话,就是列表类型。有(),则只返回()里的内容;没有(),则返回正则表达式的内容。
    # items = re.search(pattern, html)      # search()匹配的是正则表达式的内容
    print(items)
    with open('filename.txt', 'w') as f:
        f.write(str(items))


def main():
    url = 'http://book.zongheng.com/chapter/891033/58356325.html'
    html = get_one_page(url)
    print(html)
    parse_one_page(html)


if __name__ == '__main__':
    # __name__是内置变量,可用于表示当前模块的名字
    # if __name__=='__main__'下的代码只能被自己直接执行,不能被其他程序import调用执行;
    main()


# 在network的response中查看原始请求得到的源码

参考书籍《Python 3网络开发爬虫实战》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值