==2. 爬虫请求模块==
2.1 requests模块
-
【1】Linux
sudo pip3 install requests
【2】Windows
python -m pip install requests
2.2 常用方法
-
requests.get()
【1】作用
向目标网站发起请求,并获取响应对象
【2】参数
2.1> url :需要抓取的URL地址
2.2> headers : 请求头
2.3> timeout : 超时时间,超过时间会抛出异常 -
爬虫程序示例
import requests
resp = requests.get(url='https://www.jd.com/')
# text属性:获取响应内容-字符串(右键->查看网页源代码)
html = resp.text
# content属性:获取响应内容-bytes(抓取图片、文件、音频、视频...)
html = resp.content
# status_code属性:获取HTTP响应码
code = resp.status_code
# url属性:返回实际数据的URL地址
url = resp.url
print(url) -
响应对象(resp)属性
【1】text :拿到网页源代码字符串
【2】resp.json() :拿到json格式的数据(响应数据为json格式的)
【3】content :字节流
【4】status_code :HTTP响应码
【5】url :实际数据的URL地址
【6】encoding :用法--res.encoding = 'utf-8' 改变字符编码
【7】apparent_encoding 可有获取现有的字符编码格式
【8】resp.headers :获取请求头
【9】resp.cookies :获取cookies -
重大问题思考
==网站如何来判定是人类正常访问还是爬虫程序访问?--检查请求头(User-Agent,Cookies,签名验证)
# 请求头(headers)中的 User-Agent
# 测试案例: 向测试网站http://httpbin.org/get发请求,查看请求头(User-Agent)
import requests
url = 'http://httpbin.org/get'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}
html = requests.get(url=url,headers=headers).text
print(html)
# 请求头中:User-Agent为-> python-requests/2.22.0 那第一个被网站干掉的是谁???我们是不是需要发送请求时重构一下User-Agent???添加 headers 参数!!!
-
重大问题解决 - headers参数
"""
包装好请求头后,向测试网站发请求,并验证
养成好习惯,发送请求携带请求头,重构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
# 在html中确认User-Agent
print(html)
3. URL地址拼接
3.1 拼接URL地址的三种方式
【1】字符串相加
【2】字符串格式化(占位符 %s)
【3】format()方法
'http://www.baidu.com/s?{}'.format(params)
url = 'https://www.guazi.com/dachang/buy/o{}/#bread'
for i in range(1, 21):
page_url = url.format(i)
print(page_url)
4. 正则解析模块re
4.1 使用流程
r_list=re.findall('正则表达式',html,re.S)
4.2 元字符
元字符 | 含义 |
---|---|
. | 任意一个字符(不包括\n) |
\d | 一个数字 |
\s | 空白字符 |
\S | 非空白字符 |
[] | 包含[]内容 |
* | 出现0次或多次 |
+ | 出现1次或多次 |
-
思考 - 匹配任意一个字符的正则表达式?
r_list = re.findall('.', html, re.S)
4.3 贪婪与非贪婪
-
贪婪匹配(默认)
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)
4.4 正则分组
-
作用
在完整的模式中定义子模式,将每个圆括号中子模式匹配出来的结果提取出来
-
分组总结
1、在网页中,想要什么内容,就加()
2、先按整体正则匹配,然后再提取分组()中的内容
如果有2个及以上分组(),则结果中以元组形式显示 [(),(),()]
3、最终结果有3种情况
情况1:[]
情况2:['', '', ''] -- 正则中1个分组时
情况3:[(), (), ()] -- 正则中多个分组时
5. 猫眼电影爬虫示例
5.1 项目需求
【1】官网地址:https://maoyan.com/board/4
【2】爬取目标
top100电影中100个电影的
2.1》电影名称
2.2》电影主演
2.3》上映时间
5.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>'
【4】开干吧兄弟
5.3 代码实现
""
猫眼电影top100抓取
"""
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; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'}
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>'
# [('名称','主演','时间'),(),...]
r_list = re.findall(regex, html, re.S)
for r in r_list:
print(r)
def crawl(self):
for offset in range(0, 91, 10):
page_url = self.url.format(offset)
self.get_html(url=page_url)
# 控制频率
time.sleep(random.randint(1, 3))
if __name__ == '__main__':
spider = MaoYanSpider()
spider.crawl()