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爬虫示例代码

Python:关于爬虫

关于python网络爬虫——摘取新闻标题及链接

Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段

Python爬虫与一汽项目综述

python爬虫学习笔记-M3U8流视频数据爬虫