QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5251|回复: 2
打印 上一主题 下一主题

[分享] [DataScience] 手把手教你用python抓网页数据

[复制链接]
字体大小: 正常 放大

1

主题

12

听众

76

积分

升级  74.74%

  • TA的每日心情
    开心
    2016-1-31 11:16
  • 签到天数: 40 天

    [LV.5]常住居民I

    跳转到指定楼层
    1#
    发表于 2015-12-4 16:22 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    这条帖子也是小伙伴分享给我的,觉得不错,分享给大家,关于网页数据提取的,对于一些少数据或是在网页上拷数据的数学建模题目来说很有用!
    / j$ k5 S' z! V  X2 X再次声明一下,本帖是转发贴,感谢原作者:EroicaCMCS,以下是原帖地址:http://www.1point3acres.com/bbs/thread-83337-1-1.html
    # z- h8 {1 q5 L! F$ v3 h前言:
    数据科学越来越火了,网页是数据很大的一个来源。最近很多人问怎么抓网页数据,据我所知,常见的编程语言(C++,java,python)都可以实现抓网页数据,甚至很多统计\计算的语言(R,Matlab)都有可以实现和网站交互的包。本人试过用java,python,R抓网页,感觉语法各有差异,逻辑上是一样的。我准备用python来大概讲讲抓网页是什么概念,具体的内容要自己看手册或者google别人的博客,这里算是抛砖引玉了。水平有限,出现错误或者有更好的办法,欢迎讨论。
    / o* l. h' I" ~' |' d$ E9 a
    ; a: g) K. x9 R步骤一:熟悉Python的基本语法。
    ) D+ ^" P; A' o3 b2 J$ @; R5 i已经熟悉Python的直接跳到步骤二。
    , E2 i7 i! P; U3 h- nPython是门比较容易入门的编程语言,如何上手视编程基础而定。+ O* R% D8 @' N
    (1) 如果有一定编程的基础,建议看google's python class,链接https://developers.google.com/edu/python/?hl=zh-CN&csw=14 ?% \8 k5 R$ b
    这个是一个为期两天的短期培训课程(当然,是两个全天),大概是七个视频,每个视频之后给编程作业,每个作业一个小时之内可以完成。这是我学习python的第二门课(第一门是codecademy的python,很早之前看的,很多内容都记不得了),当时每天看视频+编程作业一个多小时,六天弄完,效果还不错,用python写基本的程序没有问题。
    ) A: B# H5 \9 A' N" H(2) 如果是没有任何编程基础,建议看coursera上Rice University开的An Introduction to Interactive Programming in Python。这门课我没有跟过,但是看coursetalk的评论反映非常好,地里也有同学评论(点这里),课程链接:https://www.coursera.org/course/interactivepython。Udacity上的CS101也是不错的选择,地里有相关的讨论帖(点这里),而且这门课就叫做build a search engine,会专门讲一些和网络相关的module。其他学习资源还有code school和codecademy,这些资源也是挺不错的,但是编程量太少,初学者还是系统的跟课、多练练手来打好基础吧。1 c: I6 s/ u7 E, j  M
    当然,每个人的偏好不同,我推荐的不一定适合你。可以先看看这个帖子【长期加分贴】介绍你上过的公开课里面其他人是怎么说的,或者上coursetalk.org看看课程评论,再决定吧。  h6 J- ?' [! G  b+ X9 h3 G- E
    5 O' ]6 R# h! U
    # M6 q( M% L' i# n
    步骤二:学会如何与网站建立链接,得到网页数据。
    % F8 r$ Y! y1 F. i写脚本与网站进行交互,要熟悉python和网页相关的几个module(urllib,urllib2,httplib)中的一个,知道一个即可,其他的都类似的。这三个是python提供的和网页交互的基本module,还有其他的一些,比如:mechanize和scrappy,我没有用过,可能有更好的性能,欢迎了解的来补充。基本的网页抓取,前面的三个module足矣。
    6 y0 z, X0 k. O9 I- G' s- Y. d) B8 ?" X下面的代码演示如何用urllib2与google scholar进行交互,获得网页信息。4 y' I& D3 q$ @* a; Z' H6 j6 c" z
    • # 导入模块 urllib2
    • import urllib2
    • # 随便查询一篇文章,比如On random graph。对每一个查询google
    • # scholar都有一个url,这个url形成的规则是要自己分析的。
    • query = 'On+random+graph'
    • url = 'http://scholar.google.com/scholar?hl=en&q=' + query + '&btnG=&as_sdt=1%2C5&as_sdtp='
    • # 设置头文件。抓取有些的网页不需要专门设置头文件,但是这里如果不设置的话,
    • # google会认为是机器人不允许访问。另外访问有些网站还有设置Cookie,这个会相对复杂一些,
    • # 这里暂时不提。关于怎么知道头文件该怎么写,一些插件可以看到你用的浏览器和网站交互的
    • # 头文件(这种工具很多浏览器是自带的),我用的是firefox的firebug插件。
    • header = {'Host': 'scholar.google.com',
    • 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:26.0) Gecko/20100101 Firefox/26.0',
    • 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    • 'Accept-Encoding': 'gzip, deflate',
    • 'Connection': 'keep-alive'}
    • # 建立连接请求,这时google的服务器返回页面信息给con这个变量,con是一个对象
    • req = urllib2.Request(url, headers = header)
    • con = urllib2.urlopen( req )
    • # 对con这个对象调用read()方法,返回的是html页面,也就是有html标签的纯文本
    • doc = con.read()
    • # 关闭连接。就像读完文件要关闭文件一样,如果不关闭有时可以、但有时会有问题,
    • # 所以作为一个守法的好公民,还是关闭连接好了。
    • con.close()2 x6 {8 t# B1 N" k; C$ d
    1 j, c1 c6 R7 H2 |5 l( u) N, m, k+ G* F
    复制代码% H3 S9 g4 n! s0 N
    以上的代码就把在google scholar上查询On Random Graph的结果返回到doc这个变量中了,这个和你打开google scholar搜索On Random Graph,然后将网页右键保存的效果是一样的。
    # ^  W! D+ v+ f6 E3 R! H& C  p6 _
    ( }6 H1 C6 `+ e0 G$ I3 z; v步骤三、解析网页
    9 w" \, N  S$ d* h" K3 A5 W3 a" \上面的步骤得到了网页的信息,但是包括了html标签,你要把这些标签去掉,然后从html文本中整理出有用的信息,
    2 m- w( u7 S& ?( ~' u你需要解析这个网页。; [$ |* F5 m3 I4 P5 f* Q) B
    解析网页的方法:
      E- N! i$ H+ G' w(1) 正则表达式。正则表达式很有用,熟悉它节省很多的时间,有时候清洗数据不用写脚本或者在数据库上查询,直接在notepad++上用正则表达式组合使用就行了。如何学习正则表达式建议看:正则表达式30分钟入门教程,链接:http://deerchao.net/tutorials/regex/regex.htm% S& s) p4 U; Y
    (2) BeautifulSoup模块。BeautifulSoup是一个很强大的模块,能把html文件解析成一个对象,这个对象是一棵树。我们都知道html文件是树状的,比如 body -> table -> tbody -> tr,对于tbody这个节点,有很多个tr的子节点。BeautifulSoup可以很方便的取到特定的节点,对单个节点也可以取它的sibling node。网上有很多相关的说明,这里不细说,只演示简单的代码:
    - y  X9 p( O3 o* I0 W% u(3) 上面两种方法结合使用。) r0 v6 ^8 V0 f% E5 a& ?' T
    • # 导入BeautifulSoup模块和re模块,re是python中正则表达式的模块
    • import BeautifulSoup
    • import re
    • # 生成一个soup对象,doc就是步骤二中提到的
    • soup = BeautifulSoup.BeautifulSoup(doc)
    • # 抓取论文标题,作者,简短描述,引用次数,版本数,引用它的文章列表的超链接
    • # 这里还用了一些正则表达式,不熟悉的先无知它好了。至于'class' : 'gs_rt'中
    • # 'gs_rt'是怎么来的,这个是分析html文件肉眼看出来的。上面提到的firebug插件
    • # 让这个变的很简单,只要一点网页,就可以知道对应的html 标签的位置和属性,
    • # 相当好用。
    • paper_name = soup.html.body.find('h3', {'class' : 'gs_rt'}).text
    • paper_name = re.sub(r'\[.*\]', '', paper_name) # eliminate '[]' tags like '[PDF]'
    • paper_author = soup.html.body.find('div', {'class' : 'gs_a'}).text
    • paper_desc = soup.html.body.find('div', {'class' : 'gs_rs'}).text
    • temp_str = soup.html.body.find('div', {'class' : 'gs_fl'}).text
    • temp_re = re.match(r'[A-Za-z\s]+(\d*)[A-Za-z\s]+(\d*)', temp_str)
    • citeTimes = temp_re.group(1)
    • versionNum = temp_re.group(2)
    • if citeTimes == '':
    •   citeTimes = '0'
    • if versionNum == '':
    •   versionNum = '0'
    • citedPaper_href = soup.html.body.find('div', {'class' : 'gs_fl'}).a.attrs[0][1]/ e3 Q* a. U* r8 x$ y/ e& F+ t
    - t0 C! O4 f6 T4 d
    复制代码4 s: k# w9 M& E+ Q+ G" b

    : p5 P' D% s: `; w9 P这些都是我在一个分析citation network的项目的代码。顺便一提,我从google scholar上抓取paper的信息以及引用列表的信息,访问了大概1900次左右的时候给google block了,导致这个片区的ip一时无法登陆google scholar。
    & N9 j9 }! b$ T, N8 }
    / E& ?6 w/ D: j- w" q6 @7 U8 Z; q步骤四:存取数据
    # {) o' S+ u% F2 n3 j" z# Y4 m好不容易抓了数据,现在只是存储在内存中,必须保存起来才能利用。& i; }' P0 K4 P, k2 G  S" V
    (1) 最简单的方法之把数据写进txt文件中,Python中可以用如下代码实现:
    8 O+ g* W, F: s" l4 E/ l+ L- R  o  N
    • # 打开文件webdata.txt,生成对象file,这个文件可以是不存在的,参数a表示往里面添加。
    • # 还有别的参数,比如'r'只能读但不能写入,'w'可以写入但是会删除原来的记录等等
    • file = open('webdata.txt','a')
    • line = paper_name + '#' + paper_author + '#' + paper_desc + '#' + citeTimes + '\n'
    • # 对象file的write方法将字符串line写入file中
    • file = file.write(line)
    • # 再一次的,做个随手关闭文件的好青年
    • file.close()7 p1 U) A5 j* ~
    ! t$ V+ p5 ~3 m$ w, a8 V4 A+ [6 o
    复制代码2 @3 s; }# u* U2 H) o
    这样,就把从网页上抓到并且解析了的数据存储到本地了,是不是很简单?
    7 n) B5 I. Z: x0 A* p(2) 当然,你也可以不写入txt文件中,而是直接连接数据库,python中的MySQLdb模块可以实现和MySQL数据库的交互,把数据直接倒到数据库里面,与MySQL数据库建立链接的逻辑和与网站服务器建立链接的逻辑差不多。如果之前有学习过数据库,学习用MySQLdb模块实现和数据库的交互是很简单的;如果没有,则要借助在coursera\stanford openEdX平台上都有开设的Introduction to Database来系统学习,w3school用来参考或者当成手册。% \" g% `3 v& i
    Python能够链接数据库的前提是数据库是开着的,我用的是 win7 + MySQL5.5,数据库在本地。
    3 i; z0 ^' E: C: N9 @7 [% R
    • %可以用cmd开启数据库,启动命令是:
    • net start mysql55
    • %关闭命令是:
    • net stop mysql55
      9 s, n' w1 E( V8 i; E  Q& u

    ! `* G) {6 a0 O复制代码
    ! \* @7 ~' s: z5 w使用MySQLdb模块代码示例:( P* q- X" s) o8 C+ Q3 _& Z
    • # 导入 MySQLdb模块
    • import MySQLdb
    • # 和服务器建立链接,host是服务器ip,我的MySQL数据库搭建在本机,默认的是127.0.0.1,
    • # 用户、密码、数据库名称对应着照输就行了,默认的端口号是3306,charset是编码方式,
    • # 默认的是utf8(也有可能是gbk,看安装的版本)。
    • conn = MySQLdb.connect(host='127.0.0.1', user='root', passwd='yourPassword', db='dbname', port=3306, charset='utf8')
    • # 建立cursor
    • cur = conn.cursor()
    • # 通过对象cur的execute()方法执行SQL语句
    • cur.execute("select * from citeRelation where paperName = 'On Random Graph'")
    • # fetchall()方法获得查询结果,返回的是一个list,可以直接这样查询:list[j],
    • # i表示查询结果中的第i+1条record,j表示这条记录的第j+1个attribute(别忘了python从0开始计数)
    • list = cur.fetchall()
    • # 也可以进行delete,drop,insert,update等操作,比如:
    • sql = "update studentCourseRecord set fail = 1 where studentID = '%s' and semesterID = '%s' and courseID = '%s'" %(studentID,course[0],course[1])
    • cur.execute(sql)
    • # 与查询不同的是,执行完delete,insert,update这些语句后必须执行下面的命令才能成功更新数据库
    • conn.commit()
    • # 一如既往的,用完了之后记得关闭cursor,然后关闭链接
    • cur.close()
    • conn.close()( \, k$ A4 i- X, T$ o2 r
    ! K5 ~$ u6 L- h
    复制代码0 ?  N* h2 y& Q2 o9 z$ ?) G9 a5 G
    * V' L6 i$ D1 D
    这样就实现了Python和数据库之间的交互。除了MySQL数据库外,python的PyGreSQL模块可以支持postgreSQL数据库,道理类似的。还有,如果你的网页里面包含了中文,设置编码格式会非常的麻烦,需要服务器、Python、数据库和数据库界面采用相同的编码格式才能不出现乱码,如果真的出现了中文乱码的问题,请相信,你不是一个人!!去google一下吧,成千上万的人碰到过这种问题。. V0 v* O& ^- U" N# w8 X
    关于编码的问题,附一篇我看到的博文<python编码问题总结>:3 q2 K* h0 q$ g6 s! x6 z/ ?  b7 _- s# ^0 U
    http://www.xprogrammer.com/1258.html
    , |5 j2 f: T9 o5 Z, F7 w' q6 _7 P) W- \6 P
    后记:
    : {) p/ X) w7 v8 N/ m/ |. h上面介绍了抓取网页数据的方法,抓取数据只是一小步,如何分析数据就是大学问了,欢迎讨论。
    ' o3 n' P" |& Z$ Y$ ~上面有什么地方讲不清楚的,欢迎交流。
    ) w' g' [! U- t$ ^3 M. u1 P! _7 K1 ?" r: g- P- `  n/ p, J
    特别注意:$ s+ F4 Y0 k& C9 L# G: l' \
    大规模抓取网站会给网站的服务器带来很大的压力,尽量选择服务器相对轻松的时段(比如凌晨)。网站很多,不要拿一亩三分地来做试验。  |; R1 ^! ]. }1 x' J. j
    Python的time模块的sleep()方法可以让程序暂停一段时间,比如time.sleep(1)让程序运行到这里的时候暂停1秒。适时地暂停可以缓解服务器的压力,也可以保护自己的硬盘,正好码久了睡个觉,或者去趟gym,结果就出来了。
    5 r' Y/ T8 c6 ?% v& U* \
    ' J! Z+ C& d5 j% r0 B) l
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信

    0

    主题

    10

    听众

    24

    积分

    升级  20%

  • TA的每日心情
    奋斗
    2015-12-30 10:29
  • 签到天数: 2 天

    [LV.1]初来乍到

    自我介绍
    来此求学

    社区QQ达人

    回复

    使用道具 举报

    孤星亘        

    0

    主题

    12

    听众

    50

    积分

    升级  47.37%

  • TA的每日心情
    开心
    2018-6-16 11:44
  • 签到天数: 10 天

    [LV.3]偶尔看看II

  • TA的关系
  • 邮箱绑定达人

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2025-9-18 07:47 , Processed in 0.570368 second(s), 65 queries .

    回顶部