Python抓取网页方法,任务是批量下载网站上的文件。对于一个刚刚入门python的人来说,在很多细节上都有需要注意的地方,以下就分享一下我在初学python过程中遇到的问题及解决方法。
1、用Python抓取网页
- import urllib2,urllib
- url = 'http://www.baidu.com'
- req = urllib2.Request(url)
- content = urllib2.urlopen(req).read()
1)、url为网址,需要加'http://'
2)、content为网页的html源码
问题:
1、网站禁止爬虫,不能抓取或者抓取一定数量后封ip
解决:伪装成浏览器进行抓取,加入headers:
- import urllib2,urllib
- headers = { #伪装为浏览器抓取
- 'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'
- }
- req = urllib2.Request(url,headers=headers)
- content = urllib2.urlopen(req).read()
更复杂的情况(需要登录,多线程抓取)可参考:http://www.pythonclub.org/python-network-application/observer-spider
2、抓取网页中的中文为乱码问题
解决:用BeautifulSoup解析网页(BeautifulSoup是Python的一个用于解析网页的插件,其安装及使用方法下文会单独讨论)
首先需要介绍一下网页中的中文编码方式,一般网页的编码会在标签中标出,目前有三种,分别是GB2312,GBK,GB18030,三种编码是兼容的,
从包含的中文字符个数比较:GB2312 < GBK < GB18030,因此如果网页标称的编码为GB2312,但是实际上用到了GBK或者GB18030的中文字符,那么编码工具就会解析错误,导致编码退回到最基本的windows-2152了。所以解决此类问题分两种情况。
1)、若网页的实际的中文编码和其标出的相符的话,即没有字符超出所标称的编码,下面即可解决
- import urllib,urllib2,bs4
- req = urllib2.Request(url)
- content = urllib2.urlopen(req).read()
- content = bs4.BeautifulSoup(content)
- return content
2)、若网页中的中文字符超出所标称的编码时,需要在BeautifulSoup中传递参数from_encoding,设置为最大的编码字符集GB18030即可
- import urllib,urllib2,bs4
- req = urllib2.Request(url)
- content = urllib2.urlopen(req).read()
- content = bs4.BeautifulSoup(content,from_encoding='GB18030')
- return content
详细的中文乱码问题分析参见:http://againinput4.blog.163.com/blog/static/1727994912011111011432810/
2、用Python下载文件
使用Python下载文件的方法有很多,在此只介绍最简单的一种
- import urllib
- urllib.urlretrieve(url, filepath)
url为下载链接,filepath即为存放的文件路径 文件名
更多Python下载文件方法参见:http://outofmemory.cn/code-snippet/83/sanzhong-Python-xiazai-url-save-file-code
3、使用正则表达式分析网页
将网页源码抓取下来后,就需要分析网页,过滤出要用到的字段信息,通常的方法是用正则表达式分析网页,一个例子如下:
- import re
- content = ''
- match = re.compile(r'(?<=href=["]).*?(?=["])')
- rawlv2 = re.findall(match,content)
用re.compile()编写匹配模板,用findall查找,查找content中所有与模式match相匹配的结果,返回一个列表,上式的正则表达式意思为匹配以‘href="'起始,以'"'结束的字段,使用非贪婪的规则,只取中间的部分
关于正则表达式,系统的学习请参见:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
或 http://wiki.ubuntu.org.cn/Python正则表达式操作指南
个人推荐第一篇,条理清晰,不重不漏
在此就不赘述正则表达式的学习,只总结一下我在实际写正则时的认为需要注意的几个问题:
1)、一定要使用非贪婪模式进行匹配,即*?, ?(后加?),因为Python默认使用贪婪模式进行匹配,例如'a.*b',它会匹配文档中从第一个a和最后一个b之间的文本,也就是说如果遇到一个b,它不会停止,会一直搜索至文档末尾,直到它确认找到的b是最后一个。而一般我们只想取某个字段的值,贪婪模式既不能返回正确的结果,还大大浪费了时间,所以非贪婪是必不可少的
2)、raw字符串的使用:如果要匹配一个.,*这种元字符,就需要加'\'进行转义,即要表示一个'\',正则表达式需要多加一个转义,写成'\\',但是Python字符串又需要对其转义,最终变成re.compile('\\\\'),这样就不易理解且很乱,使用raw字符串让正则表达式变得易读,即写成re.compile(r'\\'),另一个方法就是将字符放到字符集中,即[\],效果相同
3)、()特殊构造的使用:一般来说,()中的匹配模式作为分组并可以通过标号访问,但是有一些特殊构造为例外,它们适用的情况是:我想要匹配href="xxxx"这个模式,但是我只需要xxxx的内容,而不需要前后匹配的模式,这时就可以用特殊构造(?<=),和(?=)来匹配前后文,匹配后不返回()中的内容,刚才的例子便用到了这两个构造。
4)、逻辑符的使用:如果想匹配多个模式,使用'|'来实现,比如
re.compile(r'.htm|.mid$')
匹配的就是以.htm或.mid结尾的模式,注意没有'&'逻辑运算符
3、使用BeautifulSoup分析网页
BeautifulSoup是Python的一个插件,用于解析HTML和XML,是替代正则表达式的利器,下文讲解BS4的安装过程和使用方法
1、安装BS4
下载地址:http://www.crummy.com/software/BeautifulSoup/#Download
下载 beautifulsoup4-4.1.3.tar.gz,解压:linux下 tar xvf beautifulsoup4-4.1.3.tar.gz,win7下直接解压即可
linux:
进入目录执行:
1, python setup.py build
2, python setup.py install
或者easy_install BeautifulSoup
win7:
cmd到控制台 -> 到安装目录 -> 执行上面两个语句即可
2、使用BeautifulSoup解析网页
本文只介绍一些常用功能,详细教程参见BeautifulSoup中文文档:http://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html
1)、包含包:import bs4
2)、读入:
- req = urllib2.Request(url)
- content = urllib2.urlopen(req).read()
- content = bs4.BeautifulSoup(content,from_encoding='GB18030')
3)、查找内容
a、按html标签名查找:
frameurl = content.findAll('frame')
framurl为存储所有frame标签内容的列表,例如frame[0] 为 tops.htm">
b、按标签属性查找
frameurl = content.findAll(target=True)
查找所有含target属性的标签
frameurl = content.findAll(target=‘m_rbottom’)
查找所有含target属性且值为'm_rbottom'的标签
c、带有正则表达式的查找
rawlv2 = content.findAll(href=re.compile(r'.htm$'))
查找所有含href属性且值为以'.htm'结尾的标签
d、综合查找
frameurl = content.findAll('frame',target=‘rtop’)
查找所有frame标签,且target属性值为'rtop'
4)、访问标签属性值和内容
a、访问标签属性值
- rawlv2 = content.findAll(href=re.compile(r'.htm$'))
- href = rawlv2[i]['href']
通过[属性名]即可访问属性值,如上式返回的便是href属性的值
b)、访问标签内容
- rawlv3 = content.findAll(href=re.compile(r'.mid$'))
- songname = str(rawlv3[i].text)
上式访问了(内容)标签的实际内容,由于text为unicode类型,所以需要用str()做转换
附上最终的成果,程序功能是抓取www.dugukeji.com上的所有midi文件并下载,需要先建立./midi/dugukeji/文件夹和./midi/linklist文件
- "font-size:14px;">#-*- coding:utf-8 -*- #允许文档中有中文
- import urllib2,urllib,cookielib,threading
- import os
- import re
- import bs4
- import sys
- reload(sys)
- sys.setdefaultencoding('utf-8') #允许打印unicode字符
- indexurl = 'http://www.dugukeji.com/'
- databasepath = './midi/linklist'
- path = './midi/dugukeji/'
- totalresult = {}
- oriresult = {}
- def crawl(url):
- headers = { #伪装为浏览器抓取
- 'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'
- }
- req = urllib2.Request(url,headers=headers)
- content = urllib2.urlopen(req).read()
- content = bs4.BeautifulSoup(content,from_encoding='GB18030')
- return content
- def crawlframe(sourceurl,target):
- global indexurl
- content = crawl(sourceurl)
- #match = re.compile(r'(?<=target=["]' target '["] src=["]).*?(?=["])') #正则表达式方法
- #frameurl = re.findall(match,content)
- frameurl = content.findAll('frame',target=target) #beautifulsoup方法
- result = indexurl frameurl[0]['src']
- return result
- def crawllv1(frameurl,st=-1,en=-1):
- global indexurl
- content = crawl(frameurl)
- #match = re.compile(r'(?<=href=["]).*?(?=["])')
- #rawlv2 = re.findall(match,content)
- rawlv2 = content.findAll(href=re.compile(r'.htm$'))
- result = []
- if st==-1 and en==-1:
- for i in range(len(rawlv2)):
- result.append(indexurl rawlv2[i]['href'])
- else:
- for i in range(st,en):
- result.append(indexurl rawlv2[i]['href'])
- #dele = []
- #for i in range(len(result)):
- # if result[i][-4:]!='.htm' and result[i][-5:]!='.html':
- # dele.append(i)
- # else:
- # result[i]=indexurl result[i]
- # if len(dele)>0:
- # for deli in dele:
- # del result[deli]
- #result.sort()
- return result
- def crawllv2(lv2url):
- global indexurl
- content = crawl(lv2url)
- #match = re.compile(r'(?<=href=["]\.\.\/).*?[">].*?(?=[<])')
- #rawlv3 = re.findall(match,content)
- rawlv3 = content.findAll(href=re.compile(r'[..].*?[0-9].htm|.mid$'))
- #print rawlv3
- result = {} #结果字典,key:链接,value:歌曲名
- for i in range(len(rawlv3)):
- tmp = str(rawlv3[i]['href'])
- #print tmp
- link = indexurl tmp[tmp.rfind('..') 3:] #有多个'..',找到最后一个
- songname = ''
- if tmp[-4:]=='.htm': #需要访问3级页
- try:
- conlv3 = crawl(link)
- except:
- print 'WARNING: visit lv3 url failed!\n'
- else:
- rawlv4 = conlv3.findAll(href=re.compile(r'.mid$'))
- if not rawlv4: #4级页没有.mid下载链接,略过
- continue
- else:
- tmp = str(rawlv4[0]['href'])
- link = indexurl tmp[tmp.rfind('..') 3:]
- songname = str(rawlv3[i].text) #将unicode类型的text转化为string
- #songname.decode('GBK')
- #songname.encode('utf-8')
- songname = songname.replace(' ','_') #将songname中空格和换行转化为下划线
- songname = songname.replace('\n','_') #原来存在的链接,直接略过
- if oriresult.has_key(link):
- continue
- if totalresult.has_key(link) and len(songname)#如果链接已保存且歌曲名长度比当前的长,略过
- continue
- else:
- totalresult[link] = songname
- result[link] = songname #加入字典
- #result.sort()
- return result
- def download(totalresult):
- for link in totalresult.keys():
- filepath = path totalresult[link] '.mid'
- print 'download: ',link,' -> ',filepath,'\n'
- urllib.urlretrieve(link, filepath)
- def readdata(databasepath):
- datafile = open(databasepath,'r') #读数据文件
- link = datafile.readline()
- while link:
- oriresult[link]=''
- link = datafile.readline()
- datafile.close()
- def writedata(databasepath):
- datafile = open(databasepath,'a') #追加打开数据文件,将新链接写入文件尾
- for link in totalresult.keys():
- datafile.write(link,'\n')
- datafile.close()
- if __name__ == '__main__':
- try:
- readdata(databasepath) #访问文件,记录已下载的链接
- except:
- print 'WARNING:read database file failed!\n'
- else:
- print 'There is ',len(oriresult),' links in database.\n'
- try:
- frameurl1 = crawlframe(indexurl,'rtop') #抓取主页中一级页url所在frame的url
- except:
- print 'WARNING: crawl lv1 frameurl failed!\n'
- try:
- urllv1 = crawllv1(frameurl1,4,20) #抓取一级页url
- except:
- print 'WARNING: crawl lv1 url failed!\n'
- for i in urllv1:
- print 'lv1 url:',i
- try:
- frameurl2 = crawlframe(i,'rbottom') #抓取一级页中二级页url所在frame的url
- except:
- print 'WARNING: crawl lv2 frameurl failed!\n'
- else:
- print '\tlv2 frameurl:',frameurl2
- try:
- urllv2 = crawllv1(frameurl2) #抓取二级页url
- except:
- print 'WARNING: crawl lv2 url failed!\n'
- else:
- for j in urllv2:
- print '\t\tlv2 url:',j
- try:
- urllv3 = crawllv2(j)
- except:
- print 'WARNING: crawl lv3 url failed!\n'
- else:
- for k in urllv3.keys():
- print '\t\t\tlv3 url:',k,'\tname:',urllv3[k]
- #download(urllv3)
- print 'new added midi num:',len(totalresult)
- print '\nbegin to download...\n'
- download(totalresult)
- print '\nWrite database...\n'
- writedata(databasepath)
- print '\n\nDone!\n'
- """
- url = 'http://www.dugukeji.com/'
- req = urllib2.Request(url)
- response = urllib2.urlopen(req).read()
- response = unicode(response,'GBK').encode('UTF-8')
- print response
- """
相关推荐
- 掌握Python爬虫环境的搭建,学习常见的Python爬虫库。 - 学习爬虫伦理和法规,了解如何遵守网络爬虫的行为规范。 2. **网页前端基础**(3学时) - 网络编程基础,理解Socket库,包括TCP和UDP通信。 - 学习...
这个"Python网络爬虫技术-源代码和实验数据.rar"压缩包包含了一系列的源代码示例和实验数据,旨在帮助学习者深入理解Python爬虫的工作原理与实践应用。 首先,我们来详细探讨Python网络爬虫的基础知识。Python作为...
python爬虫-beautifulsoup实践代码python爬虫-beautifulsoup实践代码
【python网络爬虫】-构建免费代理池 # 导入requests模块 import requests # 从bs4中导入BeautifulSoup模块 from bs4 import BeautifulSoup # 定义获取代理地址的方法 def get_proxy(pages, ua): # 定义proxy_ips...
【python网络爬虫】-python获取实习僧网站薪资数据 # 导入requests模块 import requests # 从bs4中导入BeautifulSoup模块 from bs4 import BeautifulSoup # 导入time模块 import time # 将User-Agent以字典键对...
Python网络爬虫是一种用于自动化网络数据抓取的技术,它能够高效地从互联网上获取大量信息。这个名为"Python网络爬虫集合-PythonApps.zip"的压缩包文件很可能包含了一系列使用Python编写的爬虫项目,旨在帮助用户...
【python网络爬虫】-制作词云图 # 使用import导入requests模块 import requests # 从bs4中导入BeautifulSoup from bs4 import BeautifulSoup # 使用import导入jieba模块 import jieba # 从pyecharts.charts中导入...
本实例“Spiders.zip”提供了一个关于Python爬虫项目的详细示例,名为“Spiders-master”,这通常包含了一系列的Python脚本、配置文件以及可能的数据存储结构。下面将详细探讨Python网络爬虫的基础知识、常用库和...
Python因其简洁的语法和丰富的库支持,成为了编写网络爬虫的首选语言之一。 在Python中,我们通常使用requests库进行HTTP请求,发送GET和POST请求来获取网页内容。例如,模拟登录的过程通常涉及到向网站服务器发送...
Python网络爬虫技术是当前IT领域中非常热门的一个分支,尤其在大数据分析和人工智能应用中起着关键作用。本资源“Python网络爬虫技术_习题答案.rar”看似是一个教学资料,包含了一些图像文件和章节内容,我们可以从...
例如,BeautifulSoup、Scrapy、Selenium等库为Python爬虫提供了强大的功能。 **1. 国内外研究现状** 在国内外,网络爬虫的研究主要集中在动态网页抓取和聚焦爬虫技术上。动态网页的抓取需要处理JavaScript、AJAX等...
Python爬虫的核心在于两个主要部分:网络请求和HTML解析。网络请求通常通过`requests`库来实现,它可以发送HTTP请求(如GET或POST)到目标网站并获取响应。`requests.get()`函数用于获取网页内容,而`requests.post...
通过对Python爬虫技术的学习,不仅可以帮助我们更好地理解和利用互联网资源,还能为后续的数据分析、挖掘等工作奠定坚实的基础。同时,需要注意遵守相关的法律法规和技术规范,合理合法地使用爬虫技术,为社会创造更...
python爬取小说 # 爬虫下载一本小说 import time import requests import os from bs4 import BeautifulSoup # 从bs4库中导入BeautifulSoup import random # 导入随机数模块,用于随机生成休眠时间,防止被封IP(这个...
在本案例中,我们将深入探讨如何使用Python进行网络爬虫,特别是针对百度图片搜索的爬取。这个项目是一个初级入门级别的教程,旨在帮助初学者理解网络爬虫的基本原理和实践。我们将主要关注两个核心库——requests和...
Python之所以被广泛用于网络爬虫,是因为其语法简洁、库丰富。其中,最常用的库包括BeautifulSoup、Scrapy和Requests等。BeautifulSoup提供了一种方便的方式来解析HTML和XML文档,而Scrapy则是一个完整的框架,用于...
在本实习报告中,我们将深入探讨Python网络爬虫的相关知识,并通过实例演示如何使用Python爬虫框架来爬取豆瓣网上的电影数据。 首先,我们要理解爬虫的基本原理。网络爬虫通常分为三个步骤:请求网页、解析网页和...