您的位置:首页 > 编程语言 > Python开发

简单python爬虫

2017-01-25 18:34 363 查看
初学python,借鉴网上一些资料尝试了一个简单的爬虫小程序,这是非常简单的爬网页图片的代码。

一,版本问题

开始在网上找到的简易爬虫小程序是下面这个:

简易爬虫小程序

讲解的很是详细,但是这个好像并不是用Python3.x写的,代码并不能直接用,在Python3 之后很多包都有所改动,像这篇博客代码中的urllib,re就有改动,改完之后与java的正则匹配倒是有些相似。通过查找api和搜索引擎将版本问题解决了。

二,非法访问(Bad Request)

启动程序,就遇到了一些问题,总是报出“400 Bad Request”的错误,这是非法访问的意思,我在网上查到可能是由于非人访问时,Python发过去的头并不是浏览器访问的头部,而是以,需要为其添加头部,伪装成浏览器:

user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
request.add_header('User-Agent', user_agent)


服务器可能会检查的头部如下:

User-Agent : 有些服务器或 Proxy 会通过该值来判断是否是浏览器发出的请求

Content-Type : 在使用 REST接口时,服务器会检查该值,用来确定 HTTP Body 中的内容该怎样解析。常见的取值有:

application/xml : 在 XMLRPC,如 RESTful/SOAP 调用时使用

application/json : 在 JSON RPC 调用时使用

application/x-www-form-urlencoded : 浏览器提交 Web 表单时使用

三,网页img标签中属性不同

网页爬虫中核心的步骤就是读取并解析网页内容,通过正则表达式匹配自己想要获取的内容,再下载到本地或者存入数据库中。

如果有朋友对于正则表达式不太了解,可以参加下面的博客,也是上面博客中引用的文章,讲解还是很明白的:

正则表达式介绍

而运行了他所给的网页后发现是可以的,但是换了其他网页爬图片时发现并不能下载,于是我将函数中的imglist集合打印了出来,看到是空的,可以猜测到是由于正则表达式出了问题,匹配不到了,通过查看器查看其他网页图片的源码发现有些src属性后面跟的是width属性,有的是size属性,还有的是pic_ext属性,所以只能改变正则表达式同时适配这几种才行:

reg = r'src="(http://.+?\.jpg|ng)" [size|width|pic_ext]'
imgre = re.compile(reg)
imglist = imgre.findall(html)


这里要提一下的是,findall所匹配的是元组也就是圆括号中的元素,每一个圆括号就代表一个元组(ps:这是我个人的理解,并没有在其他地方找到确切说明,但是多次尝试的确是这样)

四,urlretrieve的使用

x = 0
for imgurl in imglist:
urllib.request.urlretrieve(imgurl, '%s.jpg' % x, reporthook)
x += 1


开始写的时候urlretrieve我只用了2个参数,是没有最后一个的,这是在网上找资料时发现的,后来查了api才知道urlretrieve参数列表是这样的:

urllib.urlretrieve(url, filename=None, reporthook=None, data=None)

参数说明:

url:外部或者本地url

filename:指定了保存到本地的路径(如果未指定该参数,urllib会生成一个临时文件来保存数据);

reporthook:是一个回调函数,当连接上服务器、以及相应的数据块传输完毕的时候会触发该回调。我们可以利用这个回调函数来显示当前的下载进度。

data:指post到服务器的数据。该方法返回一个包含两个元素的元组(filename, headers),filename表示保存到本地的路径,header表示服务器的响应头。

从上面的列表可以看出来后面三个是默认参数,当不传参的时候就为None,这个reporthook主要作用是显示下载进度,代码如下:

def reporthook(a, b, c):
"""
a:已经下载的数据块
b:数据库块的大小
c:远程文件的大小
"""
per = 100.0 * a * b / c
if per > 100:
per = 100
print('完成!')
print('%.2f%%' % per)


整体代码:

import re
import urllib.request

def reporthook(a, b, c): """ a:已经下载的数据块 b:数据库块的大小 c:远程文件的大小 """ per = 100.0 * a * b / c if per > 100: per = 100 print('完成!') print('%.2f%%' % per)

def get_html(url):
request = urllib.request.Request(url)
# 添加头部,伪装成浏览器
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" request.add_header('User-Agent', user_agent)

response = urllib.request.urlopen(request)
html = response.read()
return html

def get_img(html):
html = html.decode('utf-8')
reg = r'src="(http://.+?\.jpg|ng)" [size|width|pic_ext]' imgre = re.compile(reg) imglist = imgre.findall(html)
print(imglist)

x = 0 for imgurl in imglist: urllib.request.urlretrieve(imgurl, '%s.jpg' % x, reporthook) x += 1
return 'done'

html = get_html('http://tieba.baidu.com/p/2460150866')
print(get_img(html))


以上很多都是个人见解,有什么不对的还望大牛指点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息