搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > 我爱学Python > 一个Python小白5个小时爬虫经历

一个Python小白5个小时爬虫经历

我爱学Python 2017-10-30


前言

最近业余在做一个基于.NET Core的搜索项目,奈何基层代码写好了,没有看起来很华丽的数据供测试。很巧的也是博客搜索,于是乎想到了博客园。C#也能做做页面数据抓取的,不过在博客园看到的大部分都是python实现,所以就临时想了一下看看python到底是什么东东,不看基础语法,不看语言功能,直接上代码,哪里不会搜哪里。代码完成总共用时大概4个小时,其中搭建环境加安装BeautifulSoup大概1个小时。解析HTML用时间最多了,边看demo边解析,大概2个小时,剩下的时间就是调试加保存数据了。

环境搭建

既然用python,那么自然少不了语言环境。于是乎到官网下载了3.5版本的。安装完之后,随机选择了一个编辑器叫PyCharm,话说python编辑器还真挺多的。由于本人是小白,所以安装事项不在过多赘述。

建好项目,打开编辑器,直接开工。本来之前用C#写的时候,大体思路就是获取网页内容,然后正则匹配。后来发现网上的帖子也很多。不过在搜索过程中发现,不建议用正则来匹配HTML。有正好我的正则不太好,所以我就搜了一下HTML解析工具,果不其然,人家都做好了,直接拿来用吧。没错就是这个东东:BeautifulSoup 。安装也很简单,不过中间出了个小插曲,就是bs4没有。继续搜,然后需要用pip安装一下就好了。(当然我并不知道ps4和pip是什么鬼)

思路分析

博客吗,我当然就对准了博客园,于是乎,进入博客园首页,查看请求。

发送请求

当然我不知道python是怎么进行网络请求的,其中还有什么2.0和3.0的不同,中间曲曲折折了不少,最终还是写出了最简单的一段请求代码。


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

import urllib.parse

import urllib.request

 

# params  CategoryId=808 CategoryType=SiteHome ItemListActionName=PostList PageIndex=3 ParentCategoryId=0 TotalPostCount=4000

def getHtml(url,values):

    user_agent='Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'

    headers = {'User-Agent':user_agent}

    data = urllib.parse.urlencode(values)

    response_result = urllib.request.urlopen(url+'?'+data).read()

    html = response_result.decode('utf-8')

    return html

 

#获取数据

def requestCnblogs(index):

    print('请求数据')

    url = 'http://www.cnblogs.com/mvc/AggSite/PostList.aspx'

    value= {

         'CategoryId':808,

         'CategoryType' : 'SiteHome',

         'ItemListActionName' :'PostList',

         'PageIndex' : index,

         'ParentCategoryId' : 0,

        'TotalPostCount' : 4000

    }

    result = getHtml(url,value)

    return result

其实博客园这个请求还是挺标准的,哈哈正好适合抓取。因为他返回的就是一段html。(如果返回json那不是更好。。。。)

数据解析

上文已经提到了,用到的是BeautifulSoup,好处就是不用自己写正则,只要根据他的语法来写就好了,在多次的测试之后终于完成了数据的解析。先上一段HTML。然后在对应下面的代码,也许看起来更轻松一些。


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

<div class="post_item">

    <div class="digg">

        <div class="diggit" onclick="DiggPost('hyper-xl',6417741,281238,1)">

            <span class="diggnum" id="digg_count_6417741">1</span>

        </div>

        <div class="clear"></div>

        <div id="digg_tip_6417741" class="digg_tip"></div>

    </div>

    <div class="post_item_body">

        <h3><a class="titlelnk" href="http://www.cnblogs.com/hyper-xl/p/6417741.html" target="_blank">Python 字符串格式化</a></h3>

 

 

        <p class="post_item_summary">

            <a href="http://www.cnblogs.com/hyper-xl/" target="_blank">

                <img width="48" height="48" class="pfs"

                     src="//pic.cnblogs.com/face/795666/20160421231717.png" alt="" />

            </a>    转载请注明出处 Python2.6+ 增加了str.format函数,用来代替原有的'%'操作符

 

            。它使用比'%'更加直观、灵活。下面详细介绍一下它的使用方法。 下面是使用'%'的例子: 格式很像C语言的printf是不是?由于'%'是一个操作符,只能在左右

 

            两边各放一个参数,因此右边多个值需要用元组或 ...

        </p>

 

        <div class="post_item_foot">

            <a href="http://www.cnblogs.com/hyper-xl/" class="lightblue">新月的力量_141</a>

            发布于 2017-02-19 23:07

            <span class="article_comment">

                <a href="http://www.cnblogs.com/hyper-xl/p/6417741.html#commentform" title="" class="gray">

                    评论(0)

                </a>

            </span>

            <span class="article_view">

                <a href="http://www.cnblogs.com/hyper-xl/p/6417741.html" class="gray">

                    阅读

 

                    (138)

                </a>

            </span>

        </div>

    </div>

    <div class="clear"></div>

</div>

通过上文的HTML代码可以看到几点。首先每一条数据都在 div(class=”post_item”)下。然后 div(“post_item_body”)下有用户信息,标题,链接,简介等信息。逐一根据样式解析即可。代码如下:


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

from bs4 import BeautifulSoup

import request

import re

 

#解析最外层

def blogParser(index):

 

  cnblogs = request.requestCnblogs(index)

  soup = BeautifulSoup(cnblogs, 'html.parser')

  all_div = soup.find_all('div', attrs={'class': 'post_item_body'}, limit=20)

 

  blogs = []

  #循环div获取详细信息

  for item in all_div:

      blog = analyzeBlog(item)

      blogs.append(blog)

 

  return blogs

 

#解析每一条数据

def analyzeBlog(item):

    result = {}

    a_title = find_all(item,'a','titlelnk')

    if a_title is not None:

        # 博客标题

        result["title"] = a_title[0].string

        # 博客链接

        result["href"] = a_title[0]['href']

    p_summary = find_all(item,'p','post_item_summary')

    if p_summary is not None:

        # 简介

        result["summary"] = p_summary[0].text

    footers = find_all(item,'div','post_item_foot')

    footer = footers[0]

    # 作者

    result["author"] = footer.a.string

    # 作者url

    result["author_url"] = footer.a['href']

    str = footer.text

    time = re.findall(r"发布于 .+? .+? ", str)

    result["create_time"] = time[0].replace('发布于 ','')

 

    comment_str = find_all(footer,'span','article_comment')[0].a.string

    result["comment_num"] = re.search(r'\d+', comment_str).group()

 

    view_str = find_all(footer,'span','article_view')[0].a.string

    result["view_num"] = re.search(r'\d+', view_str).group()

 

    return result

 

def find_all(item,attr,c):

    return item.find_all(attr,attrs={'class':c},limit=1)

上边一堆代码下来,着实花费了我不少时间,边写边调试,边百度~~不过还好最终还是出来了。等数据都整理好之后,然后我把它保存到了txt文件里面,以供其他语言来处理。本来想写个put直接put到ElasticSearch中,奈何没成功。后边在试吧,毕竟我的重点只是导数据,不在抓取这里。


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

import match

import os

import datetime

import json

 

def writeToTxt(list_name,file_path):

    try:

        #这里直接write item 即可,不要自己给序列化在写入,会导致json格式不正确的问题

        fp = open(file_path,"w+",encoding='utf-8')

        l = len(list_name)

        i = 0

        fp.write('[')

        for item in list_name:

            fp.write(item)

            if i<l-1:

                fp.write(',\n')

            

版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《一个Python小白5个小时爬虫经历》的版权归原作者「Python热爱者」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注Python热爱者微信公众号

Python热爱者微信公众号:Python-520

Python热爱者

手机扫描上方二维码即可关注Python热爱者微信公众号

Python热爱者最新文章

精品公众号随机推荐

下一篇 >>

Python note_字符串