Python爬虫入门级项目

项目简介

由于最近调研文献需要,想查看KDD2017年的论文是否有相关的论文。但是KDD accept的论文有200+,要一篇篇去看太浪费时间了。于是想写个爬虫,爬取论文的abstract,然后Ctrl+F看下是否包含相关的keyword。 本来也想爬取每篇论文的keywords,但是提供的网页中没有这个内容,所以这里没有爬取。最后爬取的内容格式为:
<title, author, abstract, link>,其中link是论文在acm library中的网址。

注:建议先学习网易云课堂一个python网络爬虫的教程,免费,而且很短,里面涉及很多知识,对小白很有帮助。我使用的方法大多都是其中的。 链接:http://study.163.com/course/courseLearn.htm?courseId=1003285002#/learn/video?lessonId=1046324611&courseId=1003285002

用到的工具

Python 3.6(Anaconda虚拟环境)
requests、BeautifulSoup、pandas、re包
 Chrome插件:selectorgadget

具体步骤

首先,进入kdd2017的网址,发现accepted paper在 http://www.kdd.org/kdd2017/accepted-papers中,且该网址使用'GET'方法,所以利用requests包打开该网址。代码如下:

import requests
url = 'http://www.kdd.org/kdd2017/accepted-papers'
res = requests.get(url)
res.encoding = 'utf-8'  ##设置编码

然后观察我们需要的论文的CCS属性,利用selectorgadget可以方便的得到所有论文的CCS属性为"#fitvid0 , .table-bordered a",所以我们可以用BeautifulSoup去定位到这些论文,并把结果存在papers变量中。

from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'html.parser')
papers = soup.select('#fitvid0 , .table-bordered a')

我们输出papers中第一个元素看一下,#注释的部分为输出结果:

print(papers[0])
#<a href="http://www.kdd.org/kdd2017/papers/view/randomization-or-condensation-linear-cost-matrix-sketching-via-cascaded-com">Randomization or Condensation?: Linear-Cost Matrix Sketching Via Cascaded Compression Sampling</a>

我们发现结果中包含'href'属性,这是论文的详细描述。之前http://www.kdd.org/kdd2017/accepted-papers中只包含论文的title和author。所以为了爬取具体的abstract,我们需要分别进入每一篇论文的描述页中。 使用如下代码: papers[i]['href'],i为具体第i篇论文,我们使用for循环可以遍历每一篇论文。

解析论文描述页内容

首先我们随便找一篇论文,查看网页中包含哪些内容:


image.png

网页中包含 title, author, Abstract,以及一个支持下载的按钮。 其中该下载按钮中包含一个url跳转到具体的下载的acm library页面。所以我们接下来就对每个内容进行爬取。

Title

image.png

title内容的爬取非常简单,我们利用Chrome自带开发者模式中元素审查发现它存在于<h3></h3>中,所以我们直接定位到该标签位置即可

title = soup.select('h3').text

Author

image.png

author内容在<strong></strong>之中,所以我们可以使用如下代码提取作者信息。

author = soup.strong.text

注意:soup.strong会找出网页中第一个strong标签的内容,因为这里author的strong标签是第一个出现的,所以没有关系。

Abstract

image.png

从图中我们看到Abstract内容在<p></p>中,但是,网页中有很多的<p></p>标签,我们尝试定位并输出看一下:

image.png

爬取Abstract的难点主要有3点:
1.我们发现输出的结果中除了Abstract还有其他很多没用的信息
2.Abstract的<p></p>不是第一个出现,无法使用类似于author的方法。
3.有些论文的Abstract有2段,有些论文的Abstract只有1段。
在这里,我们通过观察每个论文的<p></p>的内容的规律,发现内容中:
第一个内容,以及最后两个内容不是我们要的Abstract,其他中间的内容就是Abstract。所以我们可以利用list的分片方法取出中间的内容。

abstract = []
    for a in soup.select('p')[1:-2]:
        abstract.append(a.text)
abstracts = ' '.join(abstract)##把多段的内容合并成一段

Link

Link的提取是本项目最难的地方。我们直接审查元素无法定位到具体的url,而真正的url存在于<a></a>中


image.png

当我们定位<a></a>标签时,会出现下面的情况。


image.png

我们发现会把网页中所有链接的url都输出了。我们需要从中选出真正指向acm library的url。在这里我们使用正则表达式进行筛选。 因为acm library的网址的开头一定是‘dl.acm.org’,所以我们利用如下的方法对每个url进行正则匹配,选择出匹配的结果。

import re
link = []
for ele in soup.find_all("a"):
    m = re.search('.*dl.acm.org/.*', ele['href'])
    if m:
       link.append(m.group(0)) ##group(0)表示完整的匹配结果

我们尝试对例子网页进行爬取,发现成功提取除了url。

image.png

By the way:细心的朋友发现我这里link初始化成list,在后面if语句中使用append添加元素。而不是直接用link = m.group(0)、这是因为在kdd2017 accepted 论文中有一篇论文不提供 download full paper的按钮,所以对那篇论文进行操作时,m对象实际上不存在。如果不先初始化link为list,则会导致程序出错。

构造解析函数

我们把上面四个内容的爬取写进一个函数中,函数的参数为论文的描述页url。

def paperDetail(url):
    detail = {}
    res = requests.get(url)
    res.encoding = 'UTF-8'
    soup = BeautifulSoup(res.text, 'html.parser')
    title = soup.h3.text
    author = soup.strong.text
    link = []
    for ele in soup.find_all("a"):
        m = re.search('.*dl.acm.org/.*', ele['href'])
        if m:
            link.append(m.group(0))
    abstract = []
    for a in soup.select('p')[1:-2]:
        abstract.append(a.text)
    abstracts = ' '.join(abstract)

    exp = lambda x: x[0] if len(x) > 0 else ''
    detail['link'] = exp(link)
    detail['author'] = author
    detail['title'] = title
    detail['abstract'] = abstracts
    return detail

循环解析所有论文

import pandas as pd
total_paper = []
    for i in range(len(papers)):
        print(i)
        one_paper = paperDetail(papers[i]['href'])
        total_paper.append(one_paper)

result = pd.DataFrame(total_paper)
result = result[['title','author','abstract','link']]
result.head()
result.to_csv('paper.csv')

至此,项目结束。

总结

这是属于最基本、最简单的python爬虫项目,只对静态页面进行爬取,也没有遇到发爬虫的困难。(本来还想进入每篇论文的link爬取论文的doi,但是acm有反爬虫机制,导致无法爬取,之后会研究如何反-反爬虫)。
有大神对我其中任何一个步骤有建议的欢迎评论,有问题也可留言。

致谢

感谢提供帮助的同学们:swy, cx, lck

完整代码

import pandas as pd
from bs4 import BeautifulSoup
import requests
import re


def paperDetail(url):
    detail = {}
    res = requests.get(url)
    res.encoding = 'UTF-8'
    soup = BeautifulSoup(res.text, 'html.parser')
    title = soup.h3.text
    author = soup.strong.text
    link = []
    for ele in soup.find_all("a"):
        m = re.search('.*dl.acm.org/.*', ele['href'])
        if m:
            link.append(m.group(0))
    abstract = []
    for a in soup.select('p')[1:-2]:
        abstract.append(a.text)
    abstracts = ' '.join(abstract)

    exp = lambda x: x[0] if len(x) > 0 else ''
    detail['link'] = exp(link)
    detail['author'] = author
    detail['title'] = title
    detail['abstract'] = abstracts
    return detail

def parse():
    url = 'http://www.kdd.org/kdd2017/accepted-papers'
    res = requests.get(url)
    res.encoding = 'utf-8'  ##设置编码
    soup = BeautifulSoup(res.text, 'html.parser')
    papers = soup.select('#fitvid0 , .table-bordered a')
    total_paper = []
    for i in range(len(papers)):
        print(i)
        one_paper = paperDetail(papers[i]['href'])
        total_paper.append(one_paper)

    result = pd.DataFrame(total_paper)
    result = result[['title','author','abstract','link']]
    result.head()
    result.to_csv('paper.csv')
    return result
if __name__ == '__main__':
    parse()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容