requests模块
常用方法
-
requests.get()
【1】作用
向目标url发起请求,并获取响应对象【2】参数
2.1> url :需要抓取的URL地址
2.2> headers : 请求头
2.3> timeout : 超时时间,超过时间会抛出异常,例如:timeout=3#打开浏览器,输入京东地址(https://www.baidu.com/),得到响应内容 import requests res = requests.get('https://www.jd.com/') html = res.text print(html)
-
响应对象(res)属性
【1】text :字符串
【2】content :字节流
【3】status_code :HTTP响应码
【4】url :实际数据的URL地址
请求头 User-Agent
# 请求头(headers)中的 User-Agent
# 向测试网站http://httpbin.org/get发请求,查看请求头(User-Agent)
import requests
url = 'http://httpbin.org/get'
res = requests.get(url=url)
html = res.text
print(html)
-
问题解决
#养成好习惯,发送请求携带请求头,重构User-Agent import requests url = 'http://httpbin.org/get' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'} html = requests.get(url=url,headers=headers).text print(html)
爬虫编码模块
- urllib.parse模块
1、标准库模块:urllib.parse
2、导入方式:
import urllib.parse
from urllib import parse
作用:
给URL地址中查询参数进行编码
函数使用方法
查询参数编码 urlencode({ 参数为字典 })
给URL地址中查询参数进行编码,参数类型为字典
-
使用方法
# 1、URL地址中 一 个查询参数 编码前: params = { 'wd':'美女'} 编码中: params = urllib.parse.urlencode(params) 编码后: params结果: 'wd=%E7%BE%8E%E5%A5%B3' # 2、URL地址中 多 个查询参数 编码前: params = { 'wd':'美女','pn':'50'} 编码中: params = urllib.parse.urlencode(params) 编码后: params结果: 'wd=%E7%BE%8E%E5%A5%B3&pn=50' 发现编码后会自动对多个查询参数间添加 & 符号
-
拼接URL地址的三种方式
# url = 'http://www.baidu.com/s?' # params = {'wd':'杨幂'} # 问题: 请拼接出完整的URL地址 ********************************** params = urllib.parse.urlencode(params) 【1】字符串相加 【2】字符串格式化(占位符 %s) 【3】format()方法 'http://www.baidu.com/s?{}'.format(params)
-
案例练习
问题: 在百度网站中输入要搜索的内容,响应内容保存
编码方法使用 urlencode()import requests from urllib import parse # 步骤1. 拼接URL地址 word = input('请输入搜索内容:') params = parse.urlencode({ 'wd':word}) url = 'http://www.baidu.com/s?{}' url = url.format(params) # 步骤2.发请求获取响应内容 headers = { 'User-Agent':'Mozilla/5.0'} html = requests.get(url=url,headers=headers).content.decode('utf-8') # 步骤 3. 保存到本地文件 filename = searchword + '.html' with open(filename,'w',encoding='utf-8') as f: f.write(html)
quote(‘参数为字符串’)使用
-
使用方法
http://www.baidu.com/s?wd=杨幂 # 对单独的字符串进行编码 - URL地址中的中文字符 word = '美女' result = urllib.parse.quote(word) result结果: ''
-
案例1
使用 quote()
在百度中输入要搜索的内容,把响应内容保存到本地文件import requests from urllib import parse # 步骤1. 拼接URL地址 word = input('请输入搜索内容:') params = parse.quote(word) url = 'http://www.baidu.com/s?wd={}' url = url.format(params) # 步骤2. 发请求获取响应内容 headers = { 'User-Agent':'Mozilla/5.0'} html = requests.get(url=url,headers=headers).content.decode('utf-8') # 步骤3. 保存到本地文件 filename = word + '.html' with open(filename,'w',encoding='utf-8') as f: f.write(html)
-
解码 unquote(string)
# 将编码后的字符串转为普通的Unicode字符串 from urllib import parse params = '%E7%BE%8E%E5%A5%B3' result = parse.unquote(params) result结果: 美女
-
小总结
【1】 什么是robots协议 【2】 requests模块使用 res = requests.get(url=url,headers={ 'User-Agent':'xxx'}) 响应对象res属性: a> res.text b> res.content c> res.status_code d> res.url 【3】urllib.parse a> urlencode({ 'key1':'xxx','key2':'xxx'}) b> quote('xxx') c> unquote('xxx') 【4】URL地址拼接 - urlencode() a> 'http://www.baidu.com/s?' + params b> 'http://www.baidu.com/s?%s' % params c> 'http://www.baidu.com/s?{}'.format(params)
模块re(正则解析)
使用流程
# 方法一
r_list=re.findall('正则表达式',html,re.S)
# 方法二
pattern = re.compile('正则表达式',re.S)
r_list = pattern.findall(html)
正则表达式元字符
元字符 | 含义 |
---|---|
. | 任意一个字符(不包括\n) |
\d | 一个数字 |
\s | 空白字符 |
\S | 非空白字符 |
[] | 包含[]内容 |
* | 出现0次或多次 |
+ | 出现1次或多次 |
练习:
-
匹配任意一个字符的正则表达式
import re # 方法一 pattern = re.compile('[\s\S]') result = pattern.findall(html) # 方法二 pattern = re.compile('.',re.S) result = pattern.findall(html)
贪婪匹配和非贪婪匹配
-
贪婪匹配(默认)
1、在整个表达式匹配成功的前提下,尽可能多的匹配 * + ? 2、表示方式:.* .+ .?
-
非贪婪匹配
1、在整个表达式匹配成功的前提下,尽可能少的匹配 * + ? 2、表示方式:.*? .+? .??
-
代码示例
import re html = ''' <div><p>九霄龙吟惊天变</p></div> <div><p>风云际会潜水游</p></div> ''' # 贪婪匹配 p = re.compile('<div><p>.*</p></div>',re.S) r_list = p.findall(html) print(r_list) # 非贪婪匹配 p = re.compile('<div><p>.*?</p></div>',re.S) r_list = p.findall(html) print(r_list)
正则表达式分组
-
作用
在完整的模式中定义子模式,将每个圆括号中子模式匹配出来的结果提取出来
-
示例代码
import re s = 'A B C D' p1 = re.compile('\w+\s+\w+') print(p1.findall(s)) # 分析结果是什么??? # 结果:['A B', 'C D'] p2 = re.compile('(\w+)\s+\w+') print(p2.findall(s)) # 第一步: ['A B', 'C D'] # 第二步: ['A', 'C'] p3 = re.compile('(\w+)\s+(\w+)') print(p3.findall(s)) # 第一步: ['A B', 'C D'] # 第二步: [('A', 'B'), ('C', 'D')]
-
分组总结
1、在网页中,想要什么内容,就加() 2、先按整体正则匹配,然后再提取分组()中的内容 如果有2个及以上分组(),则结果中以元组形式显示 [(),(),()]
-
分析需求
【1】确定URL地址 百度搜索 - 猫眼电影 - 榜单 - top100榜 【2】 爬取目标 所有电影的 电影名称、主演、上映时间 电影名称、主演、上映时间
-
代码思路
【1】查看网页源码,确认数据来源 响应内容中存在所需抓取数据 - 电影名称、主演、上映时间 【2】翻页寻找URL地址规律 第1页:https://maoyan.com/board/4?offset=0 第2页:https://maoyan.com/board/4?offset=10 第n页:offset=(n-1)*10 【3】编写正则表达式 <div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>
-
参考代码
import requests import re import time import random class MaoyanSpider: def __init__(self): self.url = 'https://maoyan.com/board/4?offset={}' self.headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'} def get_html(self, url): html = requests.get(url=url, headers=self.headers).text # 直接调用解析函数 self.parse_html(html) def parse_html(self, html): """解析提取数据""" regex = '<div class="movie-item-info">.*?title="(.*?)".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p>' pattern = re.compile(regex, re.S) r_list = pattern.findall(html) # r_list: [('活着','牛犇','2000-01-01'),(),(),...,()] self.save_html(r_list) def save_html(self, r_list): """数据处理函数""" item = { } for r in r_list: item['name'] = r[0].strip() item['star'] = r[1].strip() item['time'] = r[2].strip() print(item) def run(self): """程序入口函数""" for offset in range(0, 91, 10): url = self.url.format(offset) self.get_html(url=url) # 控制数据抓取频率:uniform()生成指定范围内的浮点数 time.sleep(random.uniform(0,1)) if __name__ == '__main__': spider = MaoyanSpider() spider.run()
抓取数据存储到Mysql
import pymysql
db = pymysql.connect('localhost','root','123456','maoyandb',charset='utf8')
cursor = db.cursor()
ins = 'insert into filmtab values(%s,%s,%s)'
cursor.execute(ins,['xxx','xxxx','xxxx'])
db.commit()
cursor.close()
db.close()
-
案例 - 将电影信息存入MySQL数据库中
【1】创建库命令 create database maoyandb charset utf8; use maoyandb; create table maoyantab( name varchar(100), star varchar(300), time varchar(100) )charset=utf8; 【2】 使用excute()方法将数据存入数据库思路 2.1) 在 __init__() 中连接数据库并创建游标对象 2.2) 在 save_html() 中将所抓取的数据处理成列表,使用execute()方法写入 2.3) 在run() 中等数据抓取完成后关闭游标及断开数据库连接
数据存储为 - csv文件
【1】目的
将爬取的数据存放到本地的csv文件中
【2】使用流程步骤
2.1> 打开csv文件
2.2> 初始化写入对象
2.3> 写入数据(参数为列表)
【3】参考代码
import csv
with open('sky.csv','w') as f:
writer = csv.writer(f)
writer.writerow([])
-
案例代码
【1】题目描述 创建 www.csv 文件,在文件中写入数据 【2】数据写入 - writerow([])方法 import csv with open('test.csv','w') as f: writer = csv.writer(f) writer.writerow(['超哥哥','25'])
-
实践1 - 使用 writerow() 方法将数据存入本地
【1】在 __init__() 中打开csv文件,因为csv文件只需要打开和关闭1次即可 【2】在 save_html() 中将所抓取的数据处理成列表,使用writerow()方法写入 【3】在run() 中等数据抓取完成后关闭文件
抓取(电影名称、主演、上映时间)
存入csv文件,使用writerow()方法
- 参考代码
import requests import re import time import random import csv class MaoyanSpider: def __init__(self): self.url = 'https://maoyan.com/board/4?offset={}' self.headers = { 'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E)'} # 打开文件,初始化写入对象 self.f = open('maoyan.csv', 'w', newline='', encoding='utf-8') self.writer = csv.writer(self.f) def get_html(self, url): html = requests.get(url=url, headers=self.headers).text # 直接调用解析函数 self.parse_html(html) def parse_html(self, html): """解析提取数据""" regex = '<div class="movie-item-info">.*?title="(.*?)".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p>' pattern = re.compile(regex, re.S) r_list = pattern.findall(html) # r_list: [('活着','牛犇','2000-01-01'),(),(),...,()] self.save_html(r_list) def save_html(self, r_list): """数据处理函数""" for r in r_list: li = [ r[0].strip(), r[