学习python爬虫有一个月了,现在将学习的东西和遇到的问题做一个阶段总结,以作复习备用,另对于python爬虫感兴趣的,如果能帮到你们少走些弯路,那也是极好的。闲话少说,下面直接上干货:

Python学习网络爬虫主要分3个大的版块:抓取分析存储

另外,比较常用的爬虫框架Scrapy,这里最后也详细介绍一下。

当我们在浏览器中输入一个url后回车,后台会发生什么?

简单来说这段过程发生了以下四个步骤:

· 查找域名对应的IP地址。

· 向IP对应的服务器发送请求。

· 服务器响应请求,发回网页内容。

· 浏览器解析网页内容。

网络爬虫要做的,简单来说,就是实现浏览器的功能。通过指定url,直接返回给用户所需要的数据,而不需要一步步人工去操纵浏览器获取。

抓取

这一步,你要明确要得到的内容是什么?是HTML源码,还是Json格式的字符串等。

1. 最基本的抓取

抓取大多数情况属于get请求,即直接从对方服务器上获取数据。

首先,Python中自带urllib及urllib2这两个模块,基本上能满足一般的页面抓取。另外,requests也是非常有用的包,与此类似的,还有httplib2等等。

Requests:

import requests

response = requests.get(url)

content = requests.get(url).content

print "response headers:", response.headers

print "content:", content

Urllib2:(标签整齐,清晰,看着比较舒服,以后可以用它,便于阅读HTML)

import urllib2

response = urllib2.urlopen(url)

content = urllib2.urlopen(url).read()

print "response headers:", response.headers

print "content:", content

Httplib2:

import httplib2

http = httplib2.Http()

response_headers, content = http.request(url, 'GET')

print "response headers:", response_headers

print "content:", content

此外,对于带有查询字段的url,get请求一般会将来请求的数据附在url之后,以?分割url和传输数据,多个参数用&连接。

data = {'data1':'XXXXX', 'data2':'XXXXX'}

Requests:data为dict,json

import requests

response = requests.get(url=url, params=data)

Urllib2:data为string

import urllib, urllib2

data = urllib.urlencode(data)

full_url = url+'?'+data

response = urllib2.urlopen(full_url)

2. 对于登陆情况的处理

2.1 使用表单登陆

这种情况属于post请求,即先向服务器发送表单数据,服务器再将返回的cookie存入本地。

data = {'data1':'XXXXX', 'data2':'XXXXX'}

Requests:data为dict,json

import requests

response = requests.post(url=url, data=data)

Urllib2:data为string

import urllib, urllib2

data = urllib.urlencode(data)

req = urllib2.Request(url=url, data=data)

response = urllib2.urlopen(req)

2.2 使用cookie登陆

使用cookie登陆,服务器会认为你是一个已登陆的用户,所以就会返回给你一个已登陆的内容。因此,需要验证码的情况可以使用带验证码登陆的cookie解决。

import requests

requests_session = requests.session()

response = requests_session.post(url=url_login, data=data)

若存在验证码,此时采用response = requests_session.post(url=url_login, data=data)是不行的,做法应该如下:

response_captcha = requests_session.get(url=url_login, cookies=cookies)

response1 = requests.get(url_login) # 未登陆

response2 = requests_session.get(url_login) # 已登陆,因为之前拿到了Response Cookie!

response3 = requests_session.get(url_results) # 已登陆,因为之前拿到了Response Cookie!

3. 对于反爬虫机制的处理

3.1 使用代理

适用情况:限制IP地址情况,也可解决由于“频繁点击”而需要输入验证码登陆的情况。

这种情况最好的办法就是维护一个代理IP池,网上有很多免费的代理IP,良莠不齐,可以通过筛选找到能用的。对于“频繁点击”的情况,我们还可以通过限制爬虫访问网站的频率来避免被网站禁掉。

关键代码,如下几行:

proxies = {'http':'http://XX.XX.XX.XX:XXXX'}

Requests:

import requests

response = requests.get(url=url, proxies=proxies)

Urllib2:

import urllib2

proxy_support = urllib2.ProxyHandler(proxies)

opener = urllib2.build_opener(proxy_support, urllib2.HTTPHandler)

urllib2.install_opener(opener) # 安装opener,此后调用urlopen()时都会使用安装过的opener对象

response = urllib2.urlopen(url)

这在某些情况下比较有用,比如IP被封了,或者比如IP访问的次数受到限制等等。此时,可以在middlewares.py中通过类对代理IP进行封装,详细代码如下:

class ProxyMiddleware(object):

def process_request(self, request, spider):

proxy = random.choice(PROXIES)

if proxy['user_pass'] is not None:

request.meta['proxy'] = "http://%s" % proxy['ip_port']

encoded_user_pass = base64.encodestring(proxy['user_pass'])

request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass

print "**************ProxyMiddleware have pass************" + proxy['ip_port']

else:

print "**************ProxyMiddleware no pass************" + proxy['ip_port']

request.meta['proxy'] = "http://%s" % proxy['ip_port']

PROXIES = [

{'ip_port': '218.4.101.130:83', 'user_pass': ''},

{'ip_port': '113.121.47.97:808', 'user_pass': ''},

{'ip_port': '112.235.20.223:80', 'user_pass': ''},

{'ip_port': '27.151.30.68:808', 'user_pass': ''},

{'ip_port': '175.155.25.50:808', 'user_pass': ''},

{'ip_port': '222.85.50.207:808', 'user_pass': ''},

{'ip_port': '116.255.153.137:8082', 'user_pass': ''},

{'ip_port': '119.5.0.26:808', 'user_pass': ''},

{'ip_port': '183.32.88.223:808', 'user_pass': ''},

{'ip_port': '180.76.154.5:8888', 'user_pass': ''},

{'ip_port': '221.229.44.174:808', 'user_pass': ''},

{'ip_port': '27.151.30.68:808', 'user_pass': ''},

{'ip_port': '60.178.86.7:808', 'user_pass': ''},

{'ip_port': '58.243.104.149:8998', 'user_pass': ''},

{'ip_port': '120.27.49.85:8090', 'user_pass': ''},

]

注意,由于代理IP一般都有时效性,需要找到能用的代理IP将上面ip_port关键字对应的值替换下来。

3.2 时间设置

适用情况:限制频率情况。

Requests,Urllib2都可以使用time库的sleep()函数:

import time

time.sleep(1)

3.3 伪装成浏览器,或者反“反盗链”

有些网站会检查你是在使用真的浏览器访问,还是机器自动访问的。这种情况,加上User-Agent,表明你是浏览器访问即可。有时还会检查是否带Referer信息,还会检查你的Referer是否合法,一般再加上Referer。

headers = {'User-Agent':'XXXXX'} # 伪装成浏览器访问,适用于拒绝爬虫的网站

headers = {'Referer':'XXXXX'}

headers = {'User-Agent':'XXXXX', 'Referer':'XXXXX'}

Requests:

response = requests.get(url=url, headers=headers)

Urllib2:

import urllib, urllib2

req = urllib2.Request(url=url, headers=headers)

response = urllib2.urlopen(req)

详细的,可以在middlewares.py中通过类对代理(浏览器)进行封装

from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware

class RotateUserAgentMiddleware(UserAgentMiddleware):

def __init__(self, user_agent=''):

self.user_agent = user_agent

def process_request(self, request, spider):

ua = random.choice(self.user_agent_list)

if ua:

#print ua, '-----------------yyyyyyyyyyyyyyyyyyyyyyyyy'

request.headers.setdefault('User-Agent', ua)

# the default user_agent_list composes chrome,IE,firefox,Mozilla,opera,netscape

# for more user agent strings,you can find it in http://www.useragentstring.com/pages/useragentstring.php

user_agent_list = [ \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" \

"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", \

"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", \

"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", \

"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \

"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \

"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", \

"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \

"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"

]

4. 对于断线重连

不多说。

def multi_session(session, *arg):

retryTimes = 20

while retryTimes>0:

try:

return session.post(*arg)

except:

print '.',

retryTimes -= 1

或者

def multi_open(opener, *arg):

retryTimes = 20

while retryTimes>0:

try:

return opener.open(*arg)

except:

print '.',

retryTimes -= 1

这样我们就可以使用multi_session或multi_open对爬虫抓取的session或opener进行保持。

或者设置失败后自动重试

def get(self,req,retries=3):

try:

response = self.opener.open(req)

data = response.read()

except Exception , what:

print what,req

if retries>0:

return self.get(req,retries-1)

else:

print 'GET Failed',req

return ''

return data

5. 多进程抓取

单线程太慢的话,就需要多线程了,这里给个简单的线程池模板 这个程序只是简单地打印了1-10,但是可以看出是并发地。

from threading import Thread

from Queue import Queue

from time import sleep

#q是任务队列

#NUM是并发线程总数

#JOBS是有多少任务

q = Queue()

NUM = 2

JOBS = 10

#具体的处理函数,负责处理单个任务

def do_somthing_using(arguments):

print arguments

#这个是工作进程,负责不断从队列取数据并处理

def working():

while True:

arguments = q.get()

do_somthing_using(arguments)

sleep(1)

q.task_done()

#fork NUM个线程等待队列

for i in range(NUM):

t = Thread(target=working)

t.setDaemon(True)

t.start()

#把JOBS排入队列

for i in range(JOBS):

q.put(i)

#等待所有JOBS完成

q.join()

6. 对于Ajax请求的处理

对于“加载更多”情况,使用Ajax来传输很多数据。

它的工作原理是:从网页的url加载网页的源代码之后,会在浏览器里执行JavaScript程序。这些程序会加载更多的内容,“填充”到网页里。这就是为什么如果你直接去爬网页本身的url,你会找不到页面的实际内容。

这里,若使用Google Chrome分析”请求“对应的链接(方法:右键→审查元素→Network→清空,点击”加载更多“,出现对应的GET链接寻找Type为text/html的,点击,查看get参数或者复制Request URL),循环过程。

· 如果“请求”之前有页面,依据上一步的网址进行分析推导第1页。以此类推,抓取Ajax地址的数据。

· 对返回的json格式数据(str)进行正则匹配。json格式数据中,需从'\uxxxx'形式的unicode_escape编码转换成u'\uxxxx'的unicode编码。

7. 自动化测试工具Selenium

Selenium是一款自动化测试工具。它能实现操纵浏览器,包括字符填充、鼠标点击、获取元素、页面切换等一系列操作。总之,凡是浏览器能做的事,Selenium都能够做到。

如:如何在给定城市列表后,使用selenium来动态抓取去哪儿网的票价信息的代码?

8. 验证码识别

对于网站有验证码的情况,我们有三种办法:

· 使用代理,更新IP。

· 使用cookie登陆。

· 验证码识别。

使用代理和使用cookie登陆之前已经讲过,下面讲一下验证码识别。

可以利用开源的Tesseract-OCR系统进行验证码图片的下载及识别,将识别的字符传到爬虫系统进行模拟登陆。当然也可以将验证码图片上传到打码平台上进行识别。如果不成功,可以再次更新验证码识别,直到成功为止。

参考项目:验证码识别项目第一版:Captcha1

爬取有两个需要注意的问题:

· 如何监控一系列网站的更新情况,也就是说,如何进行增量式爬取?

· 对于海量数据,如何实现分布式爬取?

9.编码问题

在解析的过程中要注意编码问题,因为网页有UTF-8 编码的,也有GBK编码的,还有GB2312等等. 如果编码问题没有处理好,很有可能会导致输入输出异常,正则表达式匹配错误等问题.我的解决办法是坚持一个中心思想: "不管你是什么编码来的,到解析程序统一换成utf-8编码".比如有的网页是GBK编码,在处理之前我会先对它进行一个转码操作:

utf8_page = GBK_page.decode("GBK").encode("utf8")

同时在代码的初始化位置(或者是最开始部分)我一般会加上以下代码:

import sys

reload(sys)

sys.setdefaultencoding('utf8')

同时代码文件的编码方式也要保证是utf-8.

这样处理调理比较清晰,统一.不会出现一个utf-8的正则表达式和一个GBK的字符串做匹配最后啥也匹配不出来.或者输出的数据即有utf8编码的字符串,又有GBK编码的字符串导致IO错误.

如果事先不知道网页是什么编码,建议使用python 的第三方包chardet:https://pypi.python.org/pypi/chardet/ 它可以自动帮你识别出网页的编码.用法是:

import chardetimport urllib2

#可根据需要,选择不同的数据

TestData = urllib2.urlopen('http://www.baidu.com/').read()print chardet.detect(TestData)

分析

抓取之后就是对抓取的内容进行分析,你需要什么内容,就从中提炼出相关的内容来。

常见的分析工具有正则表达式,BeautifulSoup,lxml等等。

存储

分析出我们需要的内容之后,接下来就是存储了。

我们可以选择存入文本文件,也可以选择存入MySQL或MongoDB数据库等。

存储有两个需要注意的问题:

· 如何进行网页去重?

· 内容以什么形式存储?

Scrapy

Scrapy是一个基于Twisted的开源异构的Python爬虫框架,在工业中应用非常广泛。

Python网络爬虫阶段总结相关推荐

  1. python网络爬虫教程-终于明了python网络爬虫从入门到实践

    Python是一款功能强大的脚本语言,具有丰富和强大的库,重要的是,它还具有很强的可读性,易用易学,非常适合编程初学者入门.以下是小编为你整理的python网络爬虫从入门到实践 环境配置:下载Pyth ...

  2. python与excel结合能做什么-Python网络爬虫与文本数据分析

    原标题:Python网络爬虫与文本数据分析 课程介绍 在过去的两年间,Python一路高歌猛进,成功窜上"最火编程语言"的宝座.惊奇的是使用Python最多的人群其实不是程序员,而 ...

  3. python网络爬虫的基本步骤-python爬虫入门需要哪些基础/python 网络爬虫教程

    如何入门 Python 爬虫 入门个吊,放弃 python爬虫入门需要哪些基础 现在之所以有多的小伙伴热衷于爬虫技术,无外乎是因为爬我们做很多事情,比如搜索引擎.采集数据.广告过滤等,以Python为 ...

  4. python网络爬虫技术课后答案_尔雅《Python网络爬虫技术(2020年秋季学期)》网课答案...

    尔雅<Python网络爬虫技术(2020年秋季学期)>网课答案 法律的一般含义是() 答:法律是由国家创制并保证实施的行为规范 下列属于急症手术的是 答:肝破裂 脾气统摄血液的功能,实际上 ...

  5. 小猿学python_小猿圈详解小白如何学习Python网络爬虫

    人工智能发展的今天,现在很多企业也都在学习python技术开发,但是真正会的却不是很多,特别是很多都喜欢爬虫,因为可以爬取一些自己喜欢的内容,那么对于小白的话该如何学习python爬虫呢?下面小猿圈P ...

  6. Python网络爬虫专业级框架_scrapy

    首先感慨下当今的互联网,08年刚来北京工作的时候什么也没有.出去面试全凭一张纸质的北京地图跟一张嘴.学习还停留在看书的阶段(天天上下班的公交车上看书看到睡着,哈哈). 通过这段时间的学习,初步掌握了如 ...

  7. 人生苦短,我用 Python,如何学习 Python 网络爬虫?

    人生苦短,我用 Python Python 网络爬虫上手很快,能够尽早入门,可是想精通确实是需求些时间,需求达到爬虫工程师的级别更是需求煞费苦心了,接下来共享的学习道路是针对小白或许学习 Python ...

  8. python网络爬虫教程(四):强大便捷的请求库requests详解与编程实战

    上一章中,我们了解了urllib的基本用法,详情可浏览如下链接python网络爬虫教程(三):详解urllib库,但其中确实有不方便的地方,为此,我们可以使用更方便更简洁的HTTP请求库request ...

  9. 爬虫书籍-Python网络爬虫权威指南OCR库 NLTK 数据清洗 BeautifulSoup Lambda表达式 Scrapy 马尔可夫模型

    Python网络爬虫权威指南 编辑推荐 适读人群 :需要抓取Web 数据的相关软件开发人员和研究人员 作为一种采集和理解网络上海量信息的方式,网页抓取技术变得越来越重要.而编写简单的自动化程序(网络爬 ...

  10. python网络爬虫_Python网络爬虫——爬取视频网站源视频!

    原标题:Python网络爬虫--爬取视频网站源视频! 学习前提 1.了解python基础语法 2.了解re.selenium.BeautifulSoup.os.requests等python第三方库 ...

最新文章

  1. Linux驱动程序编写
  2. CSS3弹性盒模型之box-orient box-direction
  3. Spring Boot 入门之基础篇(一)
  4. 一点点学习PS--实战四
  5. 实验一 小凡和VMware虚拟机的使用练习
  6. JavaScript from C#(入门篇)
  7. Pandas CookBook -- 04选取数据子集
  8. 第三篇.python编辑器和集成环境01
  9. angular中的href=unsafe:我该怎么摆脱你的溺爱!!
  10. java spring 过滤器_java – 如何在spring-security中的另一个过滤器之前添加过滤器?...
  11. Curie Module是什么
  12. Vue和React组件之间的传值方式
  13. 人脸识别的代码及问题
  14. 浅谈机器学习-分类和聚类的区别
  15. linux虚拟机简单部署以及安装可视化界面
  16. DSP CCS软件仿真
  17. 金蝶K3工资模块个税计算公式
  18. QHeaderView 表头设置QWidget控件
  19. 2022年打工人转行实录!你后悔转行了吗?
  20. 赤霉素3β-羟化酶的下调增强了大豆的光合作用并提高了种子产量

热门文章

  1. SPSS数据分析-交叉表分析
  2. openBSD安装桌面
  3. 超弦计算机,物理学四大神兽——拉普拉斯妖
  4. 不会比这更详细的前端工程化的入门教程了
  5. layui爬坑之路——input value属性绑定函数返回值
  6. 谱尼测试凭借现代化的测试平台
  7. C语言二级操作题满分班(2015年9月方法篇)-叶冬冬-专题视频课程
  8. turtle库画一个正方形
  9. 提前实现盈利的快手还有多少成长空间?
  10. ios播放器横竖屏切换的问题