这一晃,就又是一年

花了一年的时间,换来了什么?

不知道自己有没有真正的进步。

暑假找了份自己喜欢的工作,工资不高,我很满足。但想着未来,压力还是很大。

学习了很多 ES6 的东西,react + redux 也比较顺手了,现在走出去可以好意思说自己是 fullstack web 了。

Elixir 是个不错的语言,很有可能是未来。

9月份开始还有三门课,希望下个学期能够结束研究生的课程。

喜欢创业的状态,穷、苦逼,但是爽、刺激,可以发挥自己,很难想象自己去央企之类的地方工作。

Python 也在继续写,重构了自己以前写的论坛程序,托管在 GitHub

设计了一个新的个人主页,花了很长时间,最后干脆在首页只保留自己的名字,其他全部隐藏。Bold like me! 点此欣赏:http://shenli.me

一年前写了几篇 Django 爬虫方面的文章,很多人要求出续集。我本来是打算搞个直播的,无奈国内的平台都要各种认证,不好玩。

希望自己的人生可以再精彩一点。希望自己可以发现和遇见世上更多的美好。

愿世界和平。

PS: 感觉 WordPress 这一年下来还是有进步,但是感觉社区不如以前活跃了?

2015年第一次诈尸

诈尸原因:把博客搬家了,一不小心进了后台,突然想干点什么事情。

What’s up:

把博客放到了 scaleway 提供的 ARMv7 架构的服务器上。说起来也算是个独立服务器。 性能只能算可以接受,但是我很喜欢这种 SoC 云的体验。scaleway 提供了完整的 API 接口,关于服务器的一切设置都可以通过 API 来操作。硬盘、IP、芯片分开收费,并且可以任意组合。3欧的价格也是可以接受的。

但是,毕竟 ARM 在服务器领域还是比较年轻,有一些东西没有官方的 ARMhf 支持我还真搞不定,比如 MongoDB 等。但是对于普通的 PHP-*+MySQL+Nginx(+Apache) 应用还是完全没问题的。 这台服务器放了几个 WordPress 博客,基本上没什么压力。毕竟是没有流量的站点。

说起流量,最近终于有站能每天 IP 过 10k 了。 对于本资深但是长期没流量的站长倒是一种挑战,有机会学习实践了一些服务器优化方面的东西,Flask+MongoDD 的坑也踩了不少,另外还用 Cython 实现了一些加速。至于分布式、均衡负载这些东西还真没到需要的程度。

我还是认为,一般情况下,对于以赚钱为目的的网站,服务器的性能问题都是盈利模式的问题。如果不是为了赚钱,那一切的投入都算是为了情怀、为了公会、为了部落、为了 「to make the world a better place」。 可是到了这个年龄没钱还谈梦想和情怀会真的觉得承重,每一个选择也变得更加艰难。

虽然如此,我还是选择坚持 coding,这是我从小的爱好。最近还是继续写写 Python,主要还是 WEB 方面,另外还有自己课程相关的有限元、结构稳定性分析和岩土工程方面的东西。研究生的课说实话很累的。

上周搞了一个超级简单的 Python 爬虫方面的库,算不上框架,但是可以让写爬虫变得更简单。地址:https://github.com/ericls/gspider 。

import 个 BaseSpider 和 几个 xxField 就可以了

class PythonDocSpider(BaseSpider):

    title = PQField('h1', format='text')
    content = PQField('p')
    functions = PQListField('dl.function', format='element')


b = PythonDocSpider(
    'https://docs.python.org/3/library/base64.html#module-base64'
)
print(b.title, b.content)

看看上面这个代码,基本上就应该清楚怎么用了。 当然 也可以自定义爬虫的 property 等, 可能我会写个 readme 给 repo。这东西我打算长期更新,毕竟自己经常用。

三个月前搞了一个图床好像也没在博客上面发过,借此机会发个地址:https://github.com/ericls/tushe

如果真的有人看这篇文章,那eRic在此祝你国庆快乐。

愿世界和平。

October 5, 2015

Python爬虫建站入门手记——从零开始建立采集站点(三:采集入库)

上回,我已经大概把爬虫写出来了。

我写了一个内容爬虫,一个爬取tag里面内容链接的爬虫其实还差一个,就是收集一共有哪些tag的爬虫。但是这里先不说这个问题,因为我上次忘了 这次又不想弄。。还有个原因:如果实际采集的话,直接用http://segmentfault.com/questions/newest?page=1这个链接 获取所有问题,挨个爬就行。

进入正题

第三部分,采集入库。

3.1 定义数据库(or model or schema)

为了入库,我需要在Django定义一个数据库的结构。(不说nosql和mongodb(也是一个nosql但是很像关系型)的事)

还记得那个名叫web的app么,里面有个叫models.py的文件,我现在就来编辑它。

vim ~/python_spider/web/models.py

内容如下:

# -*- coding: utf-8 -*-
from django.db import models

# Create your models here.


class Tag(models.Model):
    title = models.CharField(max_length=30)

    def __unicode__(self):
        return self.title


class Question(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    tags = models.ManyToManyField(Tag, related_name='questions')
    sf_id = models.CharField(max_length=16, default='0') # 加上这个可以记住问题在sf的位置,方便以后更新或者其他操作
    update_date = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return self.title


class Answer(models.Model):
    question = models.ForeignKey(Question, related_name='answers')
    content = models.TextField()

    def __unicode__(self):
        return 'To question %s' % self.question.title

都很直白,关于各个field可以看看 Django 的文档

Continue reading “Python爬虫建站入门手记——从零开始建立采集站点(三:采集入库)”

Python爬虫建站入门手记——从零开始建立采集站点(二:编写爬虫)

NOTE:文章在SegmentFault同步更新 http://segmentfault.com/blog/eric/1190000002544142

 

上回,我装了环境

也就是一对乱七八糟的东西

装了pip,用pip装了virtualenv,建立了一个virtualenv,在这个virtualenv里面,装了Django,创建了一个Django项目,在这个Django项目里面创建了一个叫做web的阿皮皮。

接上回~

第二部分,编写爬虫。

工欲善其事,必先利其器。

apt-get install vim # 接上回,我们在screen里面是root身份哦~

当然了,现在我要想一个采集的目标,为了方便,我就选择segmentfault吧,这网站写博客不错,就是在海外上传图片有点慢。

这个爬虫,就像我访问一样,要分步骤来。 我先看到segmentfault首页,然后发现里面有很多tags,每个tags下面,才是一个一个的问题的内容。

所以,爬虫也要分为这几个步骤来写。 但是我要反着写,先写内容爬虫,再写分类爬虫, 因为我想。

2.1 编写内容爬虫

首先,给爬虫建立个目录,在项目里面和app同级,然后把这个目录变成一个python的package

mkdir ~/python_spider/sfspider
touch ~/python_spider/sfspider/__init__.py

以后,这个目录就叫爬虫包了

在爬虫包里面建立一个spider.py用来装我的爬虫们

vim ~/python_spider/sfspider/spider.py

一个基本的爬虫,只需要下面几行代码:
532442546-54d6dd0585a19_articlex

(代码下面会提供)

然后呢,就可以玩玩我们的“爬虫”了。

进入python shell

>>> from sfspider import spider
>>> s = spider.SegmentfaultQuestionSpider('1010000002542775')
>>> s.url
>>> 'http://segmentfault.com/q/1010000002542775'
>>> print s.dom('h1#questionTitle').text()
>>> 微信JS—SDK嵌套选择图片和上传图片接口,实现一键上传图片,遇到问题

看吧,我现在已经可以通过爬虫获取segmentfault的提问标题了。下一步,为了简化代码,我把标题,回答等等的属性都写为这个蜘蛛的属性。代码如下

# -*- coding: utf-8 -*-
import requests # requests作为我们的html客户端
from pyquery import PyQuery as Pq # pyquery来操作dom


class SegmentfaultQuestionSpider(object):

    def __init__(self, segmentfault_id): # 参数为在segmentfault上的id
        self.url = 'http://segmentfault.com/q/{0}'.format(segmentfault_id)
        self._dom = None # 弄个这个来缓存获取到的html内容,一个蜘蛛应该之访问一次

    @property
    def dom(self): # 获取html内容
        if not self._dom:
            document = requests.get(self.url)
            document.encoding = 'utf-8'
            self._dom = Pq(document.text)
        return self._dom

    @property 
    def title(self): # 让方法可以通过s.title的方式访问 可以少打对括号
        return self.dom('h1#questionTitle').text() # 关于选择器可以参考css selector或者jquery selector, 它们在pyquery下几乎都可以使用

    @property
    def content(self):
        return self.dom('.question.fmt').html() # 直接获取html 胆子就是大 以后再来过滤

    @property
    def answers(self):
        return list(answer.html() for answer in self.dom('.answer.fmt').items()) # 记住,Pq实例的items方法是很有用的

    @property
    def tags(self):
        return self.dom('ul.taglist--inline > li').text().split() # 获取tags,这里直接用text方法,再切分就行了。一般只要是文字内容,而且文字内容自己没有空格,逗号等,都可以这样弄,省事。

然后,再把玩一下升级后的蜘蛛。

>>> from sfspider import spider
>>> s = spider.SegmentfaultQuestionSpider('1010000002542775')
>>> print s.title
>>> 微信JS—SDK嵌套选择图片和上传图片接口,实现一键上传图片,遇到问题
>>> print s.content
>>> # [故意省略] #
>>> for answer in s.answers
        print answer
>>> # [故意省略] #
>>> print '/'.join(s.tags)
>>> 微信js-sdk/python/微信开发/javascript

OK,现在我的蜘蛛玩起来更方便了。

2.2 编写分类爬虫

下面,我要写一个抓取标签页面的问题的爬虫。

代码如下, 注意下面的代码是添加在已有代码下面的, 和之前的最后一行之间 要有两个空行

class SegmentfaultTagSpider(object):

    def __init__(self, tag_name, page=1):
        self.url = 'http://segmentfault.com/t/%s?type=newest&page=%s' % (tag_name, page)
        self.tag_name = tag_name
        self.page = page
        self._dom = None

    @property
    def dom(self):
        if not self._dom:
            document = requests.get(self.url)
            document.encoding = 'utf-8'
            self._dom = Pq(document.text)
            self._dom.make_links_absolute(base_url="http://segmentfault.com/") # 相对链接变成绝对链接 爽
        return self._dom


    @property
    def questions(self):
        return [question.attr('href') for question in self.dom('h2.title > a').items()]

    @property
    def has_next_page(self): # 看看还有没有下一页,这个有必要
        return bool(self.dom('ul.pagination > li.next')) # 看看有木有下一页

    def next_page(self): # 把这个蜘蛛杀了, 产生一个新的蜘蛛 抓取下一页。 由于这个本来就是个动词,所以就不加@property了
        if self.has_next_page:
            self.__init__(tag_name=self.tag_name ,page=self.page+1)
        else:
            return None

现在可以两个蜘蛛一起把玩了,就不贴出详细把玩过程了。。。

>>> from sfspider import spider
>>> s = spider.SegmentfaultTagSpider('微信')
>>> question1 = s.questions[0]
>>> question_spider = spider.SegmentfaultQuestionSpider(question1.split('/')[-1])
>>> # [故意省略] #

想做小偷站的,看到这里基本上就能搞出来了。 套个模板 加一个简单的脚本来接受和返回请求就行了。

未完待续。

下一篇,采集入库!

Python爬虫建站入门手记——从零开始建立采集站点(一:环境搭建)

从今天起,我将在这里更新一个系列的python简单爬虫到建立网站的实践手记

内容将会从最简单的开始,环境搭建,基本爬虫,入库,用Django建立可供用户访问的网站,网站部署。

同时打算涉及简单的异步爬虫,piplibe,队列等等。

为了方便,将使用django和sqlite3来作为例子, 虽然有时候这并不是最合适的场景。。

最终目的:一个能用的自动更新的垃圾站

本系列尽可能详细。

下面进入正题。

第一部分,买VPS,装环境。

本文的一切操作都在vps上

在Runabove建立最便宜的instance.

RunAbove1

选择魁省机房-Sandbox-M-Ubuntu14.10-输入Instace名字”PythonSpider”-FireUp!

不出一分钟,VPS就建立好了。
RunAbove2

用SSH 连接服务器
SSH1

先建立一个screen,顺手更新apt-get,以后都在这里面操作,避免掉线导致任务中断。


screen -S spider # 取名叫spider的screen
sudo apt-get update
sudp apt-get upgrade

再顺手安装一些肯定会用的东西

sudo apt-get install gcc python-dev -y
sudo - #这一步以后,用户就是root了 记住
nginx=stable # use nginx=development for latest development version
add-apt-repository ppa:nginx/$nginx
apt-get update
apt-get install nginx -y
apt-get install libxml2-dev libxslt1-dev lib32z1-dev -y

装pip和virtualenv

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py
pip install virtualenv

建立~/venv目录,建立virtualenv, 激活virtualenv

mkdir ~/venv
cd ~/venv
virtualenv spider
source ~/venv/spider/bin/activate

之后,shell提示符应该是这样
ssh2

安装django(1.7)

pip install django
cd ~ # 返回用户目录

5秒钟后,django安装完毕,现在开始建立项目目录(Django的project)。我们爬虫站点的所有文件都放在里面。


django-admin startproject python_spider

再测试下安装是否成功

service nginx stop # 为毛? 因为RunAbove的8000神马的端口不好用
python manage.py runserver 0.0.0.0:80 # 只能用80

现在访问192.99.71.91,我就能看到Django的示例页面
Django1
没骗你吧? 好了,看一眼能用就ctrl+c把服务器关掉。

然后,再建立一个app

cd python_spider
python manage.py startapp web

所以,现在我有一个Django项目,叫python_spider, 它里面有个app叫web.

未完待续。。。
下一篇,是简单Python爬虫的编写。

在centos6中安装python2.7和pip,virtualenv

 

1.准备工作

yum groupinstall "Development tools"
yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel

2.下载并安装python2.7(注意make altinstall)

wget http://python.org/ftp/python/2.7.6/Python-2.7.6.tar.xz
tar xf Python-2.7.6.tar.xz
cd Python-2.7.6
./configure --prefix=/usr/local --enable-unicode=ucs4 --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
make && make altinstall

3.安装pip

wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
python2.7 ez_setup.py
easy_install-2.7 pip

4.安装virtualenv

pip2.7 install virtualenv

接下来,直接使用virtualenv xxx创建隔离的运行环境,其中python版本默认为2.7

如果在virtualenv外,则需要使用python2.7来调用2.7版本

一个连原文都搜不出来的搜索引擎能叫搜索引擎!?

长期以来养成了中文搜某度 英文搜谷歌的习惯

最近发现某度的中文搜索并不比谷歌厉害

上次在某博客发现一文章,最后是未完待续,于是乎在某度搜原文,

结果第一页上不是图片没采集到位就是伪原创过度无法阅读

我没有看第二页

转到谷歌一搜 第一篇就是原文

传说中的更懂中文呢?

谁能告诉我京东为毛要有第三方?

一直很不理解这个问题 在我看来 第三方商家除了能够增加搜索出来的商品数量之外,对用户没有任何好处,对京东自己也是弊大于利

我是京东的忠实粉丝,我从来不在京东购买非京东自营的东西!

第三方卖家的商品没有质量保证,出了问题也不知道应该找谁,第三方商家是对京东口碑的最大威胁

京东的物流是一个亮点,但是在第三方卖家那里却体现不出来

而且,京东没有像支付宝一样的担保支付,对客户来说也是很危险的

周围关于京东的恶评90%都是和第三方有关,而很多客户会把对卖家的恨转移到京东,从而导致京东丢掉客户

所以实在搞不懂为毛要有第三方卖家在京东。。

用Django开发了一个BBS

放到Github上了:这里
目前运营在Python.cc
演示:http://fairybbs.com
是我的第二个django写的bbs
之前也写过一个 但是那个时候实在是太年轻了 导致我自己都看不下去代码
这次这个注意了很多之前遇到的坑
下一步打算继续完善这个东西,争取发布自己的第一个拿得出手的开原作品。