爬虫
基本流程
- 准备工作 #分析页面等
- 获取数据
- 解析内容
- 保存数据
设计思路
- 确定需要爬取的页面url地址
- 通过http请求获取http页面
- 提取html页面有用数据:
a.如果是需要的内容,保存起来
b.如果是url地址,执行第2步继续提取
可以做爬虫的语言很多,如PHP、java、c/c++、python等
- php天生不是干这个的。而且对多线程、异步支持不够好。并发处理能力若,爬虫是工具性程序,对效率要求高。
- java的网络爬虫生态圈也很完善,是python最大对手。但java本身很笨重,代码量很大。重构成本高,任何修改会导致代码大量变动。爬虫经常需要修改部分内容。
- C/C++运行效率几乎最强,但是学习成本很高,代码成型比较慢。能用C/C++做爬虫不是正确的选择。
- python语法优美代码简洁、开发效率高,支持模块多,次昂管http请求模块很多,还有强大的爬虫Scrapy,以及成熟高效的分布式策略,其他接口也很方便(胶水语言)
通用爬虫 聚焦爬虫
通用爬虫
搜索引擎用的爬虫系统。
目标:尽可能把互联网所有网页下载下来形成备份,再对这些网页做相关处理,最后提供给用户一个搜索接口
搜索引擎如何获取新网站的url地址:
- 主动向搜索引擎提交网址。
- 在其他网站里设置外链(友情链接、外部链接)
- 搜索引擎会和DNS服务商合作,快速收录新的网站。
通用爬虫并不是万物皆可爬,它也需要遵守协议。(robots协议 规定哪些可以爬,哪些不让爬// 并不是所有爬虫都遵守,一般只有大型搜索引擎遵守,我们自己写的爬虫,就不管了)
通用爬虫工作流程
爬取网页---存储数据-----内容处理-----提供检索/排名服务
通用爬虫缺点:
- 只能提供和文本相关的内容(html、word等),不能提供多媒体内容(音乐、图片等)
- 提供的内容千篇一律,不能针对不同人有不同结果,
- 不能理解人类语义上的检索。
聚焦爬虫
为了解决通用爬虫存在的问题
针对某种内容的爬虫
面向主题爬虫、会针对某种特定内容爬取信息。
http和https工作原理
请求与响应。
请求主要分为get和post两种(区别:信息是否隐藏)
urllib2库的基本使用
第一个爬虫程序
import urllib2
ua_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"
}
# 通过urllib2.Request() 方法构造一个请求对象
request = urllib2.Request("http://www.baidu.com/", headers = ua_headers)
# 向指定的url地址发送请求,并返回服务器响应的类文件对象
response = urllib2.urlopen(request)
# 服务器返回的类文件对象支持Python文件对象的操作方法
# read()方法就是读取文件里的全部内容,返回字符串
html = response.read()
# 返回 HTTP的响应码,成功返回200,4服务器页面出错,5开头的,服务器问题
print response.getcode()
# 返回 返回实际数据的实际URL,防止重定向问题
print response.geturl()
# 返回 服务器响应的HTTP报头
print response.info()
注:
- user-agent 必须设置的内容(模拟浏览器),反爬斗争第一步。
第二个爬虫程序(user-agent列表 反爬)
import urllib2
import random
url = "http://www.baidu.com/"
# 可以是User-Agent列表,也可以是代理列表
ua_list = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_7\_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"
]
# 在User-Agent列表里随机选择一个User-Agent
user_agent = random.choice(ua_list)
# 构造一个请求
request = urllib2.Request(url)
# add_header()方法 添加/修改 一个HTTP报头
#也可以用第一种方法
request.add_header("User-Agent", user_agent)
# get_header() 获取一个已有的HTTP报头的值,注意只能是第一个字母大写,其他的必须小写
print request.get_header("User-agent")
get和post的区别
- get:url附带带参数
- post:url不带参数
- get请求参数在queryString中保存
- post请求单数在porm表单中保存
第三个爬虫程序:(模拟post请求的爬虫)
import urllib
import urllib2
# 通过抓包的方式获取的url,并不是浏览器上显示的url
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"
# 完整的headers
#注意要在原本数据上去掉没有的和不能留的信息
headers = {
"Accept" : "application/json, text/javascript, */*; q=0.01",
"X-Requested-With" : "XMLHttpRequest",
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
}
# 用户接口输入
key = raw_input("请输入需要翻译的文字:")
# 发送到web服务器的表单数据(通过抓包获得)
formdata = {
"type" : "AUTO",
"i" : key,
"doctype" : "json",
"xmlVersion" : "1.8",
"keyfrom" : "fanyi.web",
"ue" : "UTF-8",
"action" : "FY_BY_CLICKBUTTON",
"typoResult" : "true"
}
# 经过urlencode转码(有中文的时候需转)
data = urllib.urlencode(formdata)
# 如果Request()方法里的data参数有值,那么这个请求就是POST
# 如果没有,就是Get
#因为get没有请求体,post有请求体
request = urllib2.Request(url, data = data, headers = headers)
print urllib2.urlopen(request).read()
异步 ajax加载方式的数据的获取
ajax方式加载的页面,数据格式一定是JSON
拿到json,就是拿到了要获取的数据
import urllib
import urllib2
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action"
#请求头
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
#post要传递的表单原始数据
formdata = {
"start":"0",
"limit":"20"
}
#转码为可识别的post传递的数据
data = urllib.urlencode(formdata)
request = urllib2.Request(url, data = data, headers = headers)
print urllib2.urlopen(request).read()
##直接请求得到json就是我们要的数据
利用cookie模拟登录
import urllib2
url = "http://www.renren.com/410043129/profile"
headers = {
"Host" : "www.renren.com",
"Connection" : "keep-alive",
#"Upgrade-Insecure-Requests" : "1",
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
"Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Referer" : "http://www.renren.com/SysHome.do",
########################################
#这个东西是千万不能要!!!
#"Accept-Encoding" : "gzip, deflate, sdch",
"Cookie" : "anonymid=ixrna3fysufnwv; _r01_=1; depovince=GW; jebe_key=f6fb270b-d06d-42e6-8b53-e67c3156aa7e%7Cc13c37f53bca9e1e7132d4b58ce00fa3%7C1484060607478%7C1%7C1484400895379; jebe_key=f6fb270b-d06d-42e6-8b53-e67c3156aa7e%7Cc13c37f53bca9e1e7132d4b58ce00fa3%7C1484060607478%7C1%7C1484400890914; JSESSIONID=abcX8s_OqSGsYeRg5vHMv; jebecookies=0c5f9b0d-03d8-4e6a-b7a9-3845d04a9870|||||; ick_login=8a429d6c-78b4-4e79-8fd5-33323cd9e2bc; _de=BF09EE3A28DED52E6B65F6A4705D973F1383380866D39FF5; p=0cedb18d0982741d12ffc9a0d93670e09; ap=327550029; first_login_flag=1; ln_uact=mr_mao_hacker@163.com; ln_hurl=http://hdn.xnimg.cn/photos/hdn521/20140529/1055/h_main_9A3Z_e0c300019f6a195a.jpg; t=56c0c522b5b068fdee708aeb1056ee819; societyguester=56c0c522b5b068fdee708aeb1056ee819; id=327550029; xnsid=5ea75bd6; loginfrom=syshome",
"Accept-Language" : "zh-CN,zh;q=0.8,en;q=0.6",
}
request = urllib2.Request(url, headers = headers)
response = urllib2.urlopen(request)
print response.read()
访问https协议的页面
import urllib2
###########添加的内容##########################
import ssl
# 忽略SSL安全认证
context = ssl._create_unverified_context()
url = "https://www.12306.cn/mormhweb/"
#url = "https://www.baidu.com/"
headers = {
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"
}
request = urllib2.Request(url, headers = headers)
# 添加到context参数里
response = urllib2.urlopen(request, context = context)
print response.read()·
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。