惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recent Announcements
Recent Announcements
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
博客园_首页
Last Week in AI
Last Week in AI
月光博客
月光博客
有赞技术团队
有赞技术团队
IT之家
IT之家
博客园 - Franky
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 三生石上(FineUI控件)
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
人人都是产品经理
人人都是产品经理
A
About on SuperTechFans
N
Netflix TechBlog - Medium
雷峰网
雷峰网
Recorded Future
Recorded Future
S
Securelist
C
CERT Recently Published Vulnerability Notes
Vercel News
Vercel News
F
Full Disclosure
C
Cybersecurity and Infrastructure Security Agency CISA
A
Arctic Wolf
Simon Willison's Weblog
Simon Willison's Weblog
L
LINUX DO - 热门话题
T
Tenable Blog
MongoDB | Blog
MongoDB | Blog
V
Visual Studio Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Jina AI
Jina AI
TaoSecurity Blog
TaoSecurity Blog
H
Hacker News: Front Page
D
DataBreaches.Net
Google DeepMind News
Google DeepMind News
T
The Exploit Database - CXSecurity.com
S
Security @ Cisco Blogs
W
WeLiveSecurity
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Darknet – Hacking Tools, Hacker News & Cyber Security
SecWiki News
SecWiki News

夜行人

回家路上 第一期的直播演示项目 震动检测器 正能量 在线参观CodeLab Neverland 发布 CodeLab Adapter 3.3.1 DynamicTable 之 纸糊方向盘 CodeLab DynamicTable: 一个可实施的技术方案 CodeLab Insight 发布 Alpha 版 情人节 Home Assistant 周报 && IoT 周报 (02) Joplin: 关注隐私的 Evernote 开源替代软件 浏览器的未来与 Web 传感器 Home Assistant 周报 && IoT 周报 (01) 百宝箱(01) 论自由 介绍 WebThings Home Assistant 周报 && iot 周报 (00) 百宝箱(00) 毛姆读书心得 传世之作 周末徒步 CodeLab Adapter ❤️ Jupyter/Python 航班 躲雨 夏令营途中 [译]思想--作为一种技术 The future of coding 美国之行 三门问题的程序模拟 从Python转向Pharo https://blog.just4fun.site/post/iot/iot-open-source-projects/ Python异步编程笔记 https://blog.just4fun.site/post/iot/iot-open-source-hardware-community/ 万物积木化开发者社区 CodeLab ❤️ Blender Scratch3技术分析之云变量 API(第7篇) [译]对管道(Pipes)的偏爱 [译]提出正确的问题比得到正确答案更重要 蓝牙设备与Scratch3.0 创建你的第一个Scratch3.0 Extension Scratch3技术分析之项目内部数据(第6篇) Scratch3技术分析之社区 API(第5篇) Scratch3技术分析之User API(第4篇) Scratch3技术分析之项目主页API(第3篇) Scratch3技术分析之静态资源API(第2篇) Scratch3.0、micro:bit与Windows7 https://blog.just4fun.site/post/iot/zerynth-vs-micropython/ 核聚变、方所与半宅空间 可视化编程为何是个糟糕的主意 codelab.club周末聚会 关于codelab.club '下一件大事'是一个房间 Hungry Robot - Eat everything 编程作为一种思考方式 今日简史 史蒂夫·乔布斯传 罗素自选文集 https://blog.just4fun.site/post/edx/tianjin-scratch-ai/ https://blog.just4fun.site/post/edx/richie-cms-openedx/ 徒步武功山 WebUSB与micro:bit 积木化编程与3D场景 夜宿武功山顶 scratch3-adapter接入优必选Alpha系列机器人 https://blog.just4fun.site/post/edx/video-migration-note/ scratch3-adapter重构笔记 https://blog.just4fun.site/post/edx/edx-community-members/ 两种硬件编程风格的比较 使用micro:bit自制PPT翻页笔 柏拉图对话集 scratch3.0 + micro:bit 七月电影放映计划 非营利组织的管理 Screenly--用树莓派让任何屏幕变为可编程的数字标牌 以最佳实践开始你的Django项目 micro:bit与事件驱动 为Scratch3.0设计的插件系统(上篇) OCR应用一例 近两年读过的一些好书 blockly开发之使用python驱动浏览器中的turtle(2) 牛顿新传 文学理论入门 逻辑的引擎 人生的意义 blockly开发之生成并运行js代码(1) blockly开发之hello world(0) micro:bit使用笔记 神器之Termux https://blog.just4fun.site/post/iot/micropython-notes/ Cozmo what is this Scratch的前世今生 下段旅程 我行在远方 爆裂 途中杂记 https://blog.just4fun.site/post/edx/open-edx-startup/ cozmo系列之入门 - 有性格且可编程的机器人 PaperWeekly开发笔记 创业二三事
用pyspider写的爬虫几例
2015-11-30 · via 夜行人

#爬虫 最初折腾爬虫还是在校期间,一个玩具项目,想把校内信息爬取下来,写一个小型校内搜索引擎,整合到公众号里

而后原理实现之后,就不想打磨细节了,急着跳入下一个坑。如那个笑话里的,程序员好不容易买齐了笔墨纸砚,写下hello world,就心满意足地离去了

去年在知乎里答过一个爬虫题目,拿了1000来个赞,陆陆续续收到一些私信问有没有兴趣换工作啥的,当时的百度和美团还是蛮有吸引力的,哎谁知一年多工夫,局势变了好多,看来拒绝的还算有先鉴之明。如pyspider作者binux所言,爬虫就那点东西,有趣的部分并不多,所以也从未考虑过此类工作。

闲暇时间,陆陆续续写过简易的几个爬虫玩具,帮朋友爬过1w枚种子,据说质量奇高,是xx中的艺术片。也爬过豆瓣知乎,数据拿来训练机器人。

说要种子的,我也不会给你啦,代码有毒,身体要紧啊同学们

写爬虫比较钟爱pyspider,选择器是jquery语法(用了pyquery),调试起来十分方便,而且又有web界面很是舒服

以下几个demo,需求都来自小伙伴。

#pyspider介绍 pyspider作者在在博客里说到

pyspider 来源于以前做的一个垂直搜索引擎使用的爬虫后端。我们需要从200个站点(由于站点失效,不是都同时啦,同时有100+在跑吧)采集数据,并要求在5分钟内将对方网站的更新更新到库中。

和大多开源项目一样,pyspider也始于作者自己真实的需求,而后发现这个解决方案对于其他人也是适用的,于是开源出来。正是自己最初真实的需求,使项目在细节方面十分周到贴心

十分推荐有兴趣的小伙伴把作者博客里的几篇文章读完:Binuxの杂货铺

这是关于爬虫方面我读过最简易清晰的几篇文章了

#安装 ##mac下安装与运行

1
2
3
4
5
6
virtualenv env #使用virtualenv建立虚拟环境
source env/bin/activate
pip install pyspider
brew install phantomjs #运行js的环境(ajax)
pyspider phantomjs #开启服务在25555端口
pyspider

##使用docker安装

1
2
docker pull binux/pyspider:master
sudo docker run -d -p 5000:5000 -v /opt/pyspider:/opt/pyspider binux/pyspider:master

之后在5000端口上就可以写爬虫逻辑啦,web本身作为控制面板

参考Running-pyspider-with-Docker

#demo ###1 爬取豆瓣8分以上书籍

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2015-09-17
# Project: douban_book

from pyspider.libs.base_handler import *
import re

class Handler(BaseHandler):
    crawl_config = {
    }

    def on_start(self):
        self.crawl('http://book.douban.com/tag/', callback=self.index_page)

    def index_page(self, response):
        for each in response.doc('a[href^="http"]').items():
            if re.match(r"http://www.douban.com/tag/\w+", each.attr.href, re.U):
                #print each.attr.href
                #romantic novels tag :  http://www.douban.com/tag/%E8%A8%80%E6%83%85/?focus=book
                self.crawl(each.attr.href , callback=self.list_page)

    def list_page(self, response):
        #print re.search(r'http://www.douban.com/tag/[^/]*',response.url ,).group() + '/book'
        self.crawl(re.search(r'http://www.douban.com/tag/[^/]*',response.url ,).group() + '/book', callback=self.list_page_detail)
    
    def list_page_detail(self, response):
        for each in response.doc('a[href^="http"]').items():
            if re.match(r'http://book.douban.com/subject/\d+',each.attr.href):
                self.crawl(each.attr.href, callback=self.page_detail)
        for each in response.doc('.next > a').items():
            #print each.attr.href
            self.crawl(each.attr.href, callback=self.list_page_detail)
    
    def page_detail(self, response):
        vote_average = response.doc('strong[property="v:average"]').text()
        if float(vote_average) >= 8:
            return {
              "url":re.search(r'http://book.douban.com/subject/\d+',response.url).group(),
              "title":response.doc('h1 > span').text(),
              "vote_average":response.doc('strong[property="v:average"]').text(),
              "vote_num":response.doc('span[property="v:votes"]').text()
            }

###demo2 爬取京东众筹数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2015-11-30
# Project: jdzc

from pyspider.libs.base_handler import *
import re

class Handler(BaseHandler):
    crawl_config = {
    }



    def on_start(self, response):
        #手动输入最大页面,这部分有ajax很烦 手写吧
        #max_page = response.doc('a.next')
        #print max_page
        max_page=218 #当前是218,有了phantomjs后可以自动获取
        for page_num in range(1,max_page):
            self.crawl('http://z.jd.com/bigger/search.html?'+str(page_num), callback=self.enter_item, method='POST', data={'sort': "zhtj", 'page': str(page_num)})
        
    
    def enter_item(self, response):
        #print response.doc(".lr-lists .link-pic")
        for each in response.doc(".lr-lists .link-pic").items():
                self.crawl(each.attr.href, fetch_type='js',callback=self.item_detail)
    
    def item_detail(self, response):
        
        item_name = response.doc('.project-tilte > h1').text() #项目名称
        item_owner = response.doc('.font18 > a').text()#项目发起人
        item_status = response.doc('.icon_pag').text() #项目状态
        #item_begintime =  response.doc('div.font14 > .lh24 > span:first').text()#发起日期,只有筹款中的才有发起日期,完成的没有
        item_deadline =  response.doc('div.font14 > .lh24 > span').eq(0).text()#截止日期
        item_target_fundraising = response.doc('div.font14 > .lh24 > span').eq(1).text() #众筹目标
        item_real_fundraising = response.doc('.font45').text() #已筹款数
        supporter_num = response.doc('.pr > p > strong').text() #支持人数
        topic_num = response.doc('#topicBtn > span').text() #话题数,需要执行完js才得到,所以需要phantomjs
        return {
              "item_name":item_name,
              "item_owner":item_owner,
              "item_status":item_status,
              "item_deadline":item_deadline,
              "item_target_fundraising":item_target_fundraising,
              "item_real_fundraising":item_real_fundraising,
              "supporter_num":supporter_num
            }

###demo3 爬取知乎指定用户收藏夹

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2015-03-24 21:56:49
# Project: zhihu_collection

from pyspider.libs.base_handler import *


class Handler(BaseHandler):
    crawl_config = {}

    @every(minutes=24 * 60)
    def on_start(self):
        start_url = "http://www.zhihu.com/people/liu-shi-jiu-84/collections"
        self.crawl(start_url, callback=self.index_page )

    @config(age=10 * 24 * 60 * 60)
    def index_page (self, response):
         for each in response.doc(".zm-profile-fav-item-title").items():
             collection_name = each.text()
             self.crawl(each.attr.href, callback=self.all_answer_pages,save={"collection_name":collection_name})

    def all_answer_pages(self,response):
         pages= response.doc(".border-pager a")
         max_pages = int(pages[-2].text) #倒数第二个, 最大页数
         all_collections_pages = [str(response.url)+"?page="+str(page) for page in range(1,max_pages+1)]
         for url in all_collections_pages:
             print url
             self.crawl(url, callback=self.collection_page,save={"collection_name":response.save["collection_name"]})

    def collection_page(self, response):
         for each in response.doc(".toggle-expand").items():
             self.crawl(each.attr.href, callback=self.detail_page,save={"collection_name":response.save["collection_name"]})

    @config(priority=2)
    def detail_page(self, response):
        return {
             "collection_name":response.save["collection_name"],
             "url": response.url,
             "title": response.doc("title").text(),
             "body":response.doc('.autohide-false .zm-item-rich-text > div').text()}
             

#附录

###Ubuntu 12.04 64bit 安装PhantomJS

1
2
3
4
5
6
sudo wget https://phantomjs.googlecode.com/files/phantomjs-1.9.0-linux-x86_64.tar.bz2
sudo tar xjf phantomjs-1.9.0-linux-x86_64.tar.bz2
sudo ln -s /usr/local/share/phantomjs-1.9.0-linux-x86_64/bin/phantomjs /usr/local/share/phantomjs; 
sudo ln -s /usr/local/share/phantomjs-1.9.0-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs;
sudo ln -s /usr/local/share/phantomjs-1.9.0-linux-x86_64/bin/phantomjs /usr/bin/phantomjs
phantomjs --version

文章作者 种瓜

上次更新 2015-11-30