Python:关于爬虫
Posted 在下雨的Tokyo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python:关于爬虫相关的知识,希望对你有一定的参考价值。
要使用python编写爬虫代码,我们需要解决第一个问题是:
Python如何访问互联网?
回答这个问题不得不提到的就是urllib,它实际上是由两部分组成的:url+lib。
url:就是我们平时所说的网页地址
lib:library的意思
URL的一般格式为(带方括号[]的为可选项):
protocol://hostname[:port]/path/[;parameters][?query]#fragment
URL由三部分组成:
第一部分是协议:http,https,ftp,file,ed2k...
http:Hypertext Transfer Protocol, 即超文本传输协议,万维网浏览服务程序所用的协议。
https:Secure Hypertext Transfer Protocol,即安全超文本传输协议,在HTTP基础上增强的数据安全的部分。
ftp:File Transfer Protocol , 即文件传送[输]协议。
file:File协议主要用于访问本地计算机中的文件,就如同在Windows资源管理器中打开文件一样。基本的格式如下:file:///文件路径,比如要打开F盘flash文件夹中的1.swf文件,那么可以在资源管理器或[IE]地址栏中键入:file:///f:/flash/1.swf并回车。
ed2k:eDonkey2000 network,是一种文件共享网络,最初用于共享音乐、电影和软件。与多数文件共享网络一样,它是分布式的;文件基于P2P原理存放于用户的电脑上而不是存储于一个中枢服务器。 说简单点就是emule下载地址的开头,也就是说要下载此种网址的文件必须用eMule,不过现在迅雷也支持[ed2k协议。
- 第二部分是存放资源的服务器的域名系统或IP地址(有时候要包含端口号,各种传输协议都有默认的端口号,如http的默认端口号为80)。
- 第三部分是资源的具体地址,如目录或文件名等。【第三部分通常是可以忽略的】
在python2.x里面,含有urllib和urllib2两个模块(module),python3.x对它做了一个较大的改动,将其合并为一个包(package),统一称为urllib,它包含了四个模块(module):
urllib.request—for opening and reading URLs
urllib.error—containing the exceptions raised by urllib.request
urllib.parse—for parsing URLs
urllib.robotparser—for parsing robots.txt files
举个例子:我们读取一个网页的内容
import urllib.request
response = urllib.request.urlopen("http://www.fishc.com")
html=response.read()
print(html)
得到的结果是:
进行解码:html=html.decode(‘utf-8‘)
得到的结果是:
实战
推荐一个网站:placekitten.com
A quick and simple service for getting pictures of kittens for use as placeholders in your designs or code. Just put your image size (width & height) after our URL and you‘ll get a placeholder.
通过以下的方式就能得到你想要的尺寸的猫的图片:
Like this: http://placekitten.com/200/300
or:http://placekitten.com/g/200/300
第一个例子:抓取图片
我们新建一个downloadcat.py文件,执行下面这段代码:
import urllib.request
response = urllib.request.urlopen("http://placekitten.com/g/320/240")
cat_img = response.read()
with open("cat_320_240.jpg", "wb") as f:
f.write(cat_img)
在downloadcat.py的同级目录里面可以可以看到一个大小为320*240的图片:
解读程序:urlopen()参数既可以是一个字符串,也可以一个request对象。实际上,response可以分解为:
req=urllib.request.Request("http://placekitten.com/g/320/240")
response=urllib.request.urlopen(req)
urlopen实际上是返回一个对象,我们可以通过read()来读取它的内容。我们还可以:
通过response.geturl()获取到图片的网址;
通过response.info()来获得图片的详细信息;
通过response.getcode()来获得状态码。
print(response.geturl())
print(response.info())
print(response.getcode())
第二个例子:利用有道词典翻译文本
我们打开有道词典,输入英文之后,会自动翻译成中文
打开浏览器的审查元素,切换到Network,我们找到name目录下的translate_o开头的文件,点击打开之后可以看到它的Preveiws的信息:
正是我们进行翻译的句子,接着切换到Headers,可以看到Headers的基本信息:
其中:
Remote Addresss是服务器的IP地址以及它打开的端口号
Request URL是真正实现翻译的地址
Request Method是请求的方式
Status Code是状态码,200表示成功
Request Headers是客户端发送请求的headers,它通常用于服务器端判断是否非人类访问,主要是通过User-Agent结构来识别是浏览器访问还是代码访问。它是可以简单自定义的。
Form Data是post提交的主要内容。i后面是待翻译的文本内容
在这个网址的笔记列表里面可以查看常见的状态码:
http://www.runoob.com/ajax/ajax-xmlhttprequest-onreadystatechange.html
我们新建一个py文件,执行下面的代码:
import urllib.request as ur
import urllib.parse
# 获取Request URl
request_url = ‘http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&sessionFrom=‘
# 获取到Form Data中的信息
data = {
‘i‘: ‘I love you‘,
‘from‘: ‘AUTO‘,
‘to‘: ‘AUTO‘,
‘smartresult‘: ‘dict‘,
‘client‘: ‘fanyideskweb‘,
‘salt‘: ‘1505653077725‘,
‘sign‘: ‘467d88b4cdc9c6adca72855020b6a1e8‘,
‘doctype‘: ‘json‘,
‘version‘: ‘2.1‘,
‘keyfrom‘: ‘fanyi.web‘,
‘action‘: ‘FY_BY_CLICKBUTTION‘,
‘typoResult‘: ‘true‘
}
data=urllib.parse.urlencode(data).encode(‘utf-8‘)
response = ur.urlopen(request_url, data)
html=response.read().decode(‘utf-8‘)
print(html)
Take Note:
记得去掉request_url中的"_0",否则会报错{"errorCode":50}
得到的结果:
从运行结果可知,得到的数据其实是json格式,它是一种轻量级的数据交换格式。关于json的用法,可以参考下面的网址:
http://www.runoob.com/json/json-tutorial.html
加入以下代码:
import json
target = json.loads(html)
print(target)
得到的结果是:
target的数据类型是dict,我们通过一层一层的访问方式:
print(target[‘translateResult‘])
print(target[‘translateResult‘][0][0])
print(target[‘translateResult‘][0][0][‘tgt‘])
可以获得我们想要的目标信息:
我们可以对代码进行简单修改,以此获得更好的用户体验:(省略部分与之前的一样)
content = input("请输入需要翻译的内容:")
......
‘i‘:content
......
print("翻译结果:%s" % target[‘translateResult‘][0][0][‘tgt‘])
测试结果:
***
隐藏
用以上的形式进行翻译会对服务器造成很大的负担,频繁访问肯能会被屏蔽。要想代码能够正常工作,我们需要对代码进行隐藏处理,让它的访问方式更贴近于浏览器的访问。
根据上文介绍审查元素的一些特性时,我们提到了User-Agent的作用,现在我们就需要对它进行操作来模拟浏览器访问。
我们在审查元素里面找到这个信息:
第一种修改方法:通过Request的headers参数修改,将response修改为两句,head的添加在req的前面进行。
head = {}
head[‘User-Agent‘] = ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36‘
......
req = ur.Request(request_url, data,head)
response = ur.urlopen(req)
......
第二种修改方法:通过Request.add_header()方法修改,将response修改为两句,head的添加在req的后面进行
......
req = ur.Request(request_url, data)
req.add_header(‘UserAgent‘,‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36‘)
response = ur.urlopen(req)
......
检验方法:print(req.headers)
Take Note:
ur是简写,引入包的时候已经声明了
import urllib.request as ur
修改User-Agent是最简单的隐藏方法,但如果这是用于抓取网页的爬虫,那么一个IP地址短时间内会连续访问,这是不正常的,会对服务器产生较大的压力,返回给用户验证码的填写页面,爬虫是无法识别验证码的,这时候User-Agent就不起作用了。我们有两种方式可以处理这个问题。
第一种:延迟提交的时间,让爬虫看起来比较正常
我们可以将以上代码做如下处理:
......
import time
......
# 将主体代码进行缩进,放在一个while循环里面
while True:
content = input("请输入需要翻译的内容(输入‘q!‘退出程序):")
if content == ‘q!‘:
break
......
time.sleep(5000)
第一次的翻译工作结束后五秒,才执行第二次翻译
第一种方式弊端:效率低下。
第二种:使用代理
步骤:
1.参数是一个字典{‘类型‘:‘代理ip:端口号‘}
proxy_support=urllib.request.ProxyHandler({})
2.定制、创建一个opener
opener=urllib.request.build_opener(proxy_support)
3.1安装opener
urllib.request.install_opener(opener)
3.2调用opener[特殊需要的时候才使用可以不安装直接调用]
opener.open(url)
import urllib.request
# 访问时会显示来源IP
url = ‘http://www.whatismyip.com.tw‘
# 按步骤,代理ip地址可以去网上找
proxy_support = urllib.request.ProxyHandler({‘http‘: ‘118.193.107.131:80‘})
opener = urllib.request.build_opener(proxy_support)
urllib.request.install_opener(opener)
response = urllib.request.urlopen(url)
html = response.read().decode(‘utf-8‘)
print(html)
代理ip地址进行访问的时候可能会出现404等错误,可能是被过滤掉了,我们可以对代码简单修改,给opener加上headers信息
opener.addheaders = [(‘UserAgent‘,‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36‘)]
为了避免ip不稳定而导致访问出错的问题,我们可以建立一个ip_list,随机使用其中一个ip进行访问
ip_list = [ ]
proxy_support = urllib.request.ProxyHandler({‘http‘: random.choice(ip_list)})
# 其余不变
以上是关于Python:关于爬虫的主要内容,如果未能解决你的问题,请参考以下文章
Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段