描述

pirate 是由我的 django 脚手架 original 实现的,文件上传提供了七牛和腾讯云两个 backend,部署提供了默认的配置文件,因此只要关注具体的微信的抓取逻辑即可。

核心表讲解

pirate/original/extracter/models.py

微信文章表,正常设计,大字段拆表。

13 class WXArticle(TimeStampedModel):

14 raw_url = models.CharField(max_length=1023)

15 title = models.CharField(max_length=255)

16 cover = models.CharField(max_length=255)

17 description = models.CharField(max_length=255, default='')

18 is_active = models.BooleanField(default=False)

19 is_delete = models.BooleanField(default=False)

98 class WXArticleContent(TimeStampedModel):

99 article_id = models.IntegerField(unique=True)

100 content = models.TextField()

101 body_script = models.TextField(default='')

pirate/original/extracter/models.py

图片上传缓存表,因为有时候会重复抓取一篇文章(例如编辑后需要重新写文章),而每次抓取文章时会将里面的图片上传到我们的 cdn,添加上传文件缓存表来减少重复的图片上传操作。

188 class URLFileUploadCache(TimeStampedModel):

189 raw_url = models.CharField(blank=True, default='', max_length=512)

190 url = models.CharField(blank=True, default='', max_length=255)

191 raw_url_md5 = models.CharField(blank=True, default='', max_length=64, db_index=True)

抓取

观察微信文章发现,文章 div id=js_content 为文章正文,其中标题和 cover 图在 meta 里面,使用 requests 抓取文章原文,BeautifulSoup 过滤需要的 dom,正则找出需要替换的图片,upload_handler 选择七牛去上传图片并且替换掉原图地址。

21 @classmethod

22 def spider_url(cls, raw_url):

23 assert raw_url.startswith('https://mp.weixin.qq.com/') or raw_url.startswith('http://mp.weixin.qq.com/')

24 content = tools.spider_request(raw_url)

25 description = content_text = title = cover = ''

26 body_script = ''

27 if content:

28 b = BeautifulSoup(content, 'html.parser')

29 content_dom = b.find('div', id='js_content')

30 title_dom = b.find('meta', property="og:title")

31 cover_dome = b.find('meta', property="og:image")

32 if title_dom:

33 title = title_dom.attrs['content']

34 if cover_dome:

35 cover = cover_dome.attrs['content']

36 raw_url = cover

37 upload_cache = URLFileUploadCache.get_cached_objects(raw_url, get_last=True)

38 if upload_cache:

39 cover = upload_cache[0].url

40 else:

41 upload_data = tools.upload_file_from_url(raw_url)

42 url = upload_data['url']

43 if url:

44 URLFileUploadCache.new_cache(raw_url, url)

45 cover = url

46 if content_dom:

47 content_text = unicode(content_dom)

48 ss = b.body.find_all('script')

49 body_script = ''.join(unicode(s) for s in ss)

50 urls = []

51 for _re in constants.WEIXIN_IMAGE_RES:

52 urls.extend(_re.findall(content_text))

53 descriptions = constants.WEIXIN_DESCRIPTION_RE.findall(content)

54 if descriptions:

55 description = BeautifulSoup(descriptions[0]).meta.attrs.get('content', '')

56 mapper = {}

57 for raw_url in urls:

58 if raw_url in mapper:

59 continue

60 upload_cache = URLFileUploadCache.get_cached_objects(raw_url, get_last=True)

61 if upload_cache:

62 mapper[raw_url] = upload_cache[0].url

63 else:

64 upload_data = tools.upload_file_from_url(raw_url, )

65 url = upload_data['url']

66 if url:

67 URLFileUploadCache.new_cache(raw_url, url)

68 mapper[raw_url] = url

69 for raw_url, url in mapper.iteritems():

70 if not url:

71 continue

72 content_text = content_text.replace(raw_url, url)

73 return {

74 'raw_url': raw_url,

75 'title': title,

76 'cover': cover,

77 'content': content_text,

78 'description': description,

79 'body_script': body_script,

80 }

上传文件到七牛的 upload_handler

13 POLICY = settings.FILE_CALLBACK_POLICY or {

14 'callbackUrl': settings.FILEUPLOAD_CALLBACK_URL,

15 'callbackBody': 'bucket=$(bucket)&key=$(key)&filename=$(fname)&filesize=$(fsize)',

16 'insertOnly': 1,

17 }

18

19

20 class UploadHandler(object):

21

22 def __init__(self, key, secret, bucket):

23 self.key = key

24 self.secret = secret

25 self.bucket = bucket

26 self.backend = qiniu

27 self._backend_auth = Auth(self.key, self.secret)

28

29 def _upload_token(self, key, expires=3600, policy=None):

30 token = self._backend_auth.upload_token(self.bucket, key=key, expires=expires, policy=policy)

31 return token

32

33 def upload_file(self, key, data, policy=None, fname='file_name'):

34 if policy is None:

35 policy = POLICY

36 uptoken = self._upload_token(key, policy=policy)

37 return self.backend.put_data(uptoken, key, data, fname=fname)

38

39 def get_download_url(self, key):

40 return '{}{}'.format(settings.FILE_DOWNLOAD_PREFIX, key)

CDN 配置

创建一个公开的存储空间,名字即 FILE_UPLOAD_BUCKET

为了让域名好看一些,配置 CDN 加速域名,根据步骤操作即可(有一些 dns 的操作)。FILE_DOWNLOAD_PREFIX

个人中心秘钥管理获取 upload_handler 需要的 FILE_UPLOAD_KEY、FILE_UPLOAD_SECRET

执行部署

创建对应 mysql 数据库

创建 virtualenv,source 后 pip install 项目路径下的 requirements/base.txt

创建 config/settings/private_production.py,见下面代码段

数据库 migrate,cd 到 original 目录,执行./manage.py migrate --settings=config.settings.production

启动项目 ./manage.py runserver 0.0.0.0:8976 (端口号随意)

当然建议用 supervisor + nginx,见deploy目录下的相关例子

import os

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.mysql',

'NAME': 'dbname', # 改成你的数据库名字

'HOST': os.environ.get('ORIGINAL_MYSQL_HOST', 'localhost'), # 数据库host

'USER': os.environ.get('ORIGINAL_MYSQL_USER', 'db_username'), # 改成你的数据库user

'PASSWORD': os.environ.get('ORIGINAL_MYSQL_PASSWORD', 'db_password'), # 改成你的数据库password

'PORT': os.environ.get('ORIGINAL_MYSQL_PORT', 3306),

'OPTIONS': {'charset': 'utf8mb4'},

}

}

FILE_UPLOAD_BACKEND = 'qiniu'

FILE_UPLOAD_KEY = 'i6fdSECQjLfF' # 改成你的qiniu key,现在这里是假的

FILE_UPLOAD_SECRET = 'adfiuerqp' # 改成你的qiniu secret

FILE_UPLOAD_BUCKET = 'reworkdev' # 改成你的qiniu bucket

FILE_CALLBACK_POLICY = {}

FILE_DOWNLOAD_PREFIX = '' # 改成你的host, 例如 http://cdn.myhost.com/

FILEUPLOAD_CALLBACK_URL = # 改成你自己host的对应地址, 例如 https://www.myhost.com/api/v1/file/upload/callback/

postman 测试接口

查看数据库

接下来

基本物料接口准备就绪,下面就可以正式开始 Java 框架的学习。

python中接口测试垃圾数据如何清理_一个六年经验的python后端是怎么学习用java写API的(2)Extracter,微信文章抓取清洗入库...相关推荐

  1. python中接口测试垃圾数据如何清理_巧用PyUnit中unittest特性解决接口测试产生脏数据问题...

    巧用PyUnit中unittest特性解决接口测试产生脏数据问题 一.背景 测试数据创建后需要对其删除,不然可能产生脏数据,对开发和测试.生产环境造成一定影响.其接口框架是基于Python,API规范 ...

  2. python中接口测试垃圾数据如何清理_接口测试---Python数据处理需要注意的细节

    一.json模块中的dumps方法 请求接口时params肯定是dict类型的,就是这种{"A":"B"},因为需要传json格式的参数到服务端,但是为了降低c ...

  3. python中接口测试垃圾数据如何清理_Python接口测试题(持续更新中)

    1.json和字典的区别? Json是轻量级的数据交互格式,以key-value的键值对形式来保存数据,结构清晰,可以说是目前互联网项目开发中最常用的一种数据交互格式. 字典,同样是以key-valu ...

  4. python后端需要什么基础_一个六年经验的python后端是怎么学习用java写API的(6) 基本的Auth...

    描述 实现了依赖注入之后就可以方便的实现各种API的业务逻辑了,下一部的问题就在于权限,我们知道大部分的系统API并不是开放的,需要基本的用户体系(注册.登录.购买.会员.不同的role等等),例如管 ...

  5. python两个字符串数据可以复制吗_无论如何,是否要将Python pandas数据框中的单个数据中的数据复制到字符串或列表中以进行进一步处理?...

    使用示例数据.请注意,由于复制和粘贴选项卡占用空格(因此使用sep ='\ s +',iso'\ t')并且我已将数据的第一行设置为列名(不使用header = None).可以使用join将一列连接 ...

  6. python中的库有哪些餐厅_推荐一些实用的的 Python 库

    Python Python开发 Python语言 推荐一些实用的的 Python 库 一门语言好用.方便的程度在很多时候会取决于这门语言相关的库够不够丰富,Python 之所以火爆除了其本身的语法和特 ...

  7. python中使用什么命令安装组件_在离线环境下安装python组件

    在一些项目中,我们会不可避免地使用到python组件,而生产环境大多数服务器是没有办法直接联网下载python的包的.当然,有的小伙伴会很聪明地把这个包的whl下载下来到服务器上去执行,但是会得到这样 ...

  8. python中csv库的writer函数_指定格式csv.writer在Python中

    我正在使用csv.DictWriter从一组词典输出csv文件.我使用以下函数:def dictlist2file(dictrows, filename, fieldnames, delimiter= ...

  9. python类型转换-Python中如何进行数据类型转换?

    原标题:Python中如何进行数据类型转换? 这一次要讲的是Python中的数据类型转换,Python中的数据类型转换是什么?就是将数据由当前类型变化为其他类型的操作就是数据类型转换.数据类型转换分为 ...

最新文章

  1. zookeeper java.env_zookeeper在生产环境中的配置(zookeeper3.6)
  2. .NET中,字符串首字母大写的方法
  3. Ubuntu 12.04 Server 搭建DNS服务器
  4. git 本地仓库同时推送到多个远程仓库
  5. 现代软件工程系列 学生和老师都不容易
  6. Oracle数据库中的dual表
  7. php如何安装mysql模块,linux安装php 模块--with-mysql --with-mysqli非得需要安装mysql吗汗血宝马...
  8. android input 点击事件失效,React Native:TextInput元素上的onContentSizeChange事件在Android上不起作用...
  9. Java的值类型(基本类型)和引用类型
  10. 权力的游戏登录显示服务器上限,权力与纷争登录不上怎么办 登录不上解决方案...
  11. linux抓包-tcpdump
  12. 技嘉主板bios设置方法
  13. Python实现BT种子转化为磁力链接
  14. 百度地图API基本使用(二)
  15. Android动态获取权限(读写、获取手机状态、定位)
  16. excel文档文件加密的方法步骤
  17. 一个控制键盘远程控制多台视频会议摄像机(转自搜狐)
  18. 常见外包公司(非全部)
  19. vue使用d3数据可视化(柱状图、饼图、折线图 带坐标轴)
  20. position定位的属性

热门文章

  1. 图像识别中的深度学习【香港中文大学王晓刚】
  2. 伪共享(false sharing),并发编程无声的性能杀手
  3. JAVA NIO之文件通道
  4. sql必知必会(第四版) 学习笔记一
  5. 聊聊Java的泛型及实现
  6. 从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
  7. 用JavaScript玩转计算机图形学(二)基本光源
  8. 【数字智能三篇】之二: 一页纸说清楚“什么是推荐系统?”
  9. 您能看出这个生成缩略图的方法有什么问题吗?
  10. 编程之美-找到符合条件的整数