网络爬虫概述
网络爬虫:
网络蜘蛛(网络机器人),用来抓去网络数据的程序
用python程序去模仿人去访问网站,模仿的越逼真越好
爬取数据的目的:
通过有效的大量数据来分析市场走势、公司决策
企业获取数据的方式:
1. 公司自有数据
2. 第三方数据平台购买(数据堂、贵阳大数据交易所)
3. 爬虫爬取数据
市场上没有或者价格太高,利用爬虫程序爬取
python做爬虫优势:
请求模块、解析模块丰富成熟,强大的scrapy框架
----------------------------------
PHP: 对多线程、异步支持不太好
Java: 代码笨重,代码量大
C/C++: 虽然效率高, 但代码成型很慢
----------------------------------
爬虫的分类
1. 通用网络爬虫(搜索引擎使用,需要遵守robots协议)
查看方式: (www.taobao.com/robots.txt)
1) 搜索引擎如何获取一个新网站的URL
1)) 网站主动向搜索引擎提供(百度站长平台)
2)) 和DNS服务网(万网),快速收录新网站
2. 聚焦网络爬虫
自己写的爬虫程序: 面向主题的爬虫、面相需求的爬虫
爬虫 <===> 反爬虫 <===> 反反爬虫
爬取数据步骤
爬取数据步骤:
1. 确定需要爬去的URL地址
2. 通过HTTP/HTTPS协议来获取相应的HTML页面
3. 提取HTML页面有用的数据
1) 所需数据保存
2) 页面中有其他URL,继续循环第2步
开发环境 Anacoda 和 Spyder
1.Anaconda : 开源的Python发行版本 解决库之间的依赖关系
2.Spyder : 集成开发环境
3.Chrome 浏览器插件:
JSONView(格式化JSON文件)
Xpath Helper(网页数据解析插件)
Proxy SwithOmega(代理切换插件)
4.抓包工具 Fiddler 5.0
WEB
1.HTTP和HTTS
1)HTTP: port:80
2)HTTPS: port:443, HTTP的升级版,加了一个安全套接层
2.GET和POST
1) GET:查询参数都会在URL上显示出来
2) POST:查询参数和需要提交数据是隐藏在Form表单里的,不会在URL地址上显示
3.URL:统一资源定位符
https:// item.jd.com :80 /26809408972.html #detail
协议 域名/IP地址 端口 访问资源的路径 锚点
4.User-Agent
记录用户的浏览器、操作系统等,为了让用户获取更好的HTML页面效果
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWeb Kit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100
Safari/537.36
Mozilla Firefox :(Gecko内核)
IE :Trident(自己的内核)
Linux : KTHML(like Gecko)
Apple :Webkit(like KHTML)
Google:Chrome(like Webkit)
其他浏览器都是模仿IE/Chrome
爬虫请求模块
urllib.request 模块
1.版本
python2: urllib / urllib2
python3: urllib.request
2.常用方法:
1) urlopen("网址")
作用: 向 网址 发起一个请求并获取响应
eg: User-Agent:python
import urllib.request
response = urllib.request.urlopen("http://www.baidu.com/")
html = response.read() #获取响应字节流
print(html.decode('utf-8'))
2) 重构 User-Agent
1.urlopen() 不支持重构 User-Agent
2.urllib.request.Request() 支持重构 User-Agent 方法
urllib.request.Request("网址",headers = "字典")
****User-Agent 是爬虫和反爬虫斗争的第一步
发送请求必须要带 User-Agent
使用流程:
1. 利用Request()方法构建一个请求对象
2. 利用urlopen()方法来获取响应对象
3. 利用响应对象read().decode("utf-8")来获取内容
import urllib.request
#创建请求对象(user-agent)
url = "http://www.baidu.com/"
headers = {"User-Agent":
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"}
req = urllib.request.Request(url,headers = headers)
#获取响应对象(urlopen)
res = urllib.request.urlopen(req)
#响应对象方法 read().decode("utf-8")
html = res.read().decode("utf-8")
print(html)
3.响应对象的常用方法
1) read(): 读取服务器响应的内容
2) getcode(): 返回HTTP的响应码
成功返回200,4xx 服务器页面出错,5xx服务器出错
3) geturl():返回响应实际数据的URL(防止重定向问题)
urllib.parse 模块
urllib.parse 模块作用:
百度中搜索爬虫,得到网址为
https://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB
1. urlencode(字典) #主注意: 参数一定要为字典
urlencode({"wd":"爬虫"})
wd=%E7.......
import urllib.parse
temp = {"wd":"爬虫"}
temp = urllib.parse.urlencode(temp)
print(temp)
2.quote(字符串)
temp = urllib.parse.quote("爬虫")
抓取百度贴吧数据
import urllib.request
import urllib.parse
import random
import time
#抓取百度贴吧数据
#随机获取一个User-Agent
header_list = [{"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"},
{"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0"},
{"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"}]
headers = random.choice(header_list)
baseurl = "https://tieba.baidu.com/f?"
name = input("请输入您要的贴吧名>>>")
begin = int(input("起始页>>>"))
end = int(input("终止页>>>"))
kw = {"kw":name}
kw = urllib.parse.urlencode(kw)
for i in range(begin,end+1):
#拼接url
pn = (i-1)*50
url = baseurl+ kw +"&pn="+str(pn)
req = urllib.request.Request(url,headers = headers)
res = urllib.request.urlopen(req,timeout = 5)
html = res.read()
filename = "h"+str(i)+".html"
#写入文件
with open(filename,"wb") as f:
print("正在爬取第%d页" % i)
f.write(html)
print("第%d页爬取结束" % i)
print("*"*20)
time.sleep(2)
类和函数封装
#从百度贴吧获取网页
import urllib.request
import urllib.parse
import random
import time
#读取页面
def readPage(url):
headers = {"User-Agent":
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"}
req = urllib.request.Request(url,headers=headers)
res = urllib.request.urlopen(req,timeout=5)
html = res.read().decode('utf-8')
return html
#写入文件
def writePage(filename,html):
with open(filename,'w',encoding = 'utf-8') as f:
f.write(html)
print("write success")
#主函数
def workOn():
baseurl = "https://tieba.baidu.com/f?"
name = input("请输入您要的贴吧名>>>")
begin = int(input("起始页>>>"))
end = int(input("终止页>>>"))
kw = {"kw":name}
kw = urllib.parse.urlencode(kw)
for i in range(begin,end+1):
#拼接url
filename = "第%d个页面.html" % i
pn = (i-1)*50
url = baseurl+ kw +"&pn="+str(pn)
html = readPage(url)
writePage(filename,html)
time.sleep(1)
if __name__ == "__main__":
workOn()
#用类封装
#从百度贴吧获取网页
import urllib.request
import urllib.parse
import random
import time
class BaiduSpider(object):
def __init__(self):
self.headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"}
self.baseurl = "https://tieba.baidu.com/f?"
def readPage(self,url):
req = urllib.request.Request(url,headers=self.headers)
res = urllib.request.urlopen(req,timeout=5)
html = res.read().decode('utf-8')
return html
def writePage(self,filename,html):
with open(filename,'w',encoding = 'utf-8') as f:
f.write(html)
print("write success")
def workOn(self):
'''最终爬取'''
name = input("请输入您要的贴吧名>>>")
begin = int(input("起始页>>>"))
end = int(input("终止页>>>"))
kw = {"kw":name}
kw = urllib.parse.urlencode(kw)
for i in range(begin,end+1):
#拼接url
filename = "第%d个页面.html" % i
pn = (i-1)*50
url = self.baseurl+ kw +"&pn="+str(pn)
html = self.readPage(url)
self.writePage(filename,html)
time.sleep(1)
if __name__ == "__main__":
spider = BaiduSpider()
spider.workOn()
请求方式及案例
GET 方式:
特点: 查询参数在URL地址中显示
案例: 抓去百度贴吧
POST 方式:
urllib.request.Request(url,headers=headers,data=......)
#Request()中添加data参数以bytes格式提交
处理表单数据为bytes类型:
1. 把Form表单数据定义为字典
2. urlencode(字典)
3. 转为bytes数据类型: bytes()
案例:有道翻译
返回json格式字符串,如何把json格式的字符串转换为python中字典
import json
r_dict = json.loads(r_json)
#有道翻译 POST 请求方式
import urllib.request
import urllib.parse
import json
#表单编码
key = input("请输入要翻译的内容>>>")
data = {'i': key,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '15706089102276',
'sign': 'fe13485d0dd7803b64d5a239f8d65dce',
'ts': '1570608910227',
'bv': '4aa7828b641c5e2587e46a4b35eb3523',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'}
#字符串 i=key&from=auto...
data = urllib.parse.urlencode(data)
data = bytes(data,'utf-8')
#发请求,获取响应
#为POST的地址
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
headers = {"User-Agent":"Mozilla/5.0"}
req = urllib.request.Request(url,data = data,headers = headers)
res = urllib.request.urlopen(req)
html = res.read().decode('utf-8')
html = json.loads(html)
print(html['translateResult'][0][0]['tgt'])