目录
一、爬虫基础
1、robots协议
规定了网站哪些是可爬,哪些不可爬,君子协议
2、http协议
(1)概念
服务器和客户端进行数据交互的一种形式
(2)常用的请求头信息
user-agent:请求载体的身份标识
Connection :请求完毕后,是断开连接,还是保持连接
(3) 常用响应头信息
connect-type 服务器响应回客户端的数据类型
3、https协议
安全的超文本传输协议
4、加密方式
对称密钥加密
非对称密钥加密
证书密钥加密
二、requests模块
1、解释
(1)requests 模块
Python中,原生的一款基于网络请求的模块,功能非常强大,简单便捷,效率极高。
(2)作用
模拟浏览器发请求
(3)如何使用(request模块的编码流程)
-- 指定 URL
-- 发起请求
-- 获取响应数据
-- 持久化存储
2、第一个简单爬虫
"""
爬取首页数据
"""
import requests
# 需要爬取的网页url
url_real = '网址'
# 获取响应对象
def url_request(url):
return requests.get(url)
# 持久化存储爬取的数据
def storage_request(url):
response = url_request(url=url)
with open('test1.html', 'w', encoding='utf-8') as f:
f.write(response.text)
print("爬虫结束")
# 主程序入口
if __name__ == '__main__':
storage_request(url_real)
运行结果如下:
3、输入参数,爬取页面搜索结果
"""
输入参数,爬取搜索的结果页面
此处我们需要伪造UA,否则爬取结果会显示:需要验证码验证
UA:User-Agent (请求载体的身份标识)
UA检测 :门户网站会检测对应请求的载体身份标识,如果检测到标识是来自某一款浏览器,说明是正常的请求,否则说明不正常(爬虫),则服务器可能会拒绝请求
UA伪装 :让爬虫对应的请求载体标识伪装成某一款浏览器
"""
import requests
# 获取响应对象
def input_somthing(kw):
url_real = '网址'
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Mobile Safari/537.36'
}
param = {
'query': kw
}
return requests.get(url=url_real, params=param, headers=headers)
# 持久化存储爬取的数据
def storage_request(kw):
response = input_somthing(kw)
with open('test2.html', 'w', encoding='utf-8') as f:
f.write(response.text)
print("爬虫结束")
# 主程序入口
if __name__ == '__main__':
kw = input('输入想要查询的内容:')
storage_request(kw)
4、爬取翻译某个界面的数据
分析 xhr 可以得到
我们对 url 发起了一个 post请求,携带一个 kw值为dog
返回的是一个json
代码如下
"""
爬取翻译结果,结果为json
"""
import json
import requests
# 获取响应对象
def input_somthing(kw):
# 需要请求的url网址
url_real = '网址'
# UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0'
}
# post 请求的参数
data = {
'kw': kw
}
# 返回请求发送
return requests.post(url=url_real, data=data, headers=headers)
# 持久化存储爬取的数据
def storage_request(kw):
response = input_somthing(kw)
job = response.json()
# 存储
with open('test3.json', 'w', encoding='utf-8') as f:
# ensure_ascii 不使用ASCII码
json.dump(job, f, indent=4,ensure_ascii=False)
print("爬虫结束")
# 主程序入口
if __name__ == '__main__':
kw = input('输入想要查询的内容:')
storage_request(kw)
5、爬取电影排行榜信息
代码如下:
"""
爬取电影排行榜信息
"""
import json
import requests
# 获取响应对象
def get_response():
# 需要请求的url网址
url = '网址'
# UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0'
}
# get 请求的参数
param = {
'type': '24',
'interval_id': '100:90',
'action': '',
'start': '1', # 从库中的第几个电影去取
'limit': '20' # 一次取得电影的个数
}
# 返回请求发送
return requests.get(url=url, params=param, headers=headers)
# 持久化存储爬取的数据
def storage_request():
response = get_response()
job = response.json()
# 存储
with open('json/test4.json', 'w', encoding='utf-8') as f:
# ensure_ascii 不使用ASCII码
json.dump(job, f, indent=4, ensure_ascii=False)
print("爬虫结束")
# 主程序入口
if __name__ == '__main__':
storage_request()
6、爬取城市餐厅地址
"""
爬取餐厅地址
"""
import json
import requests
# 获取响应对象
def post_response(kw):
# 需要请求的url网址
url = '网址'
# UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0'
}
# get 请求的参数
param = {
'cname': '',
'pid': '',
'keyword': kw,
'pageIndex': '1', # 第几页
'pageSize': '10' # 一页几个数据
}
# 返回请求发送
return requests.post(url=url,headers=headers,params=param)
# 持久化存储爬取的数据
def storage_request(kw):
response = post_response(kw)
job = response.text
new_job = json.loads(job)
# 存储
with open('json/test5.json', 'w', encoding='utf-8') as f:
# ensure_ascii 不使用ASCII码
json.dump(new_job, f, indent=4, ensure_ascii=False)
print("爬虫结束")
# 主程序入口
if __name__ == '__main__':
kw = input('请输入地名:')
storage_request(kw)
三、数据解析
1、爬取图片数据,有指定图片url
"""
爬取图片数据
有指定图片url
"""
import requests
# 获取响应对象
def requ_response():
# 需要请求的url网址
url = '网址'
# UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0'
}
# 返回请求发送
return requests.get(url=url, headers=headers)
# 持久化存储爬取的数据
def storage_request():
# content 存储的是图片二进制文件
request = requ_response().content
# 存储
with open('json/test7.jpg', 'wb') as f:
f.write(request)
print("爬虫结束")
# 主程序入口
if __name__ == '__main__':
storage_request()
2、根据re爬取指定信息
"""
"""
import re
import requests
url = '网址'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0'
}
# 爬取页面 html 代码
get_response = requests.get(url=url, headers=headers)
page_text = get_response.text
# 解析数据
obj = re.compile(r'<li>.*?<div class="item">.*?<span class="title">'
r'(?P<name>.*?)</span>.*?<p class="">.*?<br>(?P<year>.*?) '
r'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>', re.S)
result = obj.finditer(page_text)
for it in result:
print('电影名:' + it.group('name') + ';上映时间:' + it.group('year').strip() + ';电影评分:' + it.group('score').strip())
get_response.close()
3、爬取电影名加下载地址
"""
定位到2022必看热片
从2022必看热片中提取子页面的链接地址
请求子页面的链接地址,拿到我们想要的下载地址(下载地址)
"""
import re
import requests
# 爬取的网页主页面
url = '网址'
# 若是爬不到 可在request中添加,不进行安全验证 verify=False
resp = requests.get(url=url)
resp.encoding = 'gb2312' # 乱码指定字符集
# 拿到主页面的html
page_text = resp.text
# 制定第一次正则,拿取包含电影名和子页面地址的html片段
obj = re.compile('.*2022必看热片</span>.*?<ul>(?P<a>.*?)</ul>', re.S)
result = obj.finditer(page_text)
for it in result:
# 将拿取的html片段存储在tmp中
tmp = it.group('a').strip()
# 制定第二次正则,拿取第一次取得html片段中包含的电影名和子页面地址
obj2 = re.compile("<li><a href='(?P<ur>.*?)' title.*?《(?P<name>.*?)》", re.S)
result2 = obj2.finditer(tmp)
for it in result2:
# tmp = it.group('name') + ' ' + url + it.group('ur')
# 将拿取得子页面地址片段和地址拼接形成完整的url地址
url2 = url + it.group('ur')
# 对子页面地址发起请求,
res2 = requests.get(url2)
# 乱码使用解码
res2.encoding = 'gb2312'
# 拿取子页面的html
txt = res2.text
# 制定第三次正则,拿取子页面中的迅雷下载地址
obj3 = re.compile('【下载地址】.*?<a href="(?P<pp>magnet.*?)">magnet', re.S)
last = obj3.finditer(txt)
for a in last:
# 打印出 电影名和迅雷下载地址
print(it.group('name') + ' ' + a.group('pp'))
4、拿到json数据
"""
"""
import json
import requests
url = '网址'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0'
}
params = {
'limit': "20",
'current': "1",
'pubDateStartTime': "",
'pubDateEndTime': "",
'prodPcatid': "",
'prodCatid': "",
'prodName': ""
}
job = requests.post(url=url, headers=headers, params=params)
a = job.json()
print(json.dumps(a,indent=4,ensure_ascii=False))
5、利用bs批量下载图片
"""
"""
import time
import requests
from bs4 import BeautifulSoup
url = '网址'
res = requests.get(url=url)
res.encoding = 'utf-8'
# 拿到网页源代码
page_text = res.text
# 把源代码交给bs,并说明是html代码
main_page = BeautifulSoup(page_text, 'html.parser')
# find 找一次停止 find_all 一直找到最后
alist = main_page.find('div', class_='swiper-box').find_all('a')
for a in alist:
# 使用get命令取具体标签值
# print(url + a.get('href'))
new_url = url + a.get('href')
page_text = requests.get(new_url).text
main_page = BeautifulSoup(page_text, 'html.parser')
img = main_page.find('section', class_='img-content').find('img')
# print(blist.get('src'))
# 下载图片
# 拿到图片的字节
img_resp = requests.get(url=img.get('src')).content
img_name = img.get('src').split('/')[-1]
print(img_name)
with open('img/'+img_name, 'wb') as f:
f.write(img_resp)
print('1111111111111111111111')
print('over')
四、xpath解析(重点)
1、前置知识
(1)入门 1
xpath 是在XML 文档中搜索内容的一门语言
html 是 xml的一个子集
代码如下:
"""
xpath 爬取
"""
from lxml import etree
xml = """
<book>
<id>1111</id>
<nick>aaaaaaa</nick>
<name>只是当时已惘然</name>
<price>9.99</price>
<author>
<nick>苏轼</nick>
<nick>柳宗元</nick>
<div>
<nick>王安石</nick>
<div>
<nick>1111</nick>
</div>
</div>
<div>
<nick>2222</nick>
</div>
</author>
</book>
"""
tree = etree.XML(xml)
# 表示层级关系,第一个/是根节点
result = tree.xpath('/book/name/text()') # text() 拿文本
result2 = tree.xpath('/book/author/nick/text()')
# 加双斜杠 代表查找下所有的nick(所有后代)
result3 = tree.xpath('/book/author//nick/text()')
# * 代表通配符 任意节点
result4 = tree.xpath('/book/author/*/nick/text()')
# book下所有的nick后代
result5 = tree.xpath('/book//nick/text()')
print(result)
print(result2)
print(result3)
print(result4)
print(result5)
(2)入门2
from lxml import html
tree = html.parse('json/a.html')
# xpath 的顺序是从1 开始数数的,[] 表示索引
result = tree.xpath('/html/body/div/ol/li[1]/text()')
# 取标签中的指定值 如下
result2 = tree.xpath('/html/body/div/ul/li/a[@href="dapao"]/text()')
# 循环打印所有的 li
result3 = tree.xpath('/html/body/div/ul/li')
for li in result3:
# 从每一个li中提取信息
result4 = li.xpath('./a/text()') # 在li中继续寻找
print(result4)
# 拿取 标签里的属性值
result5 = li.xpath('./a/@href')
print(result5)
# 直接打印
print(tree.xpath('/html/body/div/ol/li[1]/text()'))
2、实战
"""
利用xpath爬取相关信息
"""
import requests
from lxml import etree
url = '网址'
res = requests.get(url)
page_text = res.text
tree = etree.HTML(page_text)
divs = tree.xpath('/html/body/div[6]/div/div/div[2]/div[5]/div[1]/div')
for div in divs:
# 价格
price = div.xpath('./div/div/a[2]/div[2]/div[1]/span[1]/text()')[0]
# 近半年成交数
num = div.xpath('./div/div/a[2]/div[2]/div[1]/span[2]/text()')[0]
# title
title = 'python'.join(div.xpath('./div/div/a[2]/div[2]/div[2]/p/text()'))
# 位置
loca = div.xpath('./div/div/a[1]/div[1]/div/span/text()')[0]
print(loca + '---' + title + '---' + price + '---' + num)