当前位置:   article > 正文

Pyspider的简单使用

Pyspider的简单使用

一.准备工作

1.安装pyspider和PhantomJS,安装好了MongoDB并正常运行服务,还需要安装PyMongo库

pyspider的安装用

pip3 install pyspider

PhantomJS的安装

MongoDB安装

安装PyMongo库

pip3 install PyMongo

二.启动pyspider

命令行下执行

pyspider all

三.创建项目

接下来在浏览器中输入 http://localhost:5000,可以看到 PySpider 的主界面,点击右下角的 Create,命名为 taobaomm,当然名称你可以随意取,继续点击 Create。

 

这样我们会进入到一个爬取操作的页面。

整个页面分为两栏,左边是爬取页面预览区域,右边是代码编写区域。下面对区块进行说明:

左侧绿色区域:这个请求对应的 JSON 变量,在 PySpider 中,其实每个请求都有与之对应的 JSON 变量,包括回调函数,方法名,请求链接,请求数据等等。

绿色区域右上角Run:点击右上角的 run 按钮,就会执行这个请求,可以在左边的白色区域出现请求的结果。

左侧 enable css selector helper: 抓取页面之后,点击此按钮,可以方便地获取页面中某个元素的 CSS 选择器。

左侧 web: 即抓取的页面的实时预览图。

左侧 html: 抓取页面的 HTML 代码。

左侧 follows: 如果当前抓取方法中又新建了爬取请求,那么接下来的请求就会出现在 follows 里。

左侧 messages: 爬取过程中输出的一些信息。

右侧代码区域: 你可以在右侧区域书写代码,并点击右上角的 Save 按钮保存。

右侧 WebDAV Mode: 打开调试模式,左侧最大化,便于观察调试。

 

这样我们会进入到一个爬取操作的页面。

 

page 参数代表页码。所以我们暂时抓取前 30 页。页码到最后可以随意调整。

首先我们定义基地址,然后定义爬取的页码和总页码。

  1. from pyspider.libs.base_handler import *
  2. class Handler(BaseHandler):
  3. crawl_config = {
  4. }
  5. def __init__(self):
  6. self.base_url = 'https://mm.taobao.com/json/request_top_list.htm?page='
  7. self.page_num = 1
  8. self.total_num = 30
  9. @every(minutes=24 * 60)
  10. def on_start(self):
  11. while self.page_num <= self.total_num:
  12. url = self.base_url + str(self.page_num)
  13. print url
  14. self.crawl(url, callback=self.index_page)
  15. self.page_num += 1
  16. @config(age=10 * 24 * 60 * 60)
  17. def index_page(self, response):
  18. for each in response.doc('a[href^="http"]').items():
  19. self.crawl(each.attr.href, callback=self.detail_page)
  20. @config(priority=2)
  21. def detail_page(self, response):
  22. return {
  23. "url": response.url,
  24. "title": response.doc('title').text(),
  25. }

 

点击 save 保存代码,然后点击左边的 run,运行代码

运行后我们会发现 follows 出现了 30 这个数字,说明我们接下来有 30 个新请求,点击可查看所有爬取列表。另外控制台也有输出,将所有要爬取的 URL 打印了出来。

然后我们点击左侧任意一个绿色箭头,可以继续爬取这个页面。例如点击第一个 URL,来爬取这个 URL

 

点击之后,再查看下方的 web 页面,可以预览实时页面,这个页面被我们爬取了下来,并且回调到 index_page 函数来处理,目前 index_page 函数我们还没有处理,所以是继续构件了所有的链接请求。

 

爬取到了 MM 的列表,接下来就要进入到 MM 详情页了,修改 index_page 方法。

  1. def index_page(self, response):
  2. for each in response.doc('.lady-name').items():
  3. self.crawl(each.attr.href, callback=self.detail_page)

其中 response 就是刚才爬取的列表页,response 其实就相当于列表页的 html 代码,利用 doc 函数,其实是调用了 PyQuery,用 CSS 选择器得到每一个MM的链接,然后重新发起新的请求。

比如,我们这里拿到的 each.attr.href 可能是 mm.taobao.com/self/model_card.htm?user_id=687471686,在这里继续调用了 crawl 方法,代表继续抓取这个链接的详情。

self.crawl(each.attr.href, callback=self.detail_page)

然后回调函数就是 detail_page,爬取的结果会作为 response 变量传过去。detail_page 接到这个变量继续下面的分析。

 

好,我们继续点击 run 按钮,开始下一个页面的爬取。得到的结果是这样的。

 

哦,有些页面没有加载出来,这是为什么?

在之前的文章说过,这个页面比较特殊,右边的页面使用 JS 渲染生成的,而普通的抓取是不能得到 JS 渲染后的页面的,这可麻烦了。

然而,幸运的是,PySpider 提供了动态解析 JS 的机制。

友情提示:可能有的小伙伴不知道 PhantomJS,可以参考

爬虫JS动态解析

因为我们在前面装好了 PhantomJS,所以,这时候就轮到它来出场了。在最开始运行 PySpider 的时候,使用了pyspider all命令,这个命令是把 PySpider 所有的组件启动起来,其中也包括 PhantomJS。

所以我们代码怎么改呢?很简单。

  1. def index_page(self, response):
  2. for each in response.doc('.lady-name').items():
  3. self.crawl(each.attr.href, callback=self.detail_page, fetch_type='js')

可以发现,页面已经被我们成功加载出来了,简直不能更帅!

看下面的个性域名,所有我们需要的 MM 图片都在那里面了,所以我们需要继续抓取这个页面。

好,继续修改 detail_page 方法,然后增加一个 domain_page 方法,用来处理每个 MM 的个性域名。

  1. def detail_page(self, response):
  2. domain = 'https:' + response.doc('.mm-p-domain-info li > span').text()
  3. print domain
  4. self.crawl(domain, callback=self.domain_page)
  5. def domain_page(self, response):
  6. pass

好,继续重新 run,预览一下页面,终于,我们看到了 MM 的所有图片。

 

好,照片都有了,那么我们就偷偷地下载下来吧~

完善 domain_page 代码,实现保存简介和遍历保存图片的方法。

在这里,PySpider 有一个特点,所有的 request 都会保存到一个队列中,并具有去重和自动重试机制。所以,我们最好的解决方法是,把每张图片的请求都写成一个 request,然后成功后用文件写入即可,这样会避免图片加载不全的问题。

曾经在之前文章写过图片下载和文件夹创建的过程,在这里就不多赘述原理了,直接上写好的工具类,后面会有完整代码。

  1. import os
  2. class Deal:
  3. def __init__(self):
  4. self.path = DIR_PATH
  5. if not self.path.endswith('/'):
  6. self.path = self.path + '/'
  7. if not os.path.exists(self.path):
  8. os.makedirs(self.path)
  9. def mkDir(self, path):
  10. path = path.strip()
  11. dir_path = self.path + path
  12. exists = os.path.exists(dir_path)
  13. if not exists:
  14. os.makedirs(dir_path)
  15. return dir_path
  16. else:
  17. return dir_path
  18. def saveImg(self, content, path):
  19. f = open(path, 'wb')
  20. f.write(content)
  21. f.close()
  22. def saveBrief(self, content, dir_path, name):
  23. file_name = dir_path + "/" + name + ".txt"
  24. f = open(file_name, "w+")
  25. f.write(content.encode('utf-8'))
  26. def getExtension(self, url):
  27. extension = url.split('.')[-1]
  28. return extension

 

这里面包含了四个方法。

mkDir:创建文件夹,用来创建 MM 名字对应的文件夹。

saveBrief: 保存简介,保存 MM 的文字简介。

saveImg: 传入图片二进制流以及保存路径,存储图片。

getExtension: 获得链接的后缀名,通过图片 URL 获得。

然后在 domain_page 中具体实现如下

  1. def domain_page(self, response):
  2. name = response.doc('.mm-p-model-info-left-top dd > a').text()
  3. dir_path = self.deal.mkDir(name)
  4. brief = response.doc('.mm-aixiu-content').text()
  5. if dir_path:
  6. imgs = response.doc('.mm-aixiu-content img').items()
  7. count = 1
  8. self.deal.saveBrief(brief, dir_path, name)
  9. for img in imgs:
  10. url = img.attr.src
  11. if url:
  12. extension = self.deal.getExtension(url)
  13. file_name = name + str(count) + '.' + extension
  14. count += 1
  15. self.crawl(img.attr.src, callback=self.save_img,
  16. save={'dir_path': dir_path, 'file_name': file_name})
  17. def save_img(self, response):
  18. content = response.content
  19. dir_path = response.save['dir_path']
  20. file_name = response.save['file_name']
  21. file_path = dir_path + '/' + file_name
  22. self.deal.saveImg(content, file_path)

以上方法首先获取了页面的所有文字,然后调用了 saveBrief 方法存储简介。

然后遍历了 MM 所有的图片,并通过链接获取后缀名,和 MM 的姓名以及自增计数组合成一个新的文件名,调用 saveImg 方法保存图片。

好,基本的东西都写好了。

接下来。继续完善一下代码。第一版本完成。

版本一功能:按照淘宝MM姓名分文件夹,存储MM的 txt 文本简介以及所有美图至本地。

可配置项:

  • PAGE_START: 列表开始页码
  • PAGE_END: 列表结束页码
  • DIR_PATH: 资源保存路径
  1. from pyspider.libs.base_handler import *
  2. PAGE_START = 1
  3. PAGE_END = 30
  4. DIR_PATH = '/var/py/mm'
  5. class Handler(BaseHandler):
  6. crawl_config = {
  7. }
  8. def __init__(self):
  9. self.base_url = 'https://mm.taobao.com/json/request_top_list.htm?page='
  10. self.page_num = PAGE_START
  11. self.total_num = PAGE_END
  12. self.deal = Deal()
  13. def on_start(self):
  14. while self.page_num <= self.total_num:
  15. url = self.base_url + str(self.page_num)
  16. self.crawl(url, callback=self.index_page)
  17. self.page_num += 1
  18. def index_page(self, response):
  19. for each in response.doc('.lady-name').items():
  20. self.crawl(each.attr.href, callback=self.detail_page, fetch_type='js')
  21. def detail_page(self, response):
  22. domain = response.doc('.mm-p-domain-info li > span').text()
  23. if domain:
  24. page_url = 'https:' + domain
  25. self.crawl(page_url, callback=self.domain_page)
  26. def domain_page(self, response):
  27. name = response.doc('.mm-p-model-info-left-top dd > a').text()
  28. dir_path = self.deal.mkDir(name)
  29. brief = response.doc('.mm-aixiu-content').text()
  30. if dir_path:
  31. imgs = response.doc('.mm-aixiu-content img').items()
  32. count = 1
  33. self.deal.saveBrief(brief, dir_path, name)
  34. for img in imgs:
  35. url = img.attr.src
  36. if url:
  37. extension = self.deal.getExtension(url)
  38. file_name = name + str(count) + '.' + extension
  39. count += 1
  40. self.crawl(img.attr.src, callback=self.save_img,
  41. save={'dir_path': dir_path, 'file_name': file_name})
  42. def save_img(self, response):
  43. content = response.content
  44. dir_path = response.save['dir_path']
  45. file_name = response.save['file_name']
  46. file_path = dir_path + '/' + file_name
  47. self.deal.saveImg(content, file_path)
  48. import os
  49. class Deal:
  50. def __init__(self):
  51. self.path = DIR_PATH
  52. if not self.path.endswith('/'):
  53. self.path = self.path + '/'
  54. if not os.path.exists(self.path):
  55. os.makedirs(self.path)
  56. def mkDir(self, path):
  57. path = path.strip()
  58. dir_path = self.path + path
  59. exists = os.path.exists(dir_path)
  60. if not exists:
  61. os.makedirs(dir_path)
  62. return dir_path
  63. else:
  64. return dir_path
  65. def saveImg(self, content, path):
  66. f = open(path, 'wb')
  67. f.write(content)
  68. f.close()
  69. def saveBrief(self, content, dir_path, name):
  70. file_name = dir_path + "/" + name + ".txt"
  71. f = open(file_name, "w+")
  72. f.write(content.encode('utf-8'))
  73. def getExtension(self, url):
  74. extension = url.split('.')[-1]
  75. return extension

粘贴到你的 PySpider 中运行吧~

其中有一些知识点,我会在后面作详细的用法总结。大家可以先体会一下代码。

保存之后,点击下方的 run,你会发现,海量的 MM 图片已经涌入你的电脑啦~

如果想了解 PySpider 的更多内容,可以查看官方文档。

官方文档

 

转载自:https://cuiqingcai.com/2652.html

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/954843
推荐阅读
相关标签
  

闽ICP备14008679号