Python基础学习----网页爬虫

时间:2021-07-20 06:33:28

Python进行网页内容的爬取,首先需要将网页内容下载到本地,再针对特定网页内容的结构进行网页内容的解析,获得需要的数据。

(1).网页下载

Python常用的网页下载的库有,urllib2(标准库)和Requests(第三方库),下面主要使用urllib2进行网页的下载:

【方法一】

import urllib2

url = "https://www.baidu.com/"

print "方法一"
response = urllib2.urlopen(url)
print response.getcode(), len(response.read()) # getcode()获得请求的状态码
【方法二】

有些网页的访问需要传入特殊的参数,或网站本身对访问者有一定的限制:

print "方法二"
request = urllib2.Request(url)
request.add_header('user-agent', 'Mozilla/5.0') # 伪装成浏览器访问网站
response = urllib2.urlopen(request)
print response.getcode(), len(response.read())
【方法三】

有些网站的访问需要特殊场景的处理器:

e.g. HTTPCookieProcessor(网站的Cookie),ProxyHandler(网站访问需要的代理),HttpsHandler(网站需要Https加密),HttpRedirectHandler(网页链接之间的跳转有自身url限制)

print '方法三'
import cookielib
# 创建一个Cookie容器
cj = cookielib.CookieJar()
# 创建一个场景处理器
handler = urllib2.HTTPCookieProcessor(cj)
# 创建opener
opener = urllib2.build_opener(handler)
# urllib2安装opener
urllib2.install_opener(opener)

response = urllib2.urlopen(url)
print response.getcode(), len(response.read())
print cj # 打印Cookie的内容

【说明一】

有些网站做了一些特殊处理,禁止爬虫爬取网站信息,此时我们可以通过调用request的add_header(key, value)方法,将爬虫伪装成正常的浏览器访问,我们通过查看访问百度首页的request的头信息:

Python基础学习----网页爬虫

可以看到request的头信息中包含很多内容,需要伪装爬虫,就需要设置User-Agent这一项:

# coding=utf-8
import urllib2

url = 'http://blog.csdn.net/tianmaxingkong_/article/details/52934658'
request = urllib2.Request(url)
request.add_header('user-agent', 'Mozilla/5.0') # 设置User-Agent
request.add_header('Origin', 'http://www.baidu.com') # 设置跳转网页的链接
response = urllib2.urlopen(request)
上面除了设置User-Agent这个头信息,还设置了Origin这个头信息,有些网站为防止第三方网站的链接访问,会检查Origin这一项是否内本网站链接,基于此,有时候还需要为request的头信息中设置这一项,表示当前的访问是从Origin导过来的。

【注意】当我们的爬虫访问网站而被Forbidden的时候,往往是由于网站本身通过对访问信息的比对,禁止了爬虫的访问,此时我们可以通过浏览器正常访问,并查看浏览器访问时所携带的header和body的信息,从而在爬虫中添加这些信息就可以了。


【说明二】

爬虫在访问网站的时候,有可能需要以post的方式携带一些数据:(账号信息)

# coding=utf-8
import urllib2

url = 'http://xxxx.login.php'
request = urllib2.Request(url)

postData = urllib2.parse.urlencode([
('account', '155555@qq.com'),
('password', '1234567890'),
('loginTime', '2016-10-24 12:31:21 1249')
])

request.add_header('User-Agent', 'Mozilla/5.0')
request.add_header('Origin', 'http://xxxx/firstPage.php')

# post方式携带
response = urllib2.urlopen(request, data=postData.encode('utf-8'))

print response.getcode()


(2).网页内容解析

Python常用的网页解析有:

-|  正则表达式,

-|  html.parser  网页解析器

-|  BeautifulSoup(第三方库,可以使用html.parser或lxml解析器进行解析)

-|  lxml 第三方网页解析器


下面使用BeautifulSoup进行网页解析。

BeautifulSoup开发者文档:

    https://www.crummy.com/software/BeautifulSoup/bs4/doc/

中文文档:

    https://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html

BeautifulSoup的安装:

#方法一
pip install beautifulsoup4

#方法二
sudo apt-get install python-bs4


展示使用BeautifulSoup第三方库进行网页内容解析:

($)首先是下载网页的内容,使用urllib2进行网页内容的下载,并将网页内容装载到html_doc中,以便之后去解析。

# coding=utf-8
import urllib2

# 将要爬去的网页链接
root_url = 'http://baike.baidu.com/view/21087.htm'
# 下载网页内容
response = urllib2.urlopen(root_url)
html_code = response.getcode() # 网页状态码
html_doc = response.read() # 网页的内容
print html_code, html_doc

BeautifulSoup模块是将html页面内容构建成一个DOM树的对象,通过find_all(name, attrs, string)方法和find(name, attrs, string)来进行DOM树节点的搜索,

*|  find_all(name, attrs, string)  查找DOM树中所有符合条件的节点;

*|  find(name, sttrs, string) 查找DOM树中首个符合条件的节点;

【参数说明】name: 标签的名称; attrs:标签的属性和属性值;string:标签的文字。


($)爬取网页中所有<a>标签节点

# html_doc是通过urllib2模块下载百度百科的网页内容
from bs4 import BeautifulSoup

# 创建一个bs4对象,html.parser为解析器,from_encoding指定了解析的编码格式
soup = BeautifulSoup(html_doc, 'html.parser', from_encoding='utf8')

# 通过DOM树树对象,得到所有标签<a>节点
links = soup.find_all('a');

for link in links:
# 分别打印每一个节点的名称,节点href的属性值,节点的文字信息
try:
name = link.name # 获取标签的名称的方法
link_href = link['href'] # 获取标签的某一属性的属性值的方法,href属性值
text = link.get_text() # 获取标签文字信息的方法
print name, link_href, text
except:
print 'fall'
打印结果:
a /view/2561555.htm 计算机程序设计语言
a /view/2975166.htm Guido van Rossum
a /view/20965.htm *软件
a /subview/60376/5122159.htm 源代码
a /view/592974.htm 解释器
a /view/130692.htm GPL
a /view/36272.htm GNU
fall
a /view/2993364.htm 胶水语言
a /subview/10075/6770152.htm C
a /view/824.htm C++
a /view/330120.htm 应用程序
a /view/10598.htm MATLAB
fall
fall
#............此处省略多个打印结果.................
a javascript:; 编辑
a #ref_[1]_21087
【说明】通过调用BeautifulSoup对象的find_all('a')方法,获取到DOM树中所有<a>标签节点,因为网页中<a>标签有各种作用,所以上面的打印结果有好多种情况,但是有一种<a>标签的href的属性值为 /view/数字.htm 的,是该网页中包含的其他词条的链接。


($)爬取网页中包含的词条节点

【说明】查看原网页的信息可以发现,网页中词条节点的特点为,都是<a>标签,href属性的值类似于 /view/数字.htm 的格式,根据这样的特点,可以:

# html_doc是通过urllib2模块下载百度百科的网页内容
from bs4 import BeautifulSoup

# 创建一个bs4对象,html.parser为解析器,from_encoding指定了解析的编码格式
soup = BeautifulSoup(html_doc, 'html.parser', from_encoding='utf8')

# 通过正则表达式来进行匹配
import re
pattern = re.compile('/view/\d*\.htm')

links = soup.find_all('a', href=pattern)

print len(links)

for link in links:
link_name = link.name # 获取标签名称的方法
link_href = link['href'] # 获取标签某一属性的属性值的方法
link_text = link.get_text() # 获取标签的文字内容的方法
print link_name, link_href, link_text
打印结果:
/usr/bin/python2.7 /home/mxd/文档/WorkPlace/python/PythonStudy/test.py
114
a /view/10812319.htm 锁定
a /view/2561555.htm 计算机程序设计语言
a /view/2975166.htm Guido van Rossum
a /view/20965.htm *软件
a /view/592974.htm 解释器
a /view/130692.htm GPL
a /view/36272.htm GNU
a /view/2993364.htm 胶水语言
# ...............................................此处省略很多行打印结果......................................
a /view/845405.htm Unix shell
a /view/4373007.htm TIOBE
a /view/1020193.htm 卡耐基梅隆大学
a /view/159864.htm 接口
a /view/1343775.htm OpenCV
a /view/330120.htm 应用程序
a /view/10598.htm MATLAB
a /view/119481.htm 界面设计

Process finished with exit code 0

($)抓取网页中某一词条的节点

# html_doc是通过urllib2模块下载百度百科的网页内容
from bs4 import BeautifulSoup

# 创建一个bs4对象,html.parser为解析器,from_encoding指定了解析的编码格式
soup = BeautifulSoup(html_doc, 'html.parser', from_encoding='utf8')

# 抓取 href='/view/330120.htm'的节点
link_node = soup.find('a', href='/view/330120.htm')

name_link = link_node.name # 获取节点名称的方法
href_link = link_node['href'] # 获取节点某一属性的属性值的方法
text_link = link_node.get_text() # 获取节点文字内容的方法

print name_link, href_link, text_link
打印结果:

/usr/bin/python2.7 /home/mxd/文档/WorkPlace/python/PythonStudy/test.py
a /view/330120.htm 应用程序

Process finished with exit code 0


($)爬取网页中包含class属性的节点

【说明】查看网页的内容,会发现如下的节点,包含class这样的属性,因为class为Python的关键字,因此在抓取的时候,需要指定class属性的时候,使用class_,以便于Python的关键字区分:

Python基础学习----网页爬虫

from bs4 import BeautifulSoup

# 创建一个bs4对象,html.parser为解析器,from_encoding指定了解析的编码格式
soup = BeautifulSoup(html_doc, 'html.parser', from_encoding='utf8')

# 要抓取的节点 <a class="logo cmn-inline-block" title="到百科首页" href="/">
link_node = soup.find('a', class_='logo cmn-inline-block')

node_title = link_node['title']
print node_title
打印结果:
/usr/bin/python2.7 /home/mxd/文档/WorkPlace/python/PythonStudy/test.py
到百科首页

Process finished with exit code 0