本次目的:
python爬取海量表情包
亮点:
- 系统分析目标网页
- html标签数据解析方法
- 海量图片数据一键保存
环境介绍:
模块使用:
- requests >>> pip install requests
- parsel >>> pip install parsel
相对应的安装包/安装教程/激活码/使用教程/学习资料/工具插件 可以点击领取
模块安装问题:
如果安装python第三方模块:
- win + R 输入 cmd 点击确定, 输入安装命令 pip install 模块名 (pip install requests) 回车
- 在pycharm中点击Terminal(终端) 输入安装命令
安装失败原因:
失败一:
pip 不是内部命令
解决方法:
设置环境变量
失败二:
出现大量报红 (read time out)
解决方法:
因为是网络链接超时, 需要切换镜像源 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 华中理工大学:http://pypi.hustunique.com/ 山东理工大学:http://pypi.sdutlinux.org/ 豆瓣:http://pypi.douban.com/simple/ 例如:pip3 install -i https://pypi.doubanio.com/simple/ 模块名
失败三:
cmd里面显示已经安装过了, 或者安装成功了, 但是在pycharm里面还是无法导入
解决方法:
可能安装了多个python版本 (anaconda 或者 python 安装一个即可) 卸载一个就好 或者你pycharm里面python解释器没有设置好
如何配置pycharm里面的python解释器?
- 选择file(文件) >>> setting(设置) >>> Project(项目) >>> python interpreter(python解释器)
- 点击齿轮, 选择add
- 添加python安装路径
pycharm如何安装插件?
- 选择file(文件) >>> setting(设置) >>> Plugins(插件)
- 点击 Marketplace 输入想要安装的插件名字 比如:翻译插件 输入 translation
- 选择相应的插件点击 install(安装) 即可
- 安装成功之后 是会弹出 重启pycharm的选项 点击确定, 重启即可生效
爬虫基本思路流程:
一. 数据来源分析
- 确定要获取的内容 (确定需求)
发表情网站的表情包图片 - 通过开发者工具抓包分析 数据(图片url地址以及图片标题)来源
可以知道发表情这个网站是静态网页, 我们想要的数据内容都是来自他网页源代码
二. 代码实现步骤:
- 发送请求, 对于表情包列表页面发送请求
- 获取数据, 获取服务器返回的数据内容(response响应体数据)
- 解析数据, 提取我们想要数据内容 (图片url地址 以及 图片标题)
- 保存数据, 把获取下来的内容保存本地的文件夹里面
- 多页爬取, 根据请求url地址的变化规律
代码
导入模块
import requests
import parsel
import re
# 1. 发送请求
# 需要注意点: 确定请求url地址 请求方法 请求头参数(某些网站需要加cookie 或者 防盗链)
for page in range(12, 21):
print(f'正在爬取第{page}页数据内容')
url = f'https://fabiaoqing.com/biaoqing/lists/page/{page}.html'
# headers 作用伪装python代码的 爬虫是模拟浏览器对于服务器发送请求
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36'
}
response = requests.get(url=url, headers=headers)
# 2. 获取数据, 获取服务器返回的数据内容(response响应体数据) response.text 获取响应体文本数据
# 3. 解析数据 提取内容, 是要根据服务器返回的数据, 而不是看元素面板
# print(response.text) # 得到的response.text 这个html字符串数据 直接提取字符串数据内容 需要用re正则表达式
selector = parsel.Selector(response.text) # 把得到的字符串数据内容 转换成 selector 对象
# css选择器 就是根据标签属性内容提取数据
divs = selector.css('div.ui.segment.imghover div') # 获取所有div标签 返回对象
for index in divs:
# a::attr(title) 获取a标签里面 title 属性 数据 get() 获取第一个标签数据内容
title = index.css('a::attr(title)').get()
title = re.sub(r'[\/:*?"<>|\n]', '', title)
img_url = index.css('img::attr(data-original)').get()
# split 字符串分割的方法 列表[-1] 取最后一个元素 右边的第一个元素
img_name = img_url.split('.')[-1]
# response.content 获取二进制数据内容, 保存图片/视频/音频/特定格式的文件内容 都是以二进制数据保存
img_content = requests.get(url=img_url, headers=headers).content
with open('img\\' + title + '.' + img_name, mode='wb') as f:
f.write(img_content)
print(title, '保存成功')
多线程代码
import re
import time
import requests
import parsel
import concurrent.futures
def change_title(title):
mode = re.compile(r'[\\\/\:\*\?\"\<\>\|\n]')
new_title = re.sub(mode, '_', title)
return new_title
def get_response(html_url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
}
response = requests.get(url=html_url, headers=headers)
return response
def save(name, title, img_url):
img_content = get_response(img_url).content
with open('img\\' + title + '.' + name, mode='wb') as f:
f.write(img_content)
print('正在保存:', title)
def main(html_url):
html_data = get_response(html_url).text
selector = parsel.Selector(html_data)
divs = selector.css('#container div.tagbqppdiv')
for div in divs:
title = div.css('img::attr(title)').get()
img_url = div.css('img::attr(data-original)').get()
name = img_url.split('.')[-1]
new_title = change_title(title)
if len(new_title) > 255:
new_title = new_title[:10]
save(name, new_title, img_url)
else:
save(name, new_title, img_url)
if __name__ == '__main__':
start_time = time.time()
exe = concurrent.futures.ThreadPoolExecutor(max_workers=7)
for page in range(1, 201):
url = f'https://www.fabiaoqing.com/biaoqing/lists/page/{page}.html'
exe.submit(main, url)
exe.shutdown()
use_time = int(time.time()) - int(start_time)
print(f'总计耗时:{use_time}秒')
|