根据 WWDC16 海报配色风格调了个 Sublime Text 3 和 iTerm2 的配色

中秋节在家呆的无聊,老爸老妈都去打牌了,离做下午饭又还有段时间,于是把 Sublime Text 的配色改了。

早就想改成 WWDC 2016 宣传海报的配色玩玩,之前在 Github 找了一个https://github.com/Snazzyham/wwdc-2016,用上后总觉得不对,于是自己也用 TmTheme Editor 调了一个。

能够确定的配色,注释,字符串,关键字,背景色。

其他部分根据自己的审美分配了一下。

最终是这样子:

用 TmTheme Editor 生成的文件,Class name 并没有样式。Google 了一下文档,把

<dict>
    <key>name</key>
    <string>Class name</string>
    <key>scope</key>
    <string>entity.name.class</string>
    <key>settings</key>
    <dict>
        <key>foreground</key>
        <string>#7DCD6E</string>
        <key>fontStyle</key>
        <string> bold</string>
    </dict>
</dict>

entity.name.class 替换成 entity.name.type.class 即可。

也顺便把 iTerm2 的配色改了。

配色文件放在了 Github 上 https://github.com/tanzhijian/wwdc16_color_scheme ,有需要的可以拿去用。


更新:用了几天的感想。。。还是 Monokai 比较可爱啊。

使用爬虫抓取一些足球网站 24 小时以内发布的新闻(续)

没有 datetime,因为上一篇写得差不多了。开始吧,下面是 FourFourTwo

这次麻烦了,新闻列表里只有发布日期,没有具体时间。(ps: 贝大湿作为世界名帅混到纽卡也是 6 的飞起)

难道要掐着表到零时整点开始抓取?不,要随时都可以抓。

既然每天抓一次,那每次抓当日和昨日,然后把当日存起来。

第二天继续抓当日和昨日,把昨日与昨天的当日比对求差集,所得结果就是昨日抓取以后的新闻,加上今日便可得。

可是可以,只是不严谨,而且还得专门建个表来存昨日的新闻。

换个思路吧。

先抓取今日和昨日的新闻,存进列表。

每一篇新闻页面是有具体的发布时间,不过小于 24 小时是 ‘6 min ago’, ‘1 hour ago’, ‘3 hours ago’ 的形式,大于 24 小时是 ‘11 March 2016’ 的形式。可以通过抓取具体的新闻页面来确定新闻是否小于 24 小时发布。

如何确定哪些链接是 24 小时以内发布?遍历然后抓取?

二分吧,简单,而且对于每次一百条以下的列表效率也不错。

把已经获取的昨日今日列表等分,列表 1 列表 2。

抓取列表 1 的最后一条 url 和列表 2 第一条 url。

如果列表 1 的最后一条 url 小于 24 小时发布,同时列表 2 的第一条 url 大于 24 小时发布,则可以确定列表 1 的最后一条 url 是 24 小时以内的最后一条。

如果仅是列表 1 的最后一条 url 小于 24 小时,则把列表 2 等分,然后重复上面的步骤。

如果仅是列表 2 的第一条 url 大于 24 小时,则把列表 1 等分,然后重复上面的步骤。

开始写代码,先抓取今日和昨日的新闻,存进列表。

_list = []
now = datetime.now()

# target 为找出的新闻列表中所有的新闻 div
for element in target:
    # 找到发布日期
    date_str = element.find('div', attrs={'class': 'created'}).string
    date_time = datetime.strptime(date_str, "%d %B %Y")
    if (now - date_time).total_seconds() < 3600 * 24 * 2:
        # 把链接找到并添加进列表
        href = 'http://www.fourfourtwo.com' +\
            node.find('h3').find('a').get('href')
        _list.append(href)

完成首页,继续获取下一页,直到当前页面出现昨日以前的新闻,结束。

定义一个函数,用来抓取新闻的具体页面,找出发布时间,并确定是否小于 24 小时发布。确定是否小于 24 小时发布的思路与上一篇的 Squawka 一样,用交集确定。

def less_than_24_hours(url):

    # requests 获取页面,然后交给 BeautifulSoup 处理
    r = requests.get(url)
    soup = BeautifulSoup(r.content, 'lxml')

    # 找到发布时间
    element = soup.find(
        'div', 
        attrs={'id': 'node_news_article_full_group_social'}
    )
    date_time_str = element.find(
        'div', 
        attrs={'class': 'field-name-post-date'}
    ).find('div', attrs={'class': 'field-item'}).string

    # 24 小时以内的关键词,并寻找交集
    keywords = ('min', 'hour', 'hours')
    num = len(set(date_time_str.split()).intersection(keywords))
    # 如果有关键词的交集,说明此新闻是小于 24 小时
    if num > 0:
        return True
    else:
        return False

然后开始二分吧。

# _list 为已找出的今日与昨日的 url 列表
original_list = _list
# 预设没有找到目标
target = False

while not target:

    # 等分
    num = len(original_list) // 2
    list1 = original_list[:num]
    list2 = original_list[num:]

    # 找出 list1 的最后一条 url 和 list2 的第一条 url
    # 使用上面定义的函数,确定是否小于 24 小时发布
    list1_last_url_less_than_24_hours = less_than_24_hours(list1[-1])
    list2_first_url_less_than_24_hours = less_than_24_hours(list2[0])

    # 如果 list1 的最后一条 url 小于 24 小时,同时 list2 的第一条 url 大于 24 小时
    # 则可以确定 list1 的最后一条 url 是 24 小时以内的最后一条,同时结束循环
    if list1_last_url_less_than_24_hours and\
            not list2_first_url_less_than_24_hours:
        target_url = list1[-1]
        target = True
    # 如果 list1 的最后一条 url 小于 24 小时,则 original_list = list2 并继续循环
    elif list1_last_url_less_than_24_hours:
        original_list = list2
    # 如果 list2 的第一条 url 大于 24 小时,则 original_list = list1 并继续循环
    elif not list2_first_url_less_than_24_hours:
        original_list = list1

    # 最后找出最后一条小于 24 小时的 url 位置,就 index 了,简单点
    target_url_num = _list.index(target_url)
    # 切片确定所有小于 24 小时的 url 列表
    url_list = _list[:target_url_num+1]

完成。效率不算高,不过代码少,逻辑也算简单。

使用 datetime 配合爬虫抓取一些足球网站 24 小时以内发布的新闻

最近由于需要,用 Python 写了一个爬虫,用来抓取一些足球网站 24 小时以内发布的新闻。

用到的库:requests,BeautifulSoup,datetime。

目标网站:虎扑国际足球新声WhoScoredGoal.comSky SportsSquawka

虎扑国际足球新声和 Sky Sports

先分析网页。

可以找到虎扑国际足球新声的新闻列表的标签 <div class="new-list>

继续分析,每条新闻都在 <ul> 标签的一个 <li> 标签里。

找到发布时间的标签 <a class="time" target="_blank" href="http://voice.hupu.com/soccer/2010662.html" title="2016-03-10 03:04">,发现需要的信息(发布时间,文章 url)都在里面了。

可以写代码了。requests 获取页面,BeautifulSoup 从页面中找到 <div class="new-list>,并从 <div class="new-list> 找出所有的 <a class="time">。由于重点不是 requests 和 BeautifulSoup,这部分代码就不贴了。

接着对每条 <a class="time"> 的发布时间进行分析。找到 <a> 标签里的 title 属性,使用 datetime 进行转换比较。可以建一个空 list,把每一条发布时间小于 24 小时 的 url 添加进去。

_list = []
now = datetime.now()

# target 为 BeautifulSoup 找出的所有 <a class="time"> list
for a in target:

    date_time = datetime.strptime(a.get('title'), "%Y-%m-%d %H:%M")

    # 如果时间差小于 24 小时,把 url 添加进列表
    if (now - date_time).total_seconds() < 86400:
        _list.append(a.get('href'))

完成首页,继续获取下一页,直到当前页面出现大于 24 小时的新闻,结束。

Sky Sports 的发布时间标签和链接的 <a> 标签并不是一起,且时间是用 am/pm 表示,因此会稍微麻烦一点。

观察发现 <div>class 属性 news-list__item--show-thumb-bp30 在整个页面只用在新闻列表的每个条目上,把它们都找出即可。

_list = []
now = datetime.now()

# target 为找出所有 class 为 news-list__item--show-thumb-bp30 的 div
for element in target:

    date_time_str = element.find('span', attrs={'class': 'label__timestamp'}).string
    # %I 匹配 12 小时制,%p 匹配 am/pm,需搭配一起使用
    date_time = datetime.strptime(date_time_str, "%d/%m/%y %I:%M%p")

    # 如果时间差小于 24 小时,找到 url 并添加进列表
    if (now - date_time).total_seconds() < 86400:
        href = element.find('a', attrs={'class': 'news-list__headline-link'}).get('href')
        _list.append(href)

完成首页,继续获取下一页,直到当前页面出现大于 24 小时的新闻,结束。

WhoScored 和 Goal.com

不需要 WhoScored 的新闻,只需要它的文章(Articles)。

文章每天只更新一到两篇,不出意外抓取首页即可满足。

_list = []
now = datetime.now()

# target 为找出的新闻列表标签里所有的 <div class="post-header"> 标签
for element in target:

    date_time_str = element.find('span', attrs={'class': 'post-date'}).string
    # 注意它的发布时间'at Wednesday, Mar 9 2016 10:35',需要干掉前 3 个字符再转换
    # %A 匹配完整的星期,%b 匹配缩写的月份
    date_time = datetime.strptime(date_time_str[3:], "%A, %b %d %Y %H:%M")

    # 如果时间差小于 24 小时,找到 url 并添加进列表
    if (now - date_time).total_seconds() < 86400:
        href = 'https://www.whoscored.com' + element.find('a', attrs={'class': 'post-title'}).get('href')
        _list.append(href)

完成首页结束。

Goal.com 的每条新闻只有发布时间,因为日期被写到了外面,因此又要麻烦一点。

分析页面,发现它是以日期作为分类,譬如 3 月 9 日在一个 div,3 月 8 日 在另一个 div。

_list = []
now = datetime.now()

# soup 为 BeautifulSoup 获取的整个页面
# 找出所有以日期为分类的 div
target = soup.find_all('div', attrs={'class': 'day-news'})
for daynews_div in target:

    # 找到日期
    _date = daynews_div.find('div', attrs={'class': 'date'}).string

    # 再找出日期标签里的所有新闻
    element_list = daynews_div.find_all('div', attrs={'class': 'articleInfo'})
    for element in element_list:

        # 找出新闻的发布时间
        _time = element.find('span', attrs={'class': 'time'}).string
        # 把发布日期和发布时间组合起来
        date_time_str = '%s %s' % (_date, _time)
        # %B 匹配完整的月份
        date_time = datetime.strptime(date_time_str, "%A, %B %d, %Y %H:%M")

        # 如果时间差小于 24 小时,找到 url 并添加进列表
        if (now - date_time).total_seconds() < 86400:
            # 因为只有一个 <a>
            href = 'http://www.goal.com' + element.find('a').get('href')
            _list.append(href)

完成首页,继续获取下一页,直到当前页面出现大于 24 小时的新闻,结束。

Squawka

<p class="posted">Posted 1 min ago</p>。。。等等,这是什么鬼。。。

抖个机灵吧。既然小于 24 小时是用 ‘Posted 1 min ago’, ‘Posted 8 mins ago’, ‘Posted 1 hour ago’, ‘Posted 4 hours ago’ 表示,且在后端已经完成了转换,那。。。

# 先把 hours, mins 等小于 24 小时的词添加到列表
keywords = ['hours','mins', 'hour', 'min']
# 把发布时间切分成列表,并寻找交集
# date_time_str 为每条新闻的发布时间
num = len(set(date_time_str.split()).intersection(keywords))
# 如果有交集,则此新闻是小于 24 小时发布
if num > 0:
    pass

最后是参考资料。

16.3. time — Time access and conversions — Python 3.5.1 documentation