找回密码
 注册SCIFIFANS!
首页 科技专区 全栈 Scrapy+GitHubActions部署云爬虫

Scrapy+GitHubActions部署云爬虫

7
回复
7595
查看
[ 复制链接 ]

该用户从未签到

10

主题

51

回帖

404

积分

Judgement

积分
404
<

用邮箱/用户名来登录sci-fifans!

您需要 登录 才可以下载或查看,没有账号?注册SCIFIFANS!

x
本帖最后由 skyone 于 2021-3-22 13:00 编辑
原文:我的博客
标题:scrapy+GitHubActions部署云爬虫
禁止转载,部分引用请著名出处
为了学习GitHub Actions的基本使用,写一个爬虫练练手
这个爬虫用于下载哔哩哔哩相簿的图片
该文章分为三步:
  • 写爬虫
  • 写workflows文件
  • 上传代码到GitHub

懒得打代码就直接Fork我的仓库:
  1. # https
  2. https://github.com/skyone-wzw/action.git
  3. # ssh
  4. git@github.com:skyone-wzw/action.git
复制代码
重点是GitHub Actions云爬虫不需要自己的服务器,还可以访问wai wang!咳咳咳,总之,懂的都懂。
GitHub Actions 为开源软件提供免费服务器,配置如下
E5 2vCPU/7G RAM
对于公开仓库可免费无时间限制的使用,且单次使用时间长达 6 个小时
对爬虫来说,有以下优点
  • 免费
  • 万兆自由网络环境
  • 定时爬取
  • 并发(可同时进行20个任务)
  • 无需担心磁盘空间不足(近60G磁盘空间)

写一个scrapy爬虫创建项目
新建一个项目文件夹,打开CMD并切换到该文件夹,输入以下命令初始化git:
git init
使用scrapy新建项目并新建爬虫:
scrapy startproject bili bilibili.com
cd bili
scrapy genspider picture
创建项目完毕,下面使用IDE打开项目文件夹吧~
我使用的是Pycharm
储存图片信息的class
打开bili/items.py,不出意外的话,这里已经有一个BiliItem(scrapy.Item)类了
我们将其改为:
  1. import scrapy


  2. class BiliItem(scrapy.Item):
  3.     url = scrapy.Field()        # 图片连接
  4.     title = scrapy.Field()      # 图片标题
  5.     author = scrapy.Field()     # 作者
  6.     id = scrapy.Field()         # 图片id
  7.     uid = scrapy.Field()        # 作者uid
  8.     extension = scrapy.Field()  # 图片拓展名
复制代码
分析哔哩哔哩API
打开哔哩哔哩相簿,开启检查元素的网络那一栏,发现每加载一次都会有一个get请求:
很好,正是我们想要的,多次尝试,很容易分析出来:
  1. GET https://api.vc.bilibili.com/link ... _num=0&page_size=20
  2. Accept: application/json
复制代码
返回:
  1. GET https://api.vc.bilibili.com/link ... _num=0&page_size=20

  2. HTTP/1.1 200 OK
  3. Date: Sun, 21 Mar 2021 06:30:48 GMT
  4. Content-Type: application/json
  5. Transfer-Encoding: chunked
  6. Connection: keep-alive
  7. L: v
  8. X-Trace-Id: 29bd4f5ef5186679
  9. Http-Status-Code: 200
  10. Bili-Status-Code: 0
  11. Server: swoole-http-server
  12. Set-Cookie: l=v
  13. Expires: Sun, 21 Mar 2021 06:30:47 GMT
  14. Cache-Control: no-cache
  15. X-Cache-Webcdn: BYPASS from hw-sh3-webcdn-08

  16. {
  17.   "code": 0,
  18.   "msg": "success",
  19.   "message": "success",
  20.   "data": {
  21.     "total_count": 500,
  22.     "items": [
  23.       {
  24.         "user": {
  25.           "uid": 21690338,
  26.           "head_url": "https://i1.hdslb.com/bfs/face/b6a132c21e444401228099c8cc07edab810bc9db.jpg",
  27.           "name": "ZWPAN盼"
  28.         },
  29.         "item": {
  30.           "doc_id": 1085297,
  31.           "poster_uid": 21690338,
  32.           "pictures": [
  33.             {
  34.               "img_src": "https://i0.hdslb.com/bfs/album/2785de69bb019f85c88ee0d9681468c779e3950f.jpg",
  35.               "img_width": 3029,
  36.               "img_height": 9506,
  37.               "img_size": 6425
  38.             }
  39.           ],
  40.           "title": "108个小电视表情",
  41.           "category": "illustration",
  42.           "upload_time": 1512023535,
  43.           "already_liked": 0,
  44.           "already_voted": 0
  45.         }
  46.       },
  47. /////////////////////////////////////////
  48. /     {                                                                  /
  49. /     "_": "太多了,就不列举了"     /
  50. /     }                                                                  /
  51. /////////////////////////////////////////
  52.       ]
  53.   }
  54. }

  55. Response code: 200 (OK); Time: 490ms; Content length: 12879 bytes
复制代码
  • method:GET
  • params:

    • category
      图片的类型,选项如下

      • all:所有类型
      • illustration:插画
      • comic:漫画
      • draw:其他

    • type
      排名规则。选项如下:

      • hot:按热度排序
      • new:按时间排序

    • page_num
      页数,从0开始
    • page_size
      每页图片数

写爬虫
先在项目的根目录创建一个配置文件setting.py
  1. # picture settings

  2. PICTURE_MAX_PAGE = 20
  3. PICTURE_SLEEP_TIME = 0.5
  4. PICTURE_CATEGORY = "all"
  5. PICTURE_TYPE = "hot"
复制代码
  • PICTURE_MAX_PAGE
    爬的页数,每页20个
  • PICTURE_SELLP_TIME
    每爬一张图间隔的时间
  • PICTURE_CATEGORY
    要爬的图片的类型,选项如下

    • all:所有类型
    • illustration:插画
    • comic:漫画
    • draw:其他

  • PICTURE_TYPE
    排名规则。选项如下:

    • hot:按热度排序
    • new:按时间排序




打开bili/spider/picture.py

  1. 导入一些库
  2. import json
  3. import scrapy
  4. import time
  5. import setting
  6. from bili.items import BiliItem
复制代码
改写class PictureSpider(scrapy.Spider):
我们要先从https://h.bilibili.com/开始爬,从而免去设置Referer
  1. start_urls = ['https://h.bilibili.com/']
复制代码
再接着循环爬取刚才分析的链接即可,记住要构造请求并设置回调函数哦!
  1. def parse(self, response, **kwargs):
  2.     for i in range(setting.PICTURE_MAX_PAGE):
  3.         yield scrapy.Request(
  4.             'https://api.vc.bilibili.com/link_draw/v2/Doc/list?page_size=20'
  5.             '&type=' + setting.PICTURE_TYPE +
  6.             '&category=' + setting.PICTURE_CATEGORY +
  7.             '&page_num=' + str(i),
  8.             callback=self.picture_info,
  9.             dont_filter=True
  10.         )

  11. def picture_info(self, response, **kwargs):
  12.     data = json.loads(response.text)
  13.     for item in data["data"]["items"]:
  14.         img = BiliItem()
  15.         img["url"] = item["item"]["pictures"][-1]["img_src"]
  16.         img["title"] = item["item"]["title"]
  17.         img["id"] = item["item"]["doc_id"]
  18.         img["author"] = item["user"]["name"]
  19.         img["uid"] = item["user"]["uid"]
  20.         img["extension"] = img["url"].split('.')[-1]
  21.         yield img
  22.         time.sleep(setting.PICTURE_SLEEP_TIME)
复制代码
bili/spiders/picture.py完整代码
  1. import json
  2. import scrapy
  3. import time
  4. import setting
  5. from bili.items import BiliItem


  6. class PictureSpider(scrapy.Spider):
  7.     name = 'picture'
  8.     allowed_domains = ['bilibili.com']
  9.     start_urls = ['https://h.bilibili.com/']

  10.     def parse(self, response, **kwargs):
  11.         for i in range(setting.PICTURE_MAX_PAGE):
  12.             yield scrapy.Request(
  13.                 'https://api.vc.bilibili.com/link_draw/v2/Doc/list?page_size=20'
  14.                 '&type=' + setting.PICTURE_TYPE +
  15.                 '&category=' + setting.PICTURE_CATEGORY +
  16.                 '&page_num=' + str(i),
  17.                 callback=self.picture_info,
  18.                 dont_filter=True
  19.             )

  20.     def picture_info(self, response, **kwargs):
  21.         data = json.loads(response.text)
  22.         for item in data["data"]["items"]:
  23.             img = BiliItem()
  24.             img["url"] = item["item"]["pictures"][-1]["img_src"]
  25.             img["title"] = item["item"]["title"]
  26.             img["id"] = item["item"]["doc_id"]
  27.             img["author"] = item["user"]["name"]
  28.             img["uid"] = item["user"]["uid"]
  29.             img["extension"] = img["url"].split('.')[-1]
  30.             yield img
  31.             time.sleep(setting.PICTURE_SLEEP_TIME)
复制代码
下载图片
图片链接已经使用上面的picture_info()方法获取了,下面使用BiliPipeline管道下载图片
打开bili/pipelines.py
由于scrapy自带的图片下载器个人觉得使用起来太麻烦,这里直接用requests库就好
  1. import requests
  2. from os import path


  3. class BiliPipeline:
  4.     def process_item(self, item, spider):
  5.         name = str(item["id"]) + '.' + item["extension"]
  6.         res = requests.get(item["url"])
  7.         with open(path.join(path.join(path.abspath('.'), 'image'), name), 'wb') as file:
  8.             file.write(res.content)
  9.             print(name)
  10.         return item
复制代码
启用管道
打开bili/settings.py
找到以下内容并取消注释
  1. ITEM_PIPELINES = {
  2.    'bili.pipelines.BiliPipeline': 300,
  3. }
复制代码
在运行阶段为了减少不必要的log提示,可以在在里面添加
  1. LOG_LEVEL = "WARNING"
复制代码
本地启动爬虫测试启动爬虫
  1. # 切换到项目根目录
  2. scrapy crawl picture
复制代码
pycharm调试爬虫
点击右上角“编辑配置”
添加配置,选择python
配置如下
  • 脚本路径为python安装目录\Lib\site-packages\scrapy\cmdline.py
  • 参数为crawl 爬虫名
  • 工作目录为项目根目录

然后就可以愉快的打断点调试了   JetBrains NB
写workflows文件
在项目根目录创建:
  1. .github/workflows/blank.yml
复制代码
直接复制粘贴即可,有时间我会另写一篇入门GitHub Actions的文章,可能会鸽,咕咕咕。。。其实网上有很多这样的文章,例如:阮一峰的网络日志
  1. name: Spider

  2. on:
  3.   workflow_dispatch:

  4. jobs:
  5.   spider:
  6.     runs-on: ubuntu-latest
  7.     steps:
  8.     - name: checkout
  9.       uses: actions/checkout@master

  10.     - name: 'Set up Python'
  11.       uses: actions/setup-python@v1
  12.       with:
  13.         python-version: 3.7

  14.     - name: Run a single-line script
  15.       run: |
  16.         pip install requests
  17.         pip install lxml
  18.         pip install scrapy
  19.         scrapy crawl picture

  20.     - name: Upload artifact
  21.       uses: actions/upload-artifact@master
  22.       with:
  23.         name: img
  24.         path: image
复制代码
部署到GitHub Actions
在Github上新建仓库
将代码推送到该仓库里
Git三部曲:
  1. git add .                     # 添加
  2. git commit -m "init"        # 提交
  3. git push                        # 推送
复制代码
打开GitHub仓库网页
依次点击:
等待一小会,不出意外的话,爬虫的结果就显示出来了,点击下载即可
illust_81689532_20201227_014258.png

吐槽一句:1M的图太小啦,还要我传到自己的OSS上( ^ω^)




使用道具 举报

该用户从未签到

10

主题

51

回帖

404

积分

Judgement

积分
404
不出所料,对MarkDown和代码块的支持惨不忍睹:L:L:L

使用道具 举报

  • TA的每日心情

    2024-12-20 08:42
  • 签到天数: 1 天

    [LV.1]初来乍到

    69

    主题

    82

    回帖

    1093

    积分

    造物主

    站长

    积分
    1093
    QQ
    好耶,这比阿方厉害多了,
    世间漫随流水,算来一梦浮生

    使用道具 举报

  • TA的每日心情
    郁闷
    2024-11-22 16:10
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    19

    主题

    75

    回帖

    2168

    积分

    Judgement

    世界第一公主殿下

    积分
    2168
    QQ
    以最初的声音,追寻未来的梦

    使用道具 举报

    该用户从未签到

    6

    主题

    36

    回帖

    459

    积分

    LV.2

    积分
    459
    QQ

    使用道具 举报

    该用户从未签到

    0

    主题

    2

    回帖

    18

    积分

    LV.1

    积分
    18
    非常厉害的样子

    使用道具 举报

    该用户从未签到

    10

    主题

    87

    回帖

    416

    积分

    版主

    积分
    416
    QQ
    np!

    使用道具 举报

    该用户从未签到

    10

    主题

    87

    回帖

    416

    积分

    版主

    积分
    416
    QQ
    啊对了,请问一下,这个是python吗?我想学习这个,但是不知道该怎么学……

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册SCIFIFANS!

    本版积分规则