上一次我自学爬虫的时候, 写了一个简陋的勉强能运行的爬虫alpha. alpha版有很多问题. 比如一个网站上不了, 爬虫却一直在等待连接返回response, 不知道超时跳过; 或者有的网站专门拦截爬虫程序, 我们的爬虫也不会伪装自己成为浏览器正规部队; 并且抓取的内容没有保存到本地, 没有什么作用. 这次我们一个个解决这些小问题.
Python 3开发网络爬虫(三): 伪装浏览器君
一、添加超时跳过功能
首先, 我简单地将
urlop = urllib.request.urlopen(url)
改为
urlop = urllib.request.urlopen(url, timeout = 2)
运行后发现, 当发生超时, 程序因为exception中断. 于是我把这一句也放在try .. except 结构里, 问题解决.
二、支持自动跳转
三、伪装浏览器正规军
爬虫需要在http的header请求中加入user-agent
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
第二种方法使用了 build_opener 这个方法, 用来自定义 opener, 这种方法的好处是可以方便的拓展功能, 例如下面的代码就拓展了自动处理 Cookies 的功能.
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 报文如下所示:
四、保存抓回来的报文
顺便说说文件操作. Python 的文件操作还是相当方便的. 我们可以讲抓回来的数据 data 以二进制形式保存, 也可以经过 decode() 处理成为字符串后以文本形式保存. 改动一下打开文件的方式就能用不同的姿势保存文件了. 下面是参考代码:
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 3开发网络爬虫(四): 登录
Python 3开发网络爬虫(五): 使用第三方模块快速抓取与解析
在前面的四篇文章中, 我们一直采用 python 3 自带的 urllib 模块来抓取网页, 然后用 re 模块来处理抓取到的数据. 这次我们使用 Requests 库来代替 urllib, 用 BeautifulSoup 来代替 re 模块.
对于这两个模块来说, 学习使用它们的最好方法是看官方文档, 这两个模块的官方文档都有中文版(翻译的不是很完整).
在 Windows 下如果安装了 Python3, 那么在 cmd 下直接可以通过 pip 来安装这两个模块, 命令如下:
在cmd中测试pip能否是使用
pip -v
安装两个库
pip install requests
pip install beautifulsoup4
测试安装是否成功
C:\Users\lenovo>python
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> from bs4 import BeautifulSoup
>>>
一、Requests Module
Requests 是 Python 界大名鼎鼎的一个网络库,主要有两大点:
- 对 GET 和 POST 方法的封装做的很好, 自动处理了编码等问题;
- 默认开启了 Cookies 处理, 在处理需要登录的问题上面非常方便.
二、BeautifulSoup Module
BeautifulSoup 大大方便了我们对抓取的 HTML 数据的解析, 可以用tag, class, id来定位我们想要的东西, 可以直接提取出正文信息, 可以全文搜索, 同样也支持正则表达式, 相当给力.
三、小试牛刀
因为 知乎已经加了https,所以用了自己的没完成的项目(没加https)。在python shell中输入
>>> import requests
>>> from bs4 import BeautifulSoup
>>> response = requests.get("http://xxxx.com")
>>> soup = BeautifulSoup(response.text)
>>> print(soup.title.text) #打印title
>>> print(soup.body.text) #打印body
>>> for x in soup.findAll("a"): #打印a标签的href
print(x['href'])
四、重访知乎
>>> soup = BeautifulSoup(requests.get("http://www.zhihu.com").text)
>>> print(soup.find("input", {"name": "_xsrf"})['value'])
d4ff8d18b293442a764bd0ccff333601
获取知乎HTML页面的input hidden 里面name为_xsrf的 value (跟jquery有点类似)