爬虫中最常常遇到的问题就是 咱们须要对不一样的网站上的内容进行抓取,可是抓取到的内容结构都是同样的,后续处理也是同样的,只是不一样网站上展现咱们要的内容的方式是不同的,须要咱们对各个网站逐一分析,构建须要的适配器去处理python
为了更通用地取匹配多个须要下载的网站,咱们一般须要使用适配器,主程序中调用相同的方法,却能够对不一样的网站进行下载。git
实现适配器的方法有多种,这里由于没有用class,就简单的使用 importlib 中的 import_module 方法,也能够实现咱们须要的功能github
最简单实现:json
先创建一个文件夹 extractors,里面创建三个文件: __init__.py, baisi.py, qiubai.py数据结构
__init__.py 不用写代码app
baisi.py:ide
def TransferPageToData_baisi(url): print('baisi', url) transfer = TransferPageToData_baisi
qiubai.py函数
def TransferPageToData_qiubai(url): print('qiubai', url) transfer = TransferPageToData_qiubai
而后将咱们的main.py 修改为以下:网站
# coding: utf-8 from pyquery import PyQuery as pq from utils.common import GetMedia, GetPage from importlib import import_module SITES = { 'qiubai': 'http://www.qiushibaike.com/', 'baisi': 'http://www.budejie.com/' } def AnyTransfer(key, sites=SITES): m = import_module('.'.join(['extractors', key])) url = sites[key] m.transfer(url) def main(): for (k, v) in SITES.items(): AnyTransfer(k) if __name__ == '__main__': main()
而后咱们运行url
$ python3 main.py
获得结果
其实咱们这一种实现方式的关键就是 :
extractors里面的适配器都返回一样的数据结构(上面咱们只是print, 待会咱们返回都是json 的list)
利用transfer = XXXX 最后返回统一的函数名
在主函数中 利用 m = import_module('.'.join(['extractors', key])) 直接得到模块,而后调用模块的transfer函数
这里咱们简单的直接用 dict的key直接去配对咱们的module了,若是更好一些能够对url正则去判断适配哪一个适配器,这里不作扩展,感兴趣的朋友能够去看看you-get的实现方式
最后咱们加入对各网站的解析,并返回一个list
baisi.py
from pyquery import PyQuery as pq from utils.common import (GetMedia, GetPage) def TransferPageToData_baisi(url): page = GetPage(url) results = [] d = pq(page) contents = d("div .g-mn .j-r-c .j-r-list ul li .j-r-list-c") for item in contents: i = pq(item) content = i("div .j-r-list-c-desc").text().strip() video_id = i("div .j-video-c").attr('data-id') pic_id = i("div .j-r-list-c-img img").attr('data-original') if video_id: print('video: ' + video_id) video_des = i("div .j-video").attr('data-mp4') video_path = GetMedia(video_des, media_type='video') dct = { "content": content, "id": video_id, "type": "video", "mediapath": video_path } results.append(dct) elif pic_id: print('pic: ' + pic_id) pic_path = GetMedia(pic_id) dct = { "content": content, "id": pic_id, "type": "pic", "mediapath": pic_path } results.append(dct) return results transfer = TransferPageToData_baisi
qiubai.py
from pyquery import PyQuery as pq from utils.common import (GetMedia, GetPage) def TransferPageToData_qiubai(url): page = GetPage(url) results = [] d = pq(page) contents = d("div .article") for item in contents: i = pq(item) pic_url = i("div .thumb img").attr.src content = i("div .content").text() qiubai_id = i.attr.id print("qiubai:", qiubai_id) if pic_url: pic_path = GetMedia(pic_url) dct = { 'id': qiubai_id, 'type': 'pic', 'mediapath': pic_path, 'content': content } else: dct = { 'id': qiubai_id, 'type': 'text', # 'mediapath': '', 'content': content } results.append(dct) return results transfer = TransferPageToData_qiubai
main.py
# coding: utf-8 from importlib import import_module __author__ = 'BONFY CHEN <foreverbonfy@163.com>' SITES = { 'qiubai': 'http://www.qiushibaike.com/', 'baisi': 'http://www.budejie.com/' } def AnyTransfer(key, sites=SITES): m = import_module('.'.join(['extractors', key])) url = sites[key] results = m.transfer(url) return results def PrepareData(): results = [] for (k, v) in SITES.items(): results = results + AnyTransfer(k) return results def main(): print(PrepareData()) if __name__ == '__main__': main()
运行获得结果
详情见 https://github.com/bonfy/xiaolinBot
敬请期待下一讲 数据存储Mongodb
若是你们以为有用,也请不要吝啬Star 和 Like哦~