使用爬虫抓取一些足球网站 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

2015 年读书清单

年末了,整理了今年的读书清单,且附上个人评分和简评,有需要的可以做个参考。

个人评分用 ★ 表示,五颗 ★ 为满分。

书排列没有顺序。

  • 《当我们谈论爱情时我们在谈论什么》;★★★;三星还是四星,比较纠结,原因是看得累,花了大量时间在字里行间抠线索,我不大喜欢这样的阅读体验,不流畅,但不可否认这本书确实好,几乎不能看到带有叙事性的描述,把所有内容埋在支离破碎的对话中,我头一次读到这样的书,感觉有太多东西可以深挖和借鉴。

  • 《神曲(故事插图本)》;★★★★;我不了解西方宗教神话,以至于书里绝大多数关于此类的梗我并能不明白,不过,1.故事直白有力的批判/歌颂人性的恶与善,通篇弥漫着自省,自我救赎,行文流畅优美,2.画有种我无法形容的气势和美。

  • 《我与地坛》;★★★★★;这本书有太多句子可以触到内心:朴素真诚,逆境却充满活力的句子,当然了,还有不得不提的东西,教科书一样的排比…有些过了。

  • 《HTTP 权威指南》;★★★★;工具书,我突然想起成天在网上“求干货”那帮人,啃这类书啊,通篇干货,干得不能再干了。

  • 《程序员的数学思维修炼》;★★;这本书如果叫非数学相关行业的数学思维修炼,我觉得可以有 4 星,毕竟内容写得挺明了易懂,程序员的数学思维修炼还是得弄一些严肃的大部头书来看。

  • 《三体(一)》;★★★★;(一)还是不错的,(二)读不下去了。

  • 《大教堂与集市》;★★★★★;开源社区政治精神学习手册…抛开这些,大教堂与集市章节中对于 Linux 世界的“集市”模式,讲得简单清楚。

  • 《爱你就像爱生命》; ★★★;感叹词过多,以至于有种通篇都是感叹号的错觉。

  • 《圣地》;★★★;和前面《神曲》一样,由于不了解文化,所以能理解的有限,权当看画了。

  • 《黑骏马》;★★★;写得啰嗦,比较无聊,有点像一些日本日常电影,看过觉得不错,但不会看第二遍。

  • 《Flask Web 开发:基于 Python 的 Web 应用开发实战》;★★★★;这本书对于我就像桑切斯对于阿森纳。

  • 《Python 学习手册(第4版)》;★★★;工具书,通读的时候冗长且乏味,但当一些细枝末节需要了解查询时就会发现它实用。

  • 《SQL 必知必会》;★★★★;工具书,通读记个目录以备查询。

  • 《去中国的小船》;★★★★;几篇文章都喜欢,简练,故事丰满,逻辑也好,依旧弥散着熟悉的悠闲和孤独。

  • 《MySQL 必知必会》;★★★★;同《SQL 必知必会》。

  • 《学习正则表达式》;★★★;下定决心要把正则表达式给搞定了,不过读完后…该查书还是得查书,该 google 还是得 google。

  • 《中国居民膳食指南》;★★★★;买给老妈的,自己先看一遍,如果您身边有人信朋友圈养身小段子,而这个人对您比较重要,那就送他一本。

  • 《城市就是健身房》;★★★★;在知乎上看作者的文章多了,见到他出的书自然也买一本。

  • 《白帽子讲 Web 安全》;★★★★;如果您对 XSS,SQL 注入,CSRF 等词汇很熟却又不大了解,读吧,科普向技术书,覆盖面广,同时讲得清楚。

  • 《遇到百分之百的女孩》;★★★★;“一期一会”大概很适合描述这本书里面文章的情节,随机,不经意间的故事,我们经历,遗忘,而他却把它们记录了下来,以至于读起来有种似曾相识的共鸣,还有,怎么又是羊男,这家伙存在感到底有多强啊…

  • 《创造者 : 从富兰克林、比尔·盖茨到伍迪·艾伦》;★★★★;它的作者是《乔布斯传》的作者,同时也是我喜爱的书《爱因斯坦 : 生活和宇宙》的作者,因为如此才买了此书,文章,对人物的探讨,对历史的见解,都足够严肃,足够深。

  • 《我承认我不曾历经沧桑》;★★★;读完后印象还不错,但没有笔记,以至现在记不起来书写的是什么了。

  • 《硬派健身》;★★★;同《城市就是健身房》。

  • 《失乐园》;★★★;无病呻吟。

  • 《小王子》;★★;谁能告诉我这书好在哪里。

  • 《JavaScript 高级程序设计(第3版)》;★★★★★;实用的工具书。

  • 《就是痛快:糖蒜广播的十年》;粉丝向,毕竟糖蒜广播听了好些年了(其实就是听 Gadio吧哼)。

  • 《jQuery 基础教程(第4版)》;★★★★★;在网上看了好多乱七八糟的 jQuery 技巧,也跟着学了不少,不过始终太零碎,于是买本书系统的看一回。

  • 《文学回忆录(全2册)》;★★★★★;读这本书,与其说是读书,倒更像是在听一个老先生凭着渊博知识东拉西扯,谈文学,谈音乐,谈绘画,谈政治,谈人性,由于是笔录,且断句方式独特,所以可以脑补出扑面而来的画面感。

  • 《足球运动系统训练》,买来送朋友,自己先看上一遍,读完后明白了一个困扰了多年的问题,为什么普通人球技到了一个水平后始终上不去,因为只知道踢球,憨踢球,忽略了一个最大问题,足球始终是一个综合体育运动,需要强壮的身体,而不仅是技巧,技巧靠天赋,普通人到了一定水平也就那样,而身体素质是可以练上去的,下意识锻炼每一块要用到的肌肉,强化体能,跑得更快,这些才是涨球的关键。

  • 《现代操作系统(原书第3版)》;★★★★★;这类书不用多说了。

  • 《计算机文化(原书第15版)》;★★★★;关于计算机名词解释的百科纸质版。

  • 《舞 ! 舞 ! 舞 !》;★★★★★;一如既往的人设,一如既往的漂亮句子,书中反复出现的两个观点:高度发达的资本主义社会,只要音乐没停就一直跳舞,前者是本书一直强调的东西,后者一直推动主线剧情——解惑。

  • 《重新定义公司:谷歌是如何运营的》;★★★★;读完就明白了——或许很早已经明白,而现在只是听它重述一遍,新时代的公司是什么样子。

  • 《那些忧伤的年轻人》;★★★★;我喜欢作家的一个特长:他们总是能把普通人脑内混沌不清的概念用清晰优美的语言给表述出来,我们谈恋爱,分手,成长了,分手,这个过程中我们恋爱了什么,成长了什么,大多数人不会去想,或者想不明白,于是就任凭混沌,他们应该读书,读《那些忧伤的年轻人》。

  • 《天黑以后》;★★★★;它讲述了一些故事,却又隐述了一些故事,更多见我稍后会写的读书笔记,值得一提的是,V2EX 有一个节点叫天黑以后,我想它的来源大概就是此书,为什么,因为它的节点描述,“白天和晚上的我,是不一样的。”

  • 《Jekyll 小书》;★★★;想把 tanzhijian.org 改成静态网站,于是买了此书参考。

  • 《长歌行(06-09)》;★★★;积累了两年的量,一下午读完。

  • 《成为贾伯斯》;★★★★★;“熟人”理解的乔布斯,和媒体塑造的乔布斯,是不一样的。

  • 《图解 HTTP》;★★★★;如果你觉得《HTTP 权威指南》太“干”,可以读这个,倒不是说这本书比较“湿”,而是它比较“萌”。

去年说读完村上的书,今年仍然没做到,不过这已经不重要,慢慢来。

今年的读书数量不少,不过感觉有些“杂”,一些书打折时,限免时囫囵买入,想随便翻翻,可这哪能做到随便,譬如《圣地》,多看阅读限免时拿下,读完也花了好几天,这样不免有些浪费时间了。

我希望明年拟一个读书计划,譬如技术主攻一两个方向的书,文学指定两三个作家的书,此外预留 20% 左右的时间,用来临时变动。

我希望明年能够读一些哲学类的书。今年在读完《文学回忆录》时就有这样的打算,一直拖拖拉拉,到现在也没能做到,明年开始吧。