Ps:本文是关于Py爬虫的基础使用,若网站侵权请邮箱联系删除。

准备工具

  • Python3
  • BeautifulSoup包

分析网页

233网校会定期推送一些二级考试题目,属于纯文本型。


我们使用网页查看器来查看网页结构,可以看到题目和每个选项以及答案的分布

我们可以看到他们在 class="newsArea-2nd-PageWord" 的 div 下,并且我们可以观察到这些网址的顺序特征

http://www.233.com/ncre2/Office/moniti/ http://www.233.com/ncre2/Office/moniti/index02.html http://www.233.com/ncre2/Office/moniti/index03.html ...

并且我们可以看到这些网址又属于哪些块下,稍后我们将提取它们

我们先来考虑一个页面的数据提取:

    req = urllib.request.Request(url=url, headers=headers)
    res = urllib.request.urlopen(req)
    res.encoding = 'utf-8'
    data = res.read()

以上是请求方式和返回数据的获取,需要导入 import urllib.request ,并且注意将 response 的编码格式设置为utf-8,以保证中文信息的正确显示。最后将返回内容提取到一个变量中,即 res.read()
但是当你此刻打印 data 时候,会发现data中存储的是整个页面的内容,此时我们就要用到 BeautifulSoup 来解析内容了。

Parser | 方法 | 优点 | 缺点 – | – | – | – Python’s html.parser | BeautifulSoup(markup,“html.parser”) | python自身带有
速度比较快 | 不能很好地兼容(Python 2.7.3 or 3.2.2之前) lxml’s HTML parser | BeautifulSoup(markup,“lxml”) | 速度很快
兼容性好 | lxml只会局部遍历 html5lib | BeautifulSoup(markup, “html5lib”) | 兼容性很好
可以像web浏览器一样解析html页面
Creates valid HTML5 | 速度很慢

这里我们选择Python’s html.parser就足够了。当然我们要先from bs4 import BeautifulSoup

接着我们就是要在一个链接列表页面获取到每个链接,

lista = []
lista = soup.select('ul.fl.f14.list-box.best-list.mt10 li a')

这里有些坑坑,当一个 class 样式的名字中包含空格时,比如此处class=“tip-box content bgf9 mt20 “,我们使用 soup 解析时候就要将空格替换为点,紧接着用空格隔开他的子级标签。即可获取到当前标签下的内容。当然 我们是用数组存放的。

同理,我们将获取到的这些链接再用一个数组存放起来:

urls = []
    for li in lista:
        urls.append(li['href'])

取出li中的每个href,并存放

紧接着便是对每个链接进行请求,并从返回的html中解析出我们需要的内容:

    for r in urls:
        req = urllib.request.Request(url=r, headers=headers)
        res = urllib.request.urlopen(req)
        data = res.read()
        soup = BeautifulSoup(data, "html.parser")
        name = soup.select('h2')
        listp = []
        listp = soup.select('.newsArea-2nd-PageWord p')
        if (name[0].text == "网校课程" or len(name) == 0):
            name = soup.select('.news-con-blk h1')
            listp = soup.select('.news-body p')
        sdata = []
        for p in listp:
            sdata.append(p.text)
        s = '\n'.join(sdata)

        saveFile(s, name[0].text)
        print(name[0].text + "保存成功")
        time.sleep(1)

这里我们需要自己再去分析网页结构了,我这里中间还加了部分判断内容,是因为在爬虫运行到第9个网站时候,它的网页结构发生了变化,题目都存在了与之前不同的标签中标签中。我们爬取数据自然是要存在文件中,最常用的一是写入数据库,二就是存入文件,写入数据库没什么好有歧义的,sql语句拼接就好。存入文件也十分简单:

def saveFile(data, name):
    path = "E:\\sxks\\JavaProblems\\" + name + ".txt"
    print(path)
    data = data.encode('utf-8')
    f = open(path, 'wb+')
    f.write(data)
    f.close()

这里我直接讲将链接的题目作为文件名存储了。对单个链接页面的处理就结束了,我们想要爬取多个页面的自然只是获取了链接存入数组遍历即可。

重要的说在这里

差点漏了一点,那就是在请求的时候,我们需要伪造请求头,即我们需要将自己伪装成一个浏览器,否则在对大多网站请求的时候,很容易就会被识破。这里只需要定义

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
    req = urllib.request.Request(url=url, headers=headers)

请求时候使用即可。

另外一点可说的就是,最好在请求时候适当的使用time.sleep(1),使请求不是那么频繁,不易被察觉。

完整源码Github