Python爬虫实战.docx

上传人:b****8 文档编号:30509691 上传时间:2023-08-16 格式:DOCX 页数:46 大小:3.82MB
下载 相关 举报
Python爬虫实战.docx_第1页
第1页 / 共46页
Python爬虫实战.docx_第2页
第2页 / 共46页
Python爬虫实战.docx_第3页
第3页 / 共46页
Python爬虫实战.docx_第4页
第4页 / 共46页
Python爬虫实战.docx_第5页
第5页 / 共46页
点击查看更多>>
下载资源
资源描述

Python爬虫实战.docx

《Python爬虫实战.docx》由会员分享,可在线阅读,更多相关《Python爬虫实战.docx(46页珍藏版)》请在冰豆网上搜索。

Python爬虫实战.docx

Python爬虫实战

Python爬虫实战

Python爬虫实战

(1):

爬取糗事百科段子

大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子.

首先,糗事百科大家都听说过吧?

糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来。

本篇目标

1.抓取糗事百科热门段子

2.过滤带有图片的段子

3。

实现每按一次回车显示一个段子的发布时间,发布人,段子内容,点赞数。

糗事百科是不需要登录的,所以也没必要用到Cookie,另外糗事百科有的段子是附图的,我们把图抓下来图片不便于显示,那么我们就尝试过滤掉有图的段子吧.

好,现在我们尝试抓取一下糗事百科的热门段子吧,每按下一次回车我们显示一个段子。

1。

确定URL并抓取页面代码

首先我们确定好页面的URL是,其中最后一个数字1代表页数,我们可以传入不同的值来获得某一页的段子内容。

我们初步构建如下的代码来打印页面代码内容试试看,先构造最基本的页面抓取方式,看看会不会成功

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#—*-coding:

utf—8—*—

importurllib

importurllib2

 

 

page=1

url='’+str(page)

try:

    request=urllib2。

Request(url)

    response=urllib2.urlopen(request)

    printresponse.read()

excepturllib2.URLError,e:

    ifhasattr(e,"code"):

        printe。

code

    ifhasattr(e,”reason”):

        printe.reason

运行程序,哦不,它竟然报错了,真是时运不济,命途多舛啊

1

2

3

line373,in_read_status

 raiseBadStatusLine(line)

httplib。

BadStatusLine:

'’

好吧,应该是headers验证的问题,我们加上一个headers验证试试看吧,将代码修改如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#—*-coding:

utf-8-*-

importurllib

importurllib2

 

page=1

url=’'+str(page)

user_agent=’Mozilla/4.0(compatible;MSIE5。

5;WindowsNT)’

headers={'User-Agent’:

user_agent}

try:

    request=urllib2.Request(url,headers=headers)

    response=urllib2.urlopen(request)

    printresponse.read()

excepturllib2.URLError,e:

    ifhasattr(e,”code”):

        printe.code

    ifhasattr(e,"reason"):

        printe。

reason

嘿嘿,这次运行终于正常了,打印出了第一页的HTML代码,大家可以运行下代码试试看。

在这里运行结果太长就不贴了。

2。

提取某一页的所有段子

好,获取了HTML代码之后,我们开始分析怎样获取某一页的所有段子。

首先我们审查元素看一下,按浏览器的F12,截图如下

我们可以看到,每一个段子都是包裹的内容。

现在我们想获取发布人,发布日期,段子内容,以及点赞的个数.不过另外注意的是,段子有些是带图片的,如果我们想在显示图片是不现实的,所以我们直接把带有图片的段子给它剔除掉,只保存仅含文本的段子。

所以我们加入如下正则表达式来匹配一下,用到的方法是re.findall是找寻所有匹配的内容。

方法的用法详情可以看前面说的正则表达式的介绍。

好,我们的正则表达式匹配语句书写如下,在原来的基础上追加如下代码

1

2

3

4

5

6

content=response.read()。

decode(’utf-8')

pattern=re。

compile(’〈div.*?

class=”author。

*?

〉。

*?

*?

.*?

〉(。

*?

)〈/a>。

*?

class'+

                     ’="content"。

*?

title=”(.*?

)”>(.*?

)〈/div〉(.*?

class="number”>(.*?

)〈/i〉’,re.S)

items=re.findall(pattern,content)

foriteminitems:

    printitem[0],item[1],item[2],item[3],item[4]

现在正则表达式在这里稍作说明

1).*?

是一个固定的搭配,。

和*代表可以匹配任意无限多个字符,加上?

表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到。

*?

的搭配。

2)(。

*?

)代表一个分组,在这个正则表达式中我们匹配了五个分组,在后面的遍历item中,item[0]就代表第一个(。

*?

)所指代的内容,item[1]就代表第二个(.*?

)所指代的内容,以此类推。

3)re。

S标志代表在匹配时为点任意匹配模式,点。

也可以代表换行符。

现在我们可以看一下部分运行结果

儒雅男神2015—02—1714:

34:

42

小时候一个一个拆着放的举个爪…

〈divclass="thumb”〉

list=hot&s=4747301″ =”_blank”onclick=”_hmt.push([‘_trackEvent’,‘post’,‘click’,‘signlePost’])”〉

〈/div>

7093

奇怪的名字啊2015—02-1714:

49:

16

回家的路,你追我赶,回家的心情和窗外的阳光一样灿烂。

一路向前,离亲人越来越近了。

哪里有爸妈哪里才是家,希望所有糗友的爸爸妈妈都身体健康…….

4803

这是其中的两个段子,分别打印了发布人,发布时间,发布内容,附加图片以及点赞数.

其中,附加图片的内容我把图片代码整体抠了出来,这个对应item[3],所以我们只需要进一步判断item[3]里面是否含有img这个字样就可以进行过滤了.

好,我们再把上述代码中的for循环改为下面的样子

1

2

3

4

foriteminitems:

        haveImg=re。

search(”img",item[3])

        ifnothaveImg:

            printitem[0],item[1],item[2],item[4]

现在,整体的代码如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

#—*—coding:

utf—8—*-

importurllib

importurllib2

importre

 

page=1

url=’'+str(page)

user_agent=’Mozilla/4.0(compatible;MSIE5.5;WindowsNT)’

headers={'User-Agent’:

user_agent}

try:

    request=urllib2。

Request(url,headers=headers)

    response=urllib2.urlopen(request)

    content=response.read().decode(’utf-8’)

    pattern=re。

compile(’〈div。

*?

class="author.*?

>。

*?

〈a.*?

〈a.*?

>(。

*?

)〈/a〉.*?

class’+

                         '="content”。

*?

title="(.*?

)”〉(.*?

*?

class="number”>(。

*?

)〈/i〉',re。

S)

    items=re。

findall(pattern,content)

    foriteminitems:

        haveImg=re。

search("img”,item[3])

        ifnothaveImg:

            printitem[0],item[1],item[2],item[4]

excepturllib2。

URLError,e:

    ifhasattr(e,"code"):

        printe。

code

    ifhasattr(e,”reason"):

        printe。

reason

运行一下看下效果

恩,带有图片的段子已经被剔除啦。

是不是很开森?

3.完善交互,设计面向对象模式

好啦,现在最核心的部分我们已经完成啦,剩下的就是修一下边边角角的东西,我们想达到的目的是:

按下回车,读取一个段子,显示出段子的发布人,发布日期,内容以及点赞个数.

另外我们需要面向对象模式,引入类和方法,将代码做一下优化和封装,最后,我们的代码如下所示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

__author__=’CQC’

#-*-coding:

utf—8—*-

importurllib

importurllib2

importre

importthread

importtime

 

#糗事百科爬虫类

classQSBK:

 

    #初始化方法,定义一些变量

    def__init__(self):

        self.pageIndex=1

        self.user_agent='Mozilla/4.0(compatible;MSIE5。

5;WindowsNT)'

        #初始化headers

        self。

headers={’User-Agent’:

self。

user_agent}

        #存放段子的变量,每一个元素是每一页的段子们

        self.stories=[]

        #存放程序是否继续运行的变量

        self。

enable=False

    #传入某一页的索引获得页面代码

    defgetPage(self,pageIndex):

        try:

            url=’'+str(pageIndex)

            #构建请求的request

            request=urllib2.Request(url,headers=self.headers)

            #利用urlopen获取页面代码

            response=urllib2。

urlopen(request)

            #将页面转化为UTF-8编码

            pageCode=response。

read()。

decode(’utf—8')

            returnpageCode

 

        excepturllib2。

URLError,e:

            ifhasattr(e,”reason”):

                printu”连接糗事百科失败,错误原因”,e.reason

                returnNone

 

 

    #传入某一页代码,返回本页不带图片的段子列表

    defgetPageItems(self,pageIndex):

        pageCode=self.getPage(pageIndex)

        ifnotpageCode:

            print”页面加载失败。

.。

"

            returnNone

        pattern=re。

compile(’

class="author.*?

〉。

*?

〈/a>.*?

〈a.*?

〉(.*?

)〈/a>.*?

class'+

                         '="content”.*?

title="(.*?

)"〉(.*?

)〈/div〉(.*?

class=”number"〉(。

*?

)〈/i〉',re.S)

        items=re。

findall(pattern,pageCode)

        #用来存储每页的段子们

        pageStories=[]

        #遍历正则表达式匹配的信息

        foriteminitems:

            #是否含有图片

            haveImg=re。

search("img",item[3])

            #如果不含有图片,把它加入list中

            ifnothaveImg:

                #item[0]是一个段子的发布者,item[1]是发布时间,item[2]是内容,item[4]是点赞数

                pageStories。

append([item[0]。

strip(),item[1].strip(),item[2]。

strip(),item[4]。

strip()])

        returnpageStories

 

    #加载并提取页面的内容,加入到列表中

    defloadPage(self):

        #如果当前未看的页数少于2页,则加载新一页

        ifself.enable==True:

            iflen(self。

stories)<2:

                #获取新一页

                pageStories=self。

getPageItems(self.pageIndex)

                #将该页的段子存放到全局list中

                ifpageStories:

                    self.stories。

append(pageStories)

                    #获取完之后页码索引加一,表示下次读取下一页

                    self。

pageIndex+=1

     

    #调用该方法,每次敲回车打印输出一个段子

    defgetOneStory(self,pageStories,page):

        #遍历一页的段子

        forstoryinpageStories:

            #等待用户输入

            input=raw_input()

            #每当输入回车一次,判断一下是否要加载新页面

            self。

loadPage()

            #如果输入Q则程序结束

            ifinput==”Q":

                self。

enable=False

                return

            printu"第%d页\t发布人:

%s\t发布时间:

%s\n%s\n赞:

%s\n”%(page,story[0],story[1],story[2],story[3])

     

    #开始方法

    defstart(self):

        printu"正在读取糗事百科,按回车查看新段子,Q退出”

        #使变量为True,程序可以正常运行

        self。

enable=True

        #先加载一页内容

        self.loadPage()

        #局部变量,控制当前读到了第几页

        nowPage=0

        whileself.enable:

            iflen(self。

stories)>0:

                #从全局list中获取一页的段子

                pageStories=self.stories[0]

                #当前读到的页数加一

                nowPage+=1

                #将全局list中第一个元素删除,因为已经取出

                delself。

stories[0]

                #输出该页的段子

                self。

getOneStory(pageStories,nowPage)

 

 

spider=QSBK()

spider。

start()

好啦,大家来吧,点一下回车会输出一个段子,包括发布人,发布时间,段子内容以及点赞数,是不是感觉爽爆了!

我们第一个爬虫实战项目介绍到这里,欢迎大家继续关注,小伙伴们加油!

Python爬虫实战

(2):

XX贴吧帖子

大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取XX贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作.

本篇目标

1.对XX贴吧的任意帖子进行抓取

2.指定是否只抓取楼主发帖内容

3。

将抓取到的内容分析并保存到文件

1。

URL格式的确定

首先,我们先观察一下XX贴吧的任意一个帖子。

比如:

,这是一个关于NBA50大的盘点,分析一下这个地址。

1

2

3

4

http:

// 代表资源传输使用http协议

tieba。

baidu。

com是XX的二级域名,指向XX贴吧的服务器。

/p/3138733512是服务器某个资源,即这个帖子的地址定位符

see_lz和pn是该URL的两个参数,分别代表了只看楼主和帖子页码,等于1表示该条件为真

所以我们可以把URL分为两部分,一部分为基础部分,一部分为参数部分。

例如,上面的URL我们划分基础部分是 ,参数部分是 

2.页面的抓取

熟悉了URL的格式,那就让我们用urllib2库来试着抓取页面内容吧。

上一篇糗事百科我们最后改成了的编码方式,这次我们直接尝试一下,定义一个类名叫BDTB(XX贴吧),一个初始化方法,一个获取页面的方法。

其中,有些帖子我们想指定给程序是否要只看楼主,所以我们把只看楼主的参数初始化放在类的初始化上,即init方法。

另外,获取页面的方法我们需要知道一个参数就是帖子页码,所以这个参数的指定我们放在该方法中.

综上,我们初步构建出基础代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

__author__='CQC’

#-*—coding:

utf—8-*-

importurllib

importurllib2

importre

 

#XX贴吧爬虫类

classBDTB:

 

    #初始化,传入基地址,是否只看楼主的参数

    def__init__(self,baseUrl,seeLZ):

        self。

baseURL=baseUrl

        self.seeLZ=’?

see_lz=’+str(seeLZ)

 

    #传入页码,获取该页帖子的代码

    defgetPage(self,pageNum):

        try:

            url=self.baseURL+self.seeLZ+’&pn=’+str(pageNum)

            request=urllib2。

Request(url)

            response=urllib2.urlopen(request)

            printresponse。

read()

            returnresponse

        excepturllib2。

URLError,e:

            ifhasattr(e,"reason”):

                printu”连接XX贴吧失败,错误原因",e.reason

                returnNone

 

baseURL=’'

bdtb=BDTB(baseURL,1)

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1