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