零基础自学用Python 3开发网络爬虫(三): 伪装浏览器君

原文出处: Jecvay Notes (@Jecvay)

上一次我自学爬虫的时候, 写了一个简陋的勉强能运行的爬虫alpha. alpha版有很多问题. 比如一个网站上不了, 爬虫却一直在等待连接返回response, 不知道超时跳过; 或者有的网站专门拦截爬虫程序, 我们的爬虫也不会伪装自己成为浏览器正规部队; 并且抓取的内容没有保存到本地, 没有什么作用. 这次我们一个个解决这些小问题.

此外, 在我写这系列文章的第二篇的时候, 我还是一个对http的get和post以及response这些名词一无所知的人, 但是我觉得这样是写不好爬虫的. 于是我参考了 <<计算机网络--自顶向下方法>> 这本书的第二章的大部分内容. 如果你也一样对http的机制一无所知, 我也推荐你找一找这方面的资料来看. 在看的过程中, 安装一个叫做Fiddler的软件, 边学边实践, 观察浏览器是如何访问一个网站的, 如何发出请求, 如何处理响应, 如何进行跳转, 甚至如何通过登录认证. 有句老话说得好, 越会用Fiddler, 就对理论理解更深刻; 越对理论理解深刻, Fiddler就用得越顺手. 最后我们在用爬虫去做各种各样的事情的时候, Fiddler总是最得力的助手之一.

添加超时跳过功能

首先, 我简单地将

urlop = urllib.request.urlopen(url)

改为

urlop = urllib.request.urlopen(url, timeout = 2)

运行后发现, 当发生超时, 程序因为exception中断. 于是我把这一句也放在try .. except 结构里, 问题解决.

支持自动跳转

在爬 http://baidu.com 的时候, 爬回来一个没有什么内容的东西, 这个东西告诉我们应该跳转到 http://www.baidu.com . 但是我们的爬虫并不支持自动跳转, 现在我们来加上这个功能, 让爬虫在爬 baidu.com 的时候能够抓取 www.baidu.com 的内容.

首先我们要知道爬 http://baidu.com 的时候他返回的页面是怎么样的, 这个我们既可以用 Fiddler 看, 也可以写一个小爬虫来抓取. 这里我抓到的内容如下, 你也应该尝试一下写几行 python 来抓一抓.

<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

看代码我们知道这是一个利用 html 的 meta 来刷新与重定向的代码, 其中的0是等待0秒后跳转, 也就是立即跳转. 这样我们再像上一次说的那样用一个正则表达式把这个url提取出来就可以爬到正确的地方去了. 其实我们上一次写的爬虫已经可以具有这个功能, 这里只是单独拿出来说明一下 http 的 meta 跳转.

伪装浏览器正规军

前面几个小内容都写的比较少. 现在详细研究一下如何让网站们把我们的Python爬虫当成正规的浏览器来访. 因为如果不这么伪装自己, 有的网站就爬不回来了. 如果看过理论方面的知识, 就知道我们是要在 GET 的时候将 User-Agent 添加到header里.

如果没有看过理论知识, 按照以下关键字搜索学习吧 :D

  • HTTP 报文分两种: 请求报文和响应报文
  • 请求报文的请求行与首部行
  • GET, POST, HEAD, PUT, DELETE 方法

我用 IE 浏览器访问百度首页的时候, 浏览器发出去的请求报文如下:

GET http://www.baidu.com/ HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: www.baidu.com
DNT: 1
Connection: Keep-Alive
Cookie: BAIDUID=57F4D171573A6B88A68789EF5DDFE87:FG=1; uc_login_unique=ccba6e8d978872d57c7654130e714abd; BD_UPN=11263145; BD

然后百度收到这个消息后, 返回给我的的响应报文如下(有删节):

HTTP/1.1 200 OK
Date: Mon, 29 Sep 2014 13:07:01 GMT
Content-Type: text/html; charset=utf-8
Connection: Keep-Alive
Vary: Accept-Encoding
Cache-Control: private
Cxy_all: baidu+8b13ba5a7289a37fb380e0324ad688e7
Expires: Mon, 29 Sep 2014 13:06:21 GMT
X-Powered-By: HPHP
Server: BWS/1.1
BDPAGETYPE: 1
BDQID: 0x8d15bb610001fe79
BDUSERID: 0
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Content-Length: 80137

<!DOCTYPE html><!--STATUS OK--><html><head><meta http-equiv="content-type" content="text/html;charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=Edge"><link rel="dns-prefetch" href="//s1.bdstatic.com"/><link rel="dns-prefetch" href="//t1.baidu.com"/><link rel="dns-prefetch" href="//t2.baidu.com"/><link rel="dns-prefetch" href="//t3.baidu.com"/><link rel="dns-prefetch" href="//t10.baidu.com"/><link rel="dns-prefetch" href="//t11.baidu.com"/><link rel="dns-prefetch" href="//t12.baidu.com"/><link rel="dns-prefetch" href="//b1.bdstatic.com"/><title>百度一下,你就知道</title><style index="index" > ..........这里省略两万字................ </script></body></html>

如果能够看懂这段话的第一句就OK了, 别的可以以后再配合 Fiddler 慢慢研究. 所以我们要做的就是在 Python 爬虫向百度发起请求的时候, 顺便在请求里面写上 User-Agent, 表明自己是浏览器君.

在 GET 的时候添加 header 有很多方法, 下面介绍两种方法.

第一种方法比较简便直接, 但是不好扩展功能, 代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

import urllib.request

url = ‘http://www.baidu.com/‘

req = urllib.request.Request(url, headers = {

‘Connection‘: ‘Keep-Alive‘,

‘Accept‘: ‘text/html, application/xhtml+xml, */*‘,

‘Accept-Language‘: ‘en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3‘,

‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko‘

})

oper = urllib.request.urlopen(req)

data = oper.read()

print(data.decode())

第二种方法使用了 build_opener 这个方法, 用来自定义 opener, 这种方法的好处是可以方便的拓展功能, 例如下面的代码就拓展了自动处理 Cookies 的功能.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

import urllib.request

import http.cookiejar

# head: dict of header

def makeMyOpener(head = {

‘Connection‘: ‘Keep-Alive‘,

‘Accept‘: ‘text/html, application/xhtml+xml, */*‘,

‘Accept-Language‘: ‘en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3‘,

‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko‘

}):

cj = http.cookiejar.CookieJar()

opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))

header = []

for key, value in head.items():

elem = (key, value)

header.append(elem)

opener.addheaders = header

return opener

oper = makeMyOpener()

uop = oper.open(‘http://www.baidu.com/‘, timeout = 1000)

data = uop.read()

print(data.decode())

上述代码运行后通过 Fiddler 抓到的 GET 报文如下所示:

GET http://www.baidu.com/ HTTP/1.1
Accept-Encoding: identity
Connection: close
Host: www.baidu.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3

可见我们在代码里写的东西都添加到请求报文里面了.

保存抓回来的报文

顺便说说文件操作. Python 的文件操作还是相当方便的. 我们可以讲抓回来的数据 data 以二进制形式保存, 也可以经过 decode() 处理成为字符串后以文本形式保存. 改动一下打开文件的方式就能用不同的姿势保存文件了. 下面是参考代码:

1

2

3

4

5

6

7

8

9

10

11

12

def saveFile(data):

save_path = ‘D:\temp.out‘

f_obj = open(save_path, ‘wb‘) # wb 表示打开方式

f_obj.write(data)

f_obj.close()

# 这里省略爬虫代码

# ...

# 爬到的数据放到 dat 变量里

# 将 dat 变量保存到 D 盘下

saveFile(dat)

下回我们会用 Python 来爬那些需要登录之后才能看到的信息. 在那之前, 我已经对 Fiddler 稍微熟悉了. 希望一起学习的也提前安装个 Fiddler 玩一下.

时间: 2024-12-26 07:40:12

零基础自学用Python 3开发网络爬虫(三): 伪装浏览器君的相关文章

Python 3开发网络爬虫(四): 登录

原文出处: Jecvay Notes (@Jecvay) <零基础自学用Python 3开发网络爬虫(一)> <零基础自学用Python 3开发网络爬虫(二)> <零基础自学用Python 3开发网络爬虫(三)> 今天的工作很有意思, 我们用 Python 来登录网站, 用Cookies记录登录信息, 然后就可以抓取登录之后才能看到的信息. 今天我们拿知乎网来做示范. 为什么是知乎? 这个很难解释, 但是肯定的是知乎这么大这么成功的网站完全不用我来帮他打广告. 知乎网的

零基础自学Python 3开发网络爬虫(二): 用到的数据结构简介以及爬虫Ver1.0 alpha

上一回, 我学会了 用伪代码写出爬虫的主要框架; 用Python的urllib.request库抓取指定url的页面; 用Python的urllib.parse库对普通字符串转符合url的字符串. 这一回, 开始用Python将伪代码中的所有部分实现. 由于文章的标题就是"零基础", 因此会先把用到的两种数据结构队列和集合介绍一下. 而对于"正则表达式"部分, 限于篇幅不能介绍, 但给出我比较喜欢的几个参考资料. Python的队列 在爬虫程序中, 用到了广度优先搜

Python 开发网络爬虫(四): 登录

http://blog.jobbole.com/77878/ 博客 – 伯乐在线 首页最新文章在线课程业界开发 IT技术 设计 创业IT职场投稿更多 ? 伯乐在线 > 首页 > 所有文章 > Python > 零基础自学用Python 3开发网络爬虫(四): 登录 零基础自学用Python 3开发网络爬虫(四): 登录 原文出处: Jecvay Notes (@Jecvay)   欢迎分享原创到伯乐头条 今天的工作很有意思, 我们用 Python 来登录网站, 用Cookies记录

讨教大学:零基础自学编程,选JAVA,Python还是PHP?

越来越多非科班出身的人也义无反顾的投身到了IT互联网行业,加入了码农大军.但是对于非科班自学编程的朋友们来说,考虑的第一个问题一定是:我该从哪一个语言开始学起?在这里小编就为大家介绍一下零基础自学几大主流语言的优劣势. 首先从这几大语言的难度谈起,不同语言门槛和难度不同,Python<PHP<JavaScript<Java<C++.也就是说,Python是最好入门的一种语言,兼具易学性和趣味性,学几天就可以做出一些有意思的小功能出来.这也给了初学者学下去的信心和兴趣,不至于啃书几天

Python服务器开发 -- 网络基础

Python服务器开发 -- 网络基础 网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.HTTP是高层协议,而TCP/IP是个协议集,包过许多的子协议.... 网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. HTTP是高层协议,而TCP/IP是个协议集,包过许多的子协议.包括:传输层的 FTP,UDP,TCP协议等,网络层的ip协议等,高层协议如HTTP,telnet协议等,HTTP是TCP/IP的一个子协议. socket是对TCP/I

python零基础自学——前篇自白

首先声明,本人就是个菜鸟,小白一个,在这里记录我自学python时的点点滴滴,用于我的经验积累以及复习.当然,若有零基础自学的人看见,交流学习经验那就最好不过了. python其实对零基础的小白来说就再适合不过了,为什么这么说,个人对编程的理解就是高.大.上.总感觉都是些BT才可以玩这个的. 我自己创业,开公司有过好的时候,但最后都倒闭了,积累如此阅历,却回首发现,自己没有一项术语自己的专业既能.所以就想学习编程.跟专业朋友交流以后,都推荐我学习python.原因有以下几点: 一:简单. 因为是

小猿圈web前端开发讲师:零基础自学html5开发方法

web前端开发目前市场使用率随着需求逐年递增.越来越多的年轻人转行进入了web前端开发领取.html5强大的功能是有目共睹的,本属自身独特的优势让这一技术越来越受欢迎,相比于原生APP,html5已经逐渐在用户体验生无限接近,再加上低廉的开发成本和强大的适配功能,早已经可以俘获开发商和开发者的芳心,本文小猿圈web前端开发讲师介绍零基础如何自学html5开发? 小猿圈web前端开发讲师:零基础自学html5开发方法: 1.拒绝插件,遇到交互效果就选择扒插件,这是一种非常不可取的方法,在这种情况之

PowerShell_零基础自学课程_5_自定义PowerShell环境及Powershell中的基本概念

PowerShell_零基础自学课程_5_自定义PowerShell环境及Powershell中的基本概念 据我个人所知,windows下的cmd shell除了能够通过修改系统参数来对其中的环境变量进行改变外,其环境的可自定义性相对来说很困难,而在Linux环境中,可以通过修改/etc目录下的某些配置文件来达到配置shell环境的目的.也许这也是某些人诟病cmd shell功能不强的原因之一. 而目前这种状况在windows powershell中得到了改善,可以说PS中提供的自定义环境的功能

零基础能学Python编程吗 Python就业市场怎样

零基础能学Python编程吗?Python就业市场怎样?Python的用处很广,比如数据挖掘,数据分析,网络爬虫,机器学习,科学计算哲学前沿领域都Python的用武之地. 目前,Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的,因为现在Python正在朝着3.x版本进化,在进化过程中,大量的针对2.x版本的代码要修改后才能运行.所以,目前有许多第三方库还暂时无法在3.x上使用. ? ? 学习Python语言,就像学习其他编程语言或者是学习某门外语一样 ,我们应该从Py