你只认识大众汽车的车标怎么能行?赶紧用python采集所有车标学习一下

梦想橡皮擦 2021-10-28 00:39:08
认识 汽车 大众 车标 大众汽车

本篇博客我们将学习如何通过 scrapy 批量下载文件,还能学习通过密码解压缩包?

目标站点分析

本次要采集的目标站点为:【车标网】,最终获取的数据是车标的的矢量图。
python 入门教程,python采集爬虫,python
在测试过程中发现,最后下载的压缩包存在解压密码,所以增加一个 通过密码解压缩的步骤

素材的下载地址,比较容易获取到,通过地址 logo.php?id=119 修改为 download.php?id=119 即可实现。

其中车标列表页所在的页面无迭代规则,按照分类获取即可:

http://www.chebiao.net/domestic.php
http://www.chebiao.net/es.php
http://www.chebiao.net/jsk.php
http://www.chebiao.net/other.php
http://www.chebiao.net/famous.php

编写时间

scrapy 基本创建不在过多说明,spider 文件夹中的爬虫文件名为 cb.py,首先通过 start_urls 的设置,采集所有分类数据。

import scrapy
from chebiao.items import ChebiaoItem
from urllib.parse import urlparse
class CbSpider(scrapy.Spider):
name = 'cb'
allowed_domains = ['chebiao.net']
start_urls = ['http://www.chebiao.net/domestic.php', 'http://www.chebiao.net/es.php',
'http://www.chebiao.net/jsk.php', 'http://www.chebiao.net/other.php',
'http://www.chebiao.net/famous.php']

接下来就是重点部分了,我们将启用 FilesPipeline 管道,用于实现对文件的下载。

使用该模块需要导入如下内容:

from scrapy.pipelines.files import FilesPipeline

FilesPipeline 类继承自 MediaPipeline,打开类文件源码,在其中发现两个比较重要的类变量。

DEFAULT_FILES_URLS_FIELD = 'file_urls'
DEFAULT_FILES_RESULT_FIELD = 'files'

上述两个变量,如果不进行修改,后续在 items.py 文件中,必须要进行声明与赋值。

在查看源码的过程中,发现了很多可以在 settings.py 文件初始化的配置,代码不在整体复制,本文仅用到了 FILES_STORE,即下图框选区域,该值表示文件存储路径。
python 入门教程,python采集爬虫,python
FilesPipeline 类中三个比较重要的方法是:

  • file_path:遍历 item 中的每一项,返回一个文件存储地址,函数原型如下所示:
    file_path(self, request, response=None, info=None, *, item=None)
  • get_media_requests:遍历 item 中的每一项,返回一个 Request 请求,请求的结果会传递给 item_completed 方法;
  • item_completed:媒体请求完毕之后,返回数据到该方法,并且该方法需要返回 item 或者 drop item

这里还要补充一个知识点,也是在翻阅 scrapy 源码的时候发现的,在 MediaPipeline 类中存在如下私有方法。

def _make_compatible(self):
"""Make overridable methods of MediaPipeline and subclasses backwards compatible"""
methods = [
"file_path", "media_to_download", "media_downloaded",
"file_downloaded", "image_downloaded", "get_images"
]
for method_name in methods:
method = getattr(self, method_name, None)
if callable(method):
setattr(self, method_name, self._compatible(method))

上述代码将 file_pathfile_downloaded 方法进行了兼容,即 file_pathmedia_to_downloadmedia_downloaded 功能一致,file_downloadedimage_downloadedget_images 功能一致。

如果你在测试代码时,发现 file_path() 方法被执行了 3 次,该原因也是由于 scrapy 框架实现的,因为 file_path() 方法分别在 media_to_download()media_downloaded()file_downloaded() 三个方法中被调用过。继续深入学习,会发现上述 3 个方法的调用顺序,这里就不在过多展开说明。

通过单文件下载,测试 scrapy 下载文件流程

接下来通过一个文件,体验整体的下载流程,该地址为:http://www.chebiao.net/download.php?id=181
按照一般编写爬虫代码的顺序,修改如下文件代码:
items.py 文件代码如下

import scrapy
class ChebiaoItem(scrapy.Item):
file_url = scrapy.Field()
file_name = scrapy.Field()
files = scrapy.Field()

其中 file_url 表示请求的文件名,如果不希望自己扩展,应该用 file_urls 实现,file_name 为保存文件名,files 为默认字段,用于返回文件响应结果相关信息。

cb.py 文件代码如下

import scrapy
from chebiao.items import ChebiaoItem
class CbSpider(scrapy.Spider):
name = 'cb'
allowed_domains = ['chebiao.net']
start_urls = ['http://www.chebiao.net/famous.php']
def parse(self, response):
item = ChebiaoItem()
item['file_name'] = "测试" # 文件名
item['file_url'] = "http://www.chebiao.net/download.php?id=181"
yield item

其中 file_namefile_url 都为测试值。

settings.py 文件设置爬虫相关配置

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36' # 用户代理
ROBOTSTXT_OBEY = False # 不访问 robot.txt 文件
DEFAULT_REQUEST_HEADERS = {

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Host': 'www.chebiao.net',
'Referer': 'http://www.chebiao.net/logo.php'
} # 请求头
# 开启数据管道,尤其注意 ChebiaoFilePipeline 为我们手动创建的管道类,代码在下文
ITEM_PIPELINES = {

'chebiao.pipelines.ChebiaoFilePipeline': 1,
'chebiao.pipelines.ChebiaoPipeline': 300,
}
FILES_STORE = './files' # 文件存储路径
LOG_LEVEL = 'WARNING' # 日志等级

配置中的 FILES_STORE 表示文件存储路径,设置绝对地址与相对地址都可。

pipelines.py 代码文件

from scrapy.pipelines.files import FilesPipeline
# 自定义类,继承自 FilesPipeline
class ChebiaoFilePipeline(FilesPipeline):
def get_media_requests(self, item, info):
print("--get_media_requests--start-----")
print("正在下载:", item['file_name'])
print("--get_media_requests--end-----")
# 请求传递文件名参数
yield Request(item['file_url'], meta={
'title': item['file_name']})
def file_path(self, request, response=None, info=None):
print("--file_path--start-----")
file_name = request.meta.get('title') + ".rar"
print("--file_path--end-----")
return file_name
def item_completed(self, results, item, info):
print("--item_completed--start-----")
print(results)
print("下载完毕")
print("--item_completed--end--------")
return item

上述代码中的 item_completed() 方法,还有一层含义,是将数据返回到下一个要执行的管道类,例如在该方法中为下一个管道增加 items.py 中的参数,需提前在 items.py 中增加 file_paths 变量。

def item_completed(self, results, item, info):
print("--item_completed--start-----")
print(results)
print("下载完毕")
file_paths = [x['path'] for ok, x in results if ok]
adapter = ItemAdapter(item)
adapter['file_paths'] = file_paths
print("--item_completed--end--------")
return item

扩展为多文件下载

只需要修改 cb.py 文件即可实现多文件下载。

import scrapy
from chebiao.items import ChebiaoItem
from urllib.parse import urlparse
class CbSpider(scrapy.Spider):
name = 'cb'
allowed_domains = ['chebiao.net']
start_urls = ['http://www.chebiao.net/domestic.php', 'http://www.chebiao.net/es.php',
'http://www.chebiao.net/jsk.php', 'http://www.chebiao.net/other.php',
'http://www.chebiao.net/famous.php']
def parse(self, response):
down_url = "http://www.chebiao.net/download.php"
dds = response.xpath("//div[@class='box2']/dl/dd")
for dd in dds:
item = ChebiaoItem()
name = dd.xpath('./a/text()').extract()[0]
url = dd.xpath('./a/@href').extract()[0]
url = down_url + "?" + urlparse(url).query
item['file_name'] = name
item['file_url'] = url
yield item

现在我们已经可以下载全站的图片了,接下来实现解压缩文件。

解压文件

由于文件是 rar 格式,所以需要安装 unrar 模块,安装过程非常简单,使用 pip install unrar 即可,但是后续出现一些列问题,接下来为大家一一说明。

安装 unrar 之后,直接使用会出现找不到库的 BUG,需要下载 unrar library,打开 https://www.rarlab.com/rar_add.htm,找到 UnRAR.dll 下载即可,下载之后的文件为 UnRARDLL.exe,直接按照到默认路径,例如我本机为 Windows7 64 位操作系统,安装路径为 C:\Program Files (x86)\UnrarDLL

下面要配置环境变量与文件名称。

  1. 配置 x64 目录到系统环境变量中;
  2. 修改 x64 目录中的 UnRaR64.dllUnRAR64.lib 为全小写字母。

python 入门教程,python采集爬虫,python

上述内置配置完毕,由于修改了环境变量,为了让 pycharm 等开发工具加载,需要重启开发工具。

接下来在 ChebiaoPipeline 类中编写如下代码,重点注意解压部分相关代码。

import os
from unrar import rarfile
class ChebiaoPipeline:
def process_item(self, item, spider):
# 获取文件完整路径
path = os.path.join(os.getcwd(), "files", item['file_path'])
# 解压路径
extract_path = os.path.join(os.getcwd(), "files")
# 由于文件设置了【加密文件名】,所以在加载文件时,也需要设置密码
rf = rarfile.RarFile(path, pwd="www.chebiao.net")
# 通过密码解压文件,解压目录为当前目录
rf.extractall(path=extract_path, pwd="www.chebiao.net")
return item

最终运行结果如下所示:
python 入门教程,python采集爬虫,python

写在后面

今天是持续写作的第 249 / 365 天。
期待 关注点赞评论收藏

更多精彩

《爬虫 100 例,专栏销售中,买完就能学会系列专栏》
从前有一个网站叫"在行",今天拿它练练Python爬虫

↓ ↓ ↓ ↓完整代码↓ ↓ ↓ ↓
版权声明
本文为[梦想橡皮擦]所创,转载请带上原文链接,感谢
https://dream.blog.csdn.net/article/details/120988302

  1. python的site-packages复制直接到其他电脑环境上能用吗
  2. Pycharm如何给项目配置python解释器
  3. conda创建python虚拟环境
  4. Python selenium的爬虫无法完整爬取整个页面的内容
  5. 高清版!这18张 Python 数据科学速查表,让你的代码变得更强大!
  6. python代码不会敲,请好心老哥帮助我一下
  7. Python敲七输出符合的个数
  8. Python 有人能给提供简单的思路嘛
  9. python单次运行写入csv成功,循环写入失败
  10. python利用os模块进行增量备份
  11. 【算法学习】807. 保持城市天际线(java / c / c++ / python / go / rust)
  12. 如何利用python输出等腰杨辉三角
  13. python按键执行倒计时小程序不能实现要求,要怎么改才好?
  14. Python request模块post请求的问题
  15. Django连接已有Oracle时的主键设置问题,没主键无法查询怎么办?
  16. 如何用python的dictionary编写一个联系人通讯录程序
  17. 如果Python里range反向输出,不输出步长会怎么样?
  18. 一个关于Python pip的问题: 出现Cannot open \python\Scripts\pip-script.py报错
  19. 富婆闺蜜非让我用Python给她写个淘宝双十一抢购脚本,那只能安排了
  20. 【全网最全】python正则表达式大全,所有讲解都在这,包教包会,学不会找我!
  21. AI python课和 python课都是198 这两个课是同一个课程内容吗?有什么区别和相似点?
  22. python的__new__()疑问
  23. Python代码阅读(第24篇):根据筛选函数将列表元素分成两组
  24. python怎么实现动态障碍物按固定路径行走
  25. Python代码阅读(第24篇):根据筛选函数将列表元素分成两组
  26. Python题目,希望帮我解答一下辛苦
  27. python +selenium 如何获取下拉列表,默认选中值
  28. 有个pb文件做好的模型,对此模型的操作想用python封装成api,怎么做?
  29. 请问,mac的Pycharm中新建项目时候的Base interpreter选项里有两个Python3.8,该选哪个?
  30. python如何读取指定文件名的excel并分别汇总
  31. 如何写利用python将fastq文件转换成fasta文件的脚本
  32. python小工具
  33. 新猿0基础python教程 如何写好接口文档
  34. 请问我哪里错了呀,数值计算,python运算符号出错,但是我看不出来
  35. Python游戏开发,Pygame模块,Python从零开始带大家实现一个魔塔小游戏(2)
  36. Python爬虫实战,requests模块,Python实现抓取王者荣耀全套皮肤
  37. Python游戏开发,Pygame模块,Python从零开始带大家实现一个魔塔小游戏(3)
  38. 大神们这个问题用python怎么解决啊
  39. 简单理解python装饰器
  40. 货物托运收费问题用python 求解 一直输出错误
  41. 使用 Python 实现的卷积神经网络初学者指南
  42. 为什么Python中调用模块传递列表报错,而直接模块内调用列表就不会报错。
  43. 可视化 Python 打包 exe,这个神器绝了!
  44. 如此高效!数据科学中这4款 Python 神器真的很棒!
  45. 用 Python 开发交互式 Web 应用,So Easy
  46. Python多分类问题pr曲线绘制(含代码)
  47. 80 行 Python 代码搞定全国区划代码
  48. 有包含一阶贝塞尔函数的Python库吗
  49. Python输出乘法口诀表中的2d是什么意思
  50. Python 爬虫goole图片 使用selenium+chromedriver 出错DevToolsActivePort file doesn't exist
  51. python怎么做,我不会做,别走,留下代码!
  52. (数据科学学习手札129)geopandas 0.10版本重要新特性一览
  53. MySQL备份之xtrabackup(Python)
  54. (数据科学学习手札129)geopandas 0.10版本重要新特性一览
  55. Python:枚举列表中所有元素的可能组合
  56. 编写python 程序 人的心跳频率与温度的关系 计算人的累记心跳次数
  57. python相关,请问这张图里代码c for c in coinValueList if c<=change是什么意思
  58. Python中的分段函数问题求解
  59. Python中的递归求年龄问题
  60. python如何求出多个股票的移动均价