pythonPython

Python爬虫基础教程——正则表达式抓取入门

2021-03-06  本文已影响0人  那个百分十先生

大家好!本篇文章主要讲述爬虫一些需要注意的地方、开发环境以及使用正则表达来抓取网站上的信息等。

一、简单介绍

网络爬虫简单的解释就是从网站上获取相关的信息为已所用的一个自动化处理的方式;

1.1 合法性

虽然在2017年就已经开始实施《网络安全法》,但是也没有特别明确爬取公开信息的行为是否违法。

小编搜索了一下资料,自己总结了两点:

1.2 检查robots.txt文件

大家可以查看一下网站的robots.txt的文件,此文件会对爬虫有哪些限制,检查robots.txt文件可以最小化爬虫被封禁的可能,还有可能会发现和网站接口相关的线索;

知乎

csdn网站

开源中国网站

说明:

并不是所有网站都有robot.txt 文件,大家在爬虫要注意,避免网站服务器过载宕机等风险。

二、开发环境

2.1 Python3.8

大家尽量使用Python3.x版本。

2.2 VSCode开发工具

VSCode环境的搭建看一下之前的推文

大家在使用python的时候会用pip install xxx的指令去安装一些包,会遇到安装不了的情况,我总结了一下解决方案,供大家参考

  1. 尽量使用管理员打开cmd 或者vscode
  2. 到python安装路径下安装,如
    C:\Users\64385\AppData\Local\Programs\Python\Python38>
  3. 指定国内下载源下载,有很多的资源都是在国外,直接下载的会有网络网速的问题,指定国内的镜像源就会很快,如:
    pip install BeautifulSoup4 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

三、正则表达式

3.1 元字符^

如果^元字符放到[]字符集中就是反取的意思

import re

str="python知识学堂,python欢迎你"
result=re.findall('[^python]',str)#反取 匹配除‘python’以外的字符 返回值是list

print(result)

结果:

3.2 元字符*

表示匹配其前面的一个字符0次或多次

import  re
str="python知识学堂,欢迎来到学堂"
print(re.findall("知识*",str)) #星号前面的一个字符可以是0次或多次,返回值是list
print(re.findall("学堂*",str)) #星号前面的一个字符可以是0次或多次,返回值是list

结果:

3.3 元字符()

也就是分组匹配,()里面的为一个组或者说是整体

import  re
str="python知识学堂,欢迎来到学堂"
print(re.findall("(知识)",str)) 
print(re.findall("(学堂)",str)) 

结果:

下面给大家列出常用的,大家自己尝试一下

3.4 常用的元字符

3.5 常用的量词

大家也可以查看 下面网站查看学习

https://docs.python.org/2/howto/regex.html

四、re模块

4.1 re函数参数说明

4.2 re.findall(pattern,string,flags=0)

对 string 返回一个不重复的 pattern 的匹配列表, string 从左到右进行扫描,匹配按找到的顺序返回。如果样式里存在一到多个组,就返回一个组合列表;就是一个元组的列表(如果样式里有超过一个组合的话)。空匹配也会包含在结果里。

import re

text="python知识学堂,python欢迎你"

print("输入结果:")
print(re.findall(r'[a-z]',text))  #查找所有小写的字母

结果:

4.3 re.search(pattern,string,flags=0)

扫描整个 字符串 找到匹配样式的第一个位置,并返回一个相应的 匹配对象。如果没有匹配,就返回一个 None ;注意这和找到一个零长度匹配是不同的。

import re

text="python知识学堂,python欢迎你"

print("输入结果:")
print(re.search(r'[a-z]',text).group())  #只会匹配一个对象

结果:

4.4 re.match(pattern,string,flags=0)

如果 string 开始的0或者多个字符匹配到了正则表达式样式,就返回一个相应的 匹配对象 。如果没有匹配,就返回 None ;注意它跟零长度匹配是不同的。

import re

text="python知识学堂,python欢迎你"

print("输入结果:")
print(re.match(r'[a-z]',text).group())  #只会匹配一个对象

结果:

4.5 flags参数

举例给大家看一下这个参数的使用方式。

import re

text="python知识学堂,PYTHON欢迎你"

print("输入结果:")
print(re.findall('[a-z]',text,re.I)) #获取所有字母不管大小写

结果:

大家可以看到有些地方加了'r' 前缀,在带有 'r' 前缀的字符串字面值中,表示反斜杠不必做任何特殊处理。如 r"\n" 表示包含 '' 和 'n' 两个字符的字符串,而 "\n" 则表示只包含一个换行符的字符串。**建议大家习惯性加前缀'r' **。

这里只举出常用的,还有一些其他的函数,大家可以去网上搜一下资料自行学习一下。下面是官方的网址,可以参考一下

https://docs.python.org/zh-cn/3/library/re.html

下面就使用正则的方式来抓取网站上的信息

五、正则方式抓取

我们会使用到的re(正则表达式)模块 与requests(http)模块,这里我们使用效率更高一点的requests库而并不是urllib库。urllib库的使用方法大家可以百度一下。re模块是python独有的,不需要安装的。requests需要安装,如下

pip install requests

下面会使用正则表达的方法一步一步的教大家怎么去抓取网页的信息。

下面以http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2019/ 网站为例,抓取当前最新的省份为例。

5.1 F12或右击检查

F12或右击检查查看网站的元素,寻找自己需要信息的位置,并观察,如下图

点击红色箭头的位置,选择网页上的自己所需要的信息,就可以快速定位;

如图可以看到我们所需要的信息的位置以及一些特征,可能这个需要大家知道一点前端上的知识。下面就开始抓取网站上的省份信息。

5.2 第一次抓取

import re
import requests

class demo():
    def __init__(self):
        try:
            response=requests.get("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2019/")
            html=response.text #获取页面的html 
            print(html)
        except:
            print('出错了')

if __name__ == '__main__':
    demo()

结果:

大家可以看出来页面的信息已经获取到了,但是好像有点乱码。

原因是因为没有设置编码方式

5.3 第二次抓取

import re
import requests

class demo():
    def __init__(self):
        try:
            response=requests.get("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2019/")
            response.encoding='gb2312' #编码转换
            html=response.text #获取页面的html 
            print(html)
        except:
            print('出错了')

if __name__ == '__main__':
    demo()

结果:

可以看到出现了已经把网页上的信息完整的获取到了。

大家考虑一下为啥我这里用了’gb2312’而不是’utf-8’的方式?

这个取决于网站,怎么知道网站是什么编码的?右击查看网页源代码,看下图

圈出来的就是网站的编码方式了。

那么下面就从获取到的网页完整的信息中提取我们需要的信息。

5.4 第三次抓取

要获取到想要的省份信息,先观察省份信息的所在位置的特征。

可以看到省份的信息都是在td 标签内,td标签包含了一个a标签,a标签中包含了下一页的链接地址。我们先只获取省份信息。

import re
import requests

class demo():
    def __init__(self):
        try:
            response=requests.get("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2019/")
            response.encoding='gb2312' #编码转换
            html=response.text #获取页面的html 
            provincelist=re.findall(r"<td><a.*?>(.*?)<br/></a></td>",html)
            for p in provincelist:
                print(p)
        except:
            print('出错了')

if __name__ == '__main__':
    demo()

结果:

可以获取到所有省份的信息了。

如果还是想要获取二级城市数据,那么我们就要获取a标签中的下级地址,我们还要看一下二级页面我们所要信息的在页面上所在的位置以及特征(与查看省份的一致,不在赘述)。

import re
import requests
import time

class demo():
    def __init__(self):
        try:
            base_url='http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2019/'
            response=requests.get(base_url)
            response.encoding='gb2312' #编码转换
            html=response.text #获取页面的html 
            provincelist=re.findall(r"<td><a.*?>(.*?)<br/></a></td>",html)
            provinceUrls=re.findall(r"<td><a href='(.*?)'>.*?<br/></a></td>",html)
            #for p in provincelist:
            # print(p)
            for u in provinceUrls:
                #print(u)
                cityurl=base_url+u
                res=requests.get(cityurl)
                res.encoding='gb2312' #编码转换
                reshtml=res.text #获取页面的html 
                citylist=re.findall(r"<td><a.*?>(.*?)</a></td>",reshtml)
                for c in citylist:
                    print(c)
                time.sleep(0.5)    
        except:
            print('出错了')

if __name__ == '__main__':
    demo()

还顺便把二级城市的区域代码也获取到了。大家也要看到了代码里有一个time.sleep的函数,指的是在延迟,单位是秒。因为该网站是没有robots.txt的信息的,所以在爬取信息时需要注意请求间隔时间。

所以仔细观察一下网站的信息特征,不难发现,如果我们一级一级的往下找就会把所有的最新的省市区以及街道的信息都获取到,这样我们就可以很方便的获取到最新的省市区的信息了。大家可以自己尝试一下。

六、总结

爬虫第一篇推文就先介绍到这。本篇主要给大家介绍一下爬虫方面需要注意的地方、使用vscode开发环境的时候会遇到的问题以及使用正则表达式的方式简单的获取省市区。使用正则的方式抓取网页上的信息还是比较简单的,多多练习,希望大家都能爬虫成功。

上一篇下一篇

猜你喜欢

热点阅读