中秋三天,把爬虫一些基础的东西过了一遍,还没有过完,等以后有时间了再来继续
Day1******************************************************************
1、定义 :网络蜘蛛、网络机器人,抓取网络数据的程序
2、总结 :用Python程序去模仿人去访问网站,模仿的越逼真越好
3、爬取数据的目的 :通过有效的大量数据分析市场走势、公司决策
1、公司自有数据
2、第三方数据平台购买
数据堂、贵阳大数据交易所
3、爬虫爬取数据
市场上没有或者价格太高,利用爬虫程序爬取
请求模块、解析模块丰富成熟,强大的scrapy框架
PHP :对多线程、异步支持不太好
JAVA :代码笨重,代码量很大
C/C++ :虽然效率高,但是代码成型很慢
http://www.taobao.com/robots.txt
1、搜索引擎如何获取一个新网站的URL
1、网站主动向搜索引擎提供(百度站长平台)
2、和DNS服务网(万网),快速收录新网站
自己写的爬虫程序:面向主题的爬虫、面向需求的爬虫
1、所需数据,保存
2、页面中有其他的URL,继续 第2步
Spyder常用快捷键:
1、注释/取消注释 :ctrl + 1(数字)
2、保存 :ctrl + s
3、运行程序 :f5
4、自动补全 :Tab
1、右上角 - 更多工具 - 扩展程序
2、点开右上角 - 开发者模式
3、把插件 拖拽到 浏览器页面,释放鼠标,点击 添加扩展...
1、Proxy SwitchOmega :代理切换插件
2、Xpath Helper :网页数据解析插件
3、JSON View :查看json格式的数据(好看)
添加证书信任的方法:证书生成器(fiddlercertmaker.exe)
1、Tools->options->HTTPS->...from browers only
2、connections :设置端口号 8888
Proxy SwitchOmega -> 选项 -> 新建情景模式 -> HTTP 127.0.0.1 8888 -> 应用选项
浏览器右上角图标 -> AID1806 -> 访问百度
1、HTTP :80
2、HTTPS :443,HTTP的升级版,加了一个安全套接层(socket)
1、GET :查询参数都会在URL上显示出来
2、POST:查询参数和需要提交数据是隐藏在Form表单里的,不会在URL地址上显示
https:// item.jd.com :80 /26809408972.html #detail
协议 域名/IP地址 端口 访问资源的路径 锚点(data-anchor:写哪跳到哪)
记录用户的浏览器、操作系统等,为了让用户获取更好的HTML页面效果
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
我的电脑:
`User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36`
User-Agent大全
Mozilla Firefox :(Gecko内核)
IE :Trident(自己的内核)
Linux : KTHML(like Gecko)
Apple :Webkit(like KHTML)
Google:Chrome(like Webkit)
其他浏览器都是模仿IE/Chrome
1、python2 :urllib2、urllib
2、python3 :把urllib和urllib2合并,urllib.request
1、urllib.request.urlopen("网址")
例子:
import urllib.request
# response为响应对象
response = urllib.request.urlopen("http://www.baidu.com/")
html = response.read().decode("utf-8")
print(html)
1、作用 :向网站发起一个请求并获取响应
字节流 = response.read()
字符串 = response.read().decode("utf-8")
#encode() 字符串 --> bytes数据类型
#decode() bytes数据类型 --> 字符串
2、重构User-Agent
1、不支持重构User-Agent :urlopen()
2、支持重构User-Agent
urllib.request.Request(添加User-Agent)
2、urllib.request.Request("网址",headers="字典")
User-Agent是爬虫和反爬虫斗争的第一步,发送请求必须带User-Agent
1、使用流程
1、利用Request()方法构建请求对象
2、利用urlopen()方法获取响应对象
3、利用响应对象的read().decode("utf-8")获取内容
例子:
url = "https://www.baidu.com/"
headers = {"User-Agent":"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"}
import urllib.request
#1.创建一个请求对象(User-Agent)
req = urllib.request.Request(url,headers = headers)
#2.获取响应对象(urlopen())
res = urllib.request.urlopen(req)
#3.响应对象read().decode("utf-8")
html = res.read().decode("utf-8")
print(html)
2、响应对象response的方法
1、read() :读取服务器响应的内容
2、getcode()作用:返回HTTP的响应码
print(respones.getcode())
200 :成功
4XX :服务器页面出错
5XX :服务器出错
3、geturl()作用 :返回实际数据的URL(防止重定向问题)
例子:
import urllib.request
url = "http://www.baidu.com/"
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"}
# 1.创建请求对象(有User-Agent)
req = urllib.request.Request(url,headers=headers)
# 2.获取响应对象(urlopen())
res = urllib.request.urlopen(req)
# 3.响应对象read().decode("utf-8")
#html = res.read().decode("utf-8")
#print(html)
print(res.getcode())
print(res.geturl())
3、urllib.parse模块
secret:%E8%B0%A2%E7%A6%B9%E6%95%8F
1、urlencode(字典) ## 注意:参数一定要为字典
urlencode({"wd":"美女"})
wd=%e8.......
tedu = {"wd":"万科"}
示例见 :04_urllib.parse.urlencode示例.py
#%E8%B0%A2%E7%A6%B9%E6%95%8F
import urllib.parse
tedu = {"miss":"miss you"}
tedu = urllib.parse.urlencode(tedu)
print(tedu)
请输入你要搜索的内容:美女
保存到本地文件 :美女.html
代码:
import urllib.request
import urllib.parse
#拼接URL
baseurl = "http://www.baidu.com/s?"
key = input("请输入要搜索的内容:")
#进行URLencode()编码
wd = {"wd":key}
key = urllib.parse.urlencode(wd)
url = baseurl + key
headers = {"User_Agebt":"MOzilla/5.0"}
#创建请求对象
req = urllib.request.Request(url,headers = headers)
#获取响应对象
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
#写入本地文件
with open("搜索.html","w",encoding = "gb18030") as f:
f.write(html)
2、quote(字符串)
key = urllib.parse.quote("字符串")
baseurl = "http://www.baidu.com/s?wd="
key = input("请输入要搜索的内容:")
#进行quote()编码
key = urllib.parse.quote(key)
url = baseurl + key
print(url)
例子:
import urllib.request
import urllib.parse
#拼接URL
baseurl = "http://www.baidu.com/s?wd="
key = input("请输入要搜索的内容:")
#进行quote()编码
key = urllib.parse.quote(key)
url = baseurl + key
print(url)
headers = {"User_Agebt":"MOzilla/5.0"}
#创建请求对象
req = urllib.request.Request(url,headers = headers)
#获取响应对象
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
#写入本地文件
with open("搜索2.html","w",encoding = "gb18030") as f:
f.write(html)
百度贴吧数据抓取
要求:
1、输入要抓取的贴吧名称
2、输入爬取的起始页和终止页
3、把每一页的内容保存到本地
第1页.html 第2页.html ... ...
步骤:
1、找URL规律,拼接URL
第1页:http://tieba.baidu.com/f?kw=??&pn=0
第2页:http://tieba.baidu.com/f?kw=??&pn=50
第3页:http://tieba.baidu.com/f?kw=??&pn=100
.....
第n页:pn=(n-1)*50
2、获取网页内容(发请求获响应)
3、保存(本地文件、数据库)
例子:易烊千玺百度贴吧抓取
import urllib.request
import urllib.parse
import random
import time
#随机获取一个User-Agent
header_list = [{"User-Agent":"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"},
{"User-Agent":"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"},
{"User-Agent":"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"}]
headers = random.choice(header_list)
#主体程序
name = input("请输入贴吧名:")
begin = int(input("请输入起始页:"))
end = int(input("请输入终止页:"))
#对贴吧名name进行编码
kw = {"kw":name}
kw = urllib.parse.urlencode(kw)
#拼接url,发请求,获响应
for i in range(begin,end + 1):
#拼接url
pn = (i -1) * 50
url = "http://tieba.baidu.com/f?" + kw + "&pn=" + str(pn)
#http://tieba.baidu.com/f?kw=??&pn=0
#发请求
req = urllib.request.Request(url,headers = headers)
res = urllib.request.urlopen(req,timeout = 5)
time.sleep(2)
html = res.read().decode("utf-8")
#写入文件
filename = "第" + str(i) + "页.html"
with open(filename,"w",encoding="utf-8") as f:
print("正在爬取第%d页" % i)
f.write(html)
print("第%d页爬取成功" % i)
print("*" * 30)
1、特点 :查询参数在URL地址中显示
2、案例 :抓取百度贴吧
1、urllib.request.Request(url,data=data,headers=headers)
data :表单数据以bytes类型提交,不能是str
2、处理表单数据为bytes类型
1、把Form表单数据定义为字典data
2、urlencode(data)
3、转为bytes数据类型 :bytes()
3、有道翻译案例
代码:
import urllib.request
import urllib.parse
#请输入你要翻译的内容
key = input("请输入要翻译的内容:")
#把提交的form表单数据转为bytes数据类型
data = {"i": key,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": "15683634125285",
"sign": "44c86c0701f282f0c07bc8020847b2a6",
"ts": "1568363412528",
"bv": "53539dde41bde18f4a71bb075fcf2e66",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME",
"typoResult":"false"
}
#字符串 i = python& from =auto...
data = urllib.parse.urlencode(data)
data = bytes(data,"utf-8")
#发请求,获取响应
#url为POST的地址,抓包工具抓到的,此处去掉_o
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
headers = {"User-Agent":"Mozilla/5.0"}
#此处data为form表单数据,为bytes数据类型
req = urllib.request.Request(url,data = data,headers = headers)
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
print(html)
4、有道翻译返回的是json格式的字符串,如何把json格式的字符串转换为Python中字典
import json
r_dict = json.loads(r_json)
day2*******************************************************************************
1、结构化数据
特点 :有固定的格式,如 :HTML、XML、JSON
2、非结构化数据
示例 :图片、音频、视频,这类数据一般都存储为二进制
1、使用流程
1、创建编译对象 :p = re.compile("正则表达式")
2、对字符串匹配 :r = p.match("字符串")
3、获取匹配结果 :print(r.group())
2、常用方法
1、match(s) :字符串开头的第1个,返回对象
2、search(s):从开始往后找,匹配第1个,返回对象
3、group() :从match或search返回对象中取值
4、findall():所有全部匹配,返回一个列表
3、表达式
. 匹配任意字符(不能匹配\n)
\d 数字
\s 空白字符
\S 非空白字符
[...] 包含[]内容 :A[BCD]E --> ABE ACE ADE
\w 字母、数字、_
* 前一个字符出现0次或多次
? 前一个字符出现0次或1次
+ 前一个字符出现1次或多次
{m} 前一个字符出现m次
{m,n} 前一个字符出现m-n次 AB{1,3}C --> ABC ABBC ABBBC
贪婪匹配(.*) :在整个表达式匹配成功的前提下,尽可能多的匹配*
非贪婪匹配(.*?) :在整个表达式匹配成功的前提下,尽可能少的匹配*
4、示例(贪婪模式和非贪婪模式)
见 :见01_贪婪匹配和非贪婪匹配示例.py
import re
s = """众芳摇落独喧妍,占尽风情向小园
疏影横斜水清浅,暗香浮动月黄昏
"""
#创建编译对象,贪婪匹配
#re.S作用:使.能够以匹配\n在内的所有字符
#贪婪匹配是.*,
p = re.compile('.*
',re.S)
#非贪婪匹配:.*?
p = re.compile('.*?
',re.S)
#匹配字符串s
r = p.findall(s)
print(r)
5、findall()的分组(重要,但我没听懂)
import re
#解释 :先按照整体匹配出来,然后再匹配()中的
# 如果有2个或者多个(),则以元组的方式取显示
s = "A B C D"
p1 = re.compile('\w+\s+\w+')
print(p1.findall(s))
# ['A B','C D']
p2 = re.compile('(\w+)\s+\w+')
# 第1步 :['A B','C D']
# 第2步 :['A','C']
print(p2.findall(s))
p3 = re.compile('(\w+)\s+(\w+)')
# 第1步 :['A B','C D']
# 第2步 :[('A','B'),('C','D')]
print(p3.findall(s))
6、练习
import re
s = """
"""
#正则表达式
p = re.compile('.*?contents">(.*?)',re.S)
r = p.findall(s)
#print(r)
for animal in r:
print("动物名称:",animal[0].strip())
print("动物描述:",animal[1].strip())
7、案例1 :内涵段子脑筋急转弯抓取
见 :04_内涵段子脑筋急转弯抓取.py
网址 :www.neihan8.com
步骤:
1、找URL规律
第1页:https://www.neihan8.com/njjzw/
第2页:https://www.neihan8.com/njjzw/index_2.html
第3页:https://www.neihan8.com/njjzw/index_3.html
2、用正则匹配出 题目 和 答案
p = re.compile('(.*?)',re.S)
3、写代码
1、发请求
2、用正则匹配
3、写入本地文件
代码:
import urllib.request
import re
class NeihanSpider:
def __init__(self):
self.baseurl = "https://www.neihan8.com/njjzw/"
self.headers = {"User-Agent":"Mozilla/5.0"}
self.page = 1
# 下载页面
def loadPage(self,url):
req = urllib.request.Request(url,headers=self.headers)
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
self.parsePage(html)
# 解析页面
def parsePage(self,html):
p = re.compile('(.*?)',re.S)
r_list = p.findall(html)
# [("什么动物...","海豹"),(),()...]
self.writePage(r_list)
# 保存页面
def writePage(self,r_list):
for r_tuple in r_list:
for r_str in r_tuple:
with open("急转弯.txt","a",encoding="gb18030") as f:
f.write(r_str.strip() + "\n")
with open("急转弯.txt","a",encoding="gb18030") as f:
f.write("\n")
def workOn(self):
self.loadPage(self.baseurl)
while True:
c = input("成功,是否继续(y/n):")
if c.strip().lower() == "y":
self.page += 1
url = self.baseurl + "index_" +\
str(self.page) + ".html"
self.loadPage(url)
else:
print("爬取结束,谢谢使用!")
break
if __name__ == "__main__":
spider = NeihanSpider()
spider.workOn()
8、猫眼电影top100榜单,存到csv表格文件中
网址:猫眼电影 - 榜单 - top100榜
目标:抓取电影名、主演、上映时间
1、知识点讲解
1、csv模块的使用流程
1、打开csv文件
with open("测试.csv","a") as f:
2、初始化写入对象
writer = csv.writer(f)
3、写入数据
writer.writerow(列表)
2、示例
'''05_csv示例.py'''
import csv
with open("猫眼.csv","a",newline="") as f:
# 初始化写入对象
writer = csv.writer(f)
#把列表写入到文件中
writer.writerow(["电影名称","主演"])
writer.writerow(["霸王别姬","张国荣"])
writer.writerow(["唐伯虎点秋香","周星驰"])
2、准备工作
1、找URL
第1页:http://maoyan.com/board/4?offset=0
第2页:http://maoyan.com/board/4?offset=10
第n页:
offset = (n-1)*10
2、正则匹配
.*?title="(.*?)".*?(.*?)
.*?releasetime">(.*?)
3、写代码
代码:
'''06_猫眼电影top100抓取.py'''
import urllib.request
import re
import csv
class MaoyanSpider:
def __init__(self):
self.baseurl = "http://maoyan.com/board/4?offset="
self.headers = {"User-Agent":"Mozilla/5.0"}
self.page = 1
self.offset = 0
# 下载页面
def loadPage(self,url):
req = urllib.request.Request(url,headers=self.headers)
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
self.parsePage(html)
# 解析页面
def parsePage(self,html):
p = re.compile('.*?title="(.*?)".*?(.*?)
.*?releasetime">(.*?)',re.S)
r_list = p.findall(html)
# print(r_list)
# [("霸王别姬","张国荣","1994-01-01"),(),()...]
self.writePage(r_list)
def writePage(self,r_list):
if self.page == 1:
with open("猫眼电影.csv","a",newline="") as f:
writer = csv.writer(f)
writer.writerow(["电影名称","主演","上映时间"])
for r_tuple in r_list:
with open("猫眼电影.csv","a",newline="") as f:
# 创建写入对象
writer = csv.writer(f)
# L = list(r_tuple)
L = [r_tuple[0].strip(),r_tuple[1].strip(),r_tuple[2].strip()]
# ["霸王别姬","张国荣","1994-01-01"]
writer.writerow(L)
def workOn(self):
while True:
c = input("爬取请按y(y/n):")
if c.strip().lower() == "y":
self.offset = (self.page-1)*10
url = self.baseurl + str(self.offset)
self.loadPage(url)
self.page += 1
else:
print("爬取结束,谢谢使用!")
break
if __name__ == "__main__":
spider = MaoyanSpider()
spider.workOn()
2、Fiddler常用菜单
1)、Inspector : 查看抓到的数据包的详细内容
1、分为请求(request)和响应(response)两部分
2、常用选项
1、Headers :显示客户端发送到服务器的header,包含客户端信息、cookie、传输状态
2、WebForms :显示请求的POST数据
3、Raw :将整个请求显示为纯文本
3)、请求方式及案例
1、GET
2、POST
3、Cookie模拟登陆
1、什么是cookie、session
HTTP是一种无连接协议,客户端和服务器交互仅仅限于 请求/响应过程,结束后断开,下一次请求时,服务器会认为是一个新的客户端,为了维护他们之间的连接,让服务器知道这是前一个用户发起的请求,必须在一个地方保存客户端信息。
cookie :通过在客户端记录的信息确定用户身份
session :通过在服务端记录的信息确定用户身份
2、案例 :使用cookie模拟登陆人人网
见 :07_cookie模拟登陆人人网.py
步骤:
1、通过抓包工具、F12获取到cookie(先登陆1次网站)
2、正常发请求
url:http://www.renren.com/967469305/profile
代码:
'''07_cookie模拟登陆人人网.py'''
import urllib.request
url = "http://www.renren.com/967469305/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/69.0.3497.100 Safari/537.36",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Referer":"http://www.renren.com/",
# Accept-Encoding: gzip, deflate
"Accept-Language":"zh-CN,zh;q=0.9",
"Cookie":"anonymid=jnoaljpk7d3nh2; depovince=BJ; _r01_=1; _de=4DBCFCC17D9E50C8C92BCDC45CC5C3B7; ln_uact=13603263409; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; jebe_key=1b1f4a34-0468-4185-a3b0-6f2c38abc368%7C2012cb2155debcd0710a4bf5a73220e8%7C1540454149943%7C1%7C1540454153787; wp_fold=0; wp=0; jebecookies=2fc339e7-1b51-43ce-bc85-e2dc1f68ee16|||||; JSESSIONID=abcANrnqoMuLshY34pQAw; ick_login=30d0bd58-f6bb-437f-8d0d-6a72ae00e7b7; p=1e1b85cb8dda387a70e400a341c2e9c95; first_login_flag=1; t=4f652cc0a8f3fd50f5c9095c92d4717d5; societyguester=4f652cc0a8f3fd50f5c9095c92d4717d5; id=967469305; xnsid=55bff2d5; loginfrom=syshome"
}
req = urllib.request.Request(url,headers=headers)
res = urllib.request.urlopen(req)
print(res.read().decode("utf-8"))
'''cookie模拟登录CSDN网'''
import urllib.request
url = "https://i.csdn.net/#/uc/profile"
headers = {
"Host":"www.csdn.net",
"Connection":"keep-alive",
"Upgrade-Insecure-Requests":"1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36x-requested-with:XMLHttpRequest",
"Accept":"application/json, text/plain, */*",
"Referer":"//passport.csdn.net/login?code=public",
# Accept-Encoding: gzip, deflate
"Accept-Language":"zh-CN,zh;q=0.9",
"Cookie":"uuid_tt_dd=10_9868640580-1568772966185-773923; dc_session_id=10_1568772966185.480725; SESSION=2c6a7725-b303-466b-9e16-24802c6d133e; __guid=165585982.4138767749505633000.1568772966482.5442; monitor_count=1; UserName=BTZywl; UserInfo=b28e65a2eb3447e9886eca80ef825a61; UserToken=b28e65a2eb3447e9886eca80ef825a61; UserNick=%E5%8C%85%E5%B0%8F%E5%BD%A4; AU=E46; UN=BTZywl; BT=1568772981929; p_uid=U000000; Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1568701652,1568705441,1568715718,1568772986; Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac=1568772986; Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=1788*1*PC_VC!5744*1*BTZywl!6525*1*10_9868640580-1568772966185-773923; dc_tos=py08zk"
}
req = urllib.request.Request(url,headers = headers)
res = urllib.request.urlopen(req)
print(res.read().decode("utf-8"))
这里的url = "https://i.csdn.net/#/uc/profile"是自己的个人中心的网址,刚开始还不知道怎么弄,后来想了一下,试了试这个,竟然对了,还有一个需要改的地方是 “Host”:“www.csdn.net”,最后记得cookie当然是要改的了,多做一两个就明白了,果然睡醒之后的大脑是很聪明的。
4、requests模块
1、安装(用管理员身份去打开Anaconda Prompt)
Anaconda : conda install requests
Windows cmd: python -m pip install requests
## 以管理员身份去执行pip安装命令
2、常用方法
1、get(url,headers=headers) : 发起请求,获取响应对象
2、response属性
1、response.text :返回字符串类型
2、response.content : 返回bytes类型
1、应用场景 :爬取非结构化数据
2、示例:将网上的图片爬取到本地
代码:
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 14 16:32:45 2019
@author: aa
"""
import requests
url = "https://media.tenor.com/images/aab76b33f0da6f6841a6c063e3d89e78/tenor.gif"
headers = {"User-Agent":"Mozilla/5.0"}
res = requests.get(url,headers = headers)
html = res.content
with open("易烊千玺.jpg","wb") as f:
f.write(html)
print("图片下载成功")
这里需要注意的是图片的地址并不是导航栏上的地址,而是需要右键—>审查元素–>里面找到图片的地址,不然很可能爬不下来,我爬取大佬的照片的时候就遇到这个小问题了。
3、response.encoding :响应对象编码
一般返回 :ISO-8859-1
response.encoding = “utf-8”
4、response.status_code :返回服务器响应码
5、response.url :返回数据的URL地址
3、get()使用场景
1、没有查询参数
res = requests.get(url,headers=headers)
2、有查询参数: params={}
注 :params参数必须为字典,自动进行编码
见 :09_requests.get.params.py
代码:
'''09_requests.get.params.py'''
import requests
headers = {"User-Agent":"Mozilla/5.0"}
url = "http://www.baidu.com/s?"
key = input("请输入要搜索的内容:")
params = {"wd":key}
# 自动编码,自动拼接URL,params必须为字典
res = requests.get(url,params=params,headers=headers)
# 指定utf-8
res.encoding = "utf-8"
print(res.text)
4、post() 参数名 :data
1、data = {}
2、示例 :10_有道翻译post.py
代码:
'''10_有道翻译post.py'''
import requests
import json
# 请输入你要翻译的内容
key = input("请输入要翻译的内容:")
# post方法要求data为字典格式
data = {"i": key,
"from":"AUTO",
"to":"AUTO",
"smartresult":"dict",
"client":"fanyideskweb",
"salt":"1540373170893",
"sign":"a5d9b838efd03c9b383dc1dccb742038",
"doctype":"json",
"version":"2.1",
"keyfrom":"fanyi.web",
"action":"FY_BY_REALTIME",
"typoResult":"false"
}
# 发请求,获取响应
# url为POST的地址,抓包工具抓到的,此处去掉 _o
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
headers = {"User-Agent":"Mozilla/5.0"}
# 此处data为form表单数据
res = requests.post(url,data=data,headers=headers)
res.encoding = "utf-8"
html = res.text
# 把json格式字符串转换为Python中字典
r_dict = json.loads(html)
result = r_dict['translateResult'][0][0]["tgt"]
print(result)
Day3*************************************************************************
1、requests模块
1、代理(参数名:proxies)
1、获取代理IP的网站
西刺代理网站
快代理
全网代理
2、普通代理
proxies = {"协议":"协议://IP地址:端口号"}
183.129.207.82 11597
183.230.177.118 8060
www.whatismyip.com(一天只能访问5次)
查自己电脑上的ip:在终端输入ipconfig
3、私密代理(收费)
proxies = {"http":"http://309435365:[email protected]:21081"}
2、案例1 :爬取链家二手房信息 --> 存到MySQL数据库中
1、找URL
https://bj.lianjia.com/ershoufang/pg1/
2、正则
(.*?).*?.*?(.*?)(.*?)
3、写代码
代码:
'''05_链家数据ToMysql.py'''
import requests
import re
import pymysql
import warnings
class LianjiaSpider:
def __init__(self):
self.baseurl = "https://bj.lianjia.com/ershoufang/pg"
self.page = 1
self.headers = {"User-Agent":"Mozilla/5.0"}
self.proxies = {"http":"http://309435365:[email protected]:16817"}
self.db = pymysql.connect("localhost",
"root","123456",charset="utf8")
self.cursor = self.db.cursor()
def getPage(self,url):
res = requests.get(url,proxies=self.proxies,headers=self.headers,timeout=5)
res.encoding = "utf-8"
html = res.text
print("页面爬取成功,正在解析...")
self.parsePage(html)
def parsePage(self,html):
p = re.compile('(.*?).*?.*?(.*?)(.*?)',re.S)
r_list = p.findall(html)
# [("天通苑","480","万"),()..]
print("页面解析完成,正在存入数据库...")
self.writeTomysql(r_list)
def writeTomysql(self,r_list):
c_db = "create database if not exists Lianjiadb \
character set utf8"
u_db = "use Lianjiadb"
c_tab = "create table if not exists housePrice( \
id int primary key auto_increment,\
housename varchar(50), \
totalprice int)charset=utf8"
warnings.filterwarnings("ignore")
try:
self.cursor.execute(c_db)
self.cursor.execute(u_db)
self.cursor.execute(c_tab)
except Warning:
pass
ins = "insert into housePrice(housename,totalprice) \
values(%s,%s)"
for r_tuple in r_list:
name = r_tuple[0].strip()
price = float(r_tuple[1].strip())*10000
L = [name,price]
self.cursor.execute(ins,L)
self.db.commit()
print("存入数据库成功")
def workOn(self):
while True:
c = input("爬取按y(q退出):")
if c.strip().lower() == "y":
url = self.baseurl + str(self.page) + "/"
self.getPage(url)
self.page += 1
else:
self.cursor.close()
self.db.close()
print("爬取结束,谢谢使用!")
break
if __name__ == "__main__":
spider = LianjiaSpider()
spider.workOn()
'''06_链家数据ToMongo.py'''
import requests
import re
import pymongo
class LianjiaSpider:
def __init__(self):
self.baseurl = "https://bj.lianjia.com/ershoufang/pg"
self.page = 1
self.headers = {"User-Agent":"Mozilla/5.0"}
self.proxies = {"http":"http://309435365:[email protected]:16817"}
self.conn = pymongo.MongoClient("localhost",27017)
self.db = self.conn.Lianjia
self.myset = self.db.housePrice
def getPage(self,url):
res = requests.get(url,proxies=self.proxies,headers=self.headers,timeout=5)
res.encoding = "utf-8"
html = res.text
print("页面爬取成功,正在解析...")
self.parsePage(html)
def parsePage(self,html):
p = re.compile('(.*?).*?.*?(.*?)(.*?)',re.S)
r_list = p.findall(html)
# [("天通苑","480","万"),()..]
print("页面解析完成,正在存入数据库...")
self.writeTomongo(r_list)
def writeTomongo(self,r_list):
for r_tuple in r_list:
D = {"houseName":r_tuple[0].strip(),\
"totalPrice":float(r_tuple[1].strip())*10000}
self.myset.insert(D)
print("存入数据库成功")
def workOn(self):
while True:
c = input("爬取按y(q退出):")
if c.strip().lower() == "y":
url = self.baseurl + str(self.page) + "/"
self.getPage(url)
self.page += 1
else:
print("爬取结束,谢谢使用!")
break
if __name__ == "__main__":
spider = LianjiaSpider()
spider.workOn()
3、Web客户端验证(参数名:auth)
1、auth=("用户名","密码")(元组的方式)
auth=("tarenacode","code_2013")
2、案例 :09_Web客户端验证.py
代码:
'''09_Web客户端验证.py'''
import requests
import re
class NoteSpider:
def __init__(self):
self.headers = {"User-Agent":"Mozilla/5.0"}
self.url = "http://code.tarena.com.cn/"
self.proxies = {"http":"http://309435365:[email protected]:16817"}
# auth参数存储用户名和密码(必须为元组)
self.auth = ("tarenacode","code_2013")
def getParsePage(self):
res = requests.get(self.url,
proxies=self.proxies,
headers=self.headers,
auth=self.auth,
timeout=3)
res.encoding = "utf-8"
html = res.text
print(html)
p = re.compile('
4、SSL证书认证(参数名:verify)
数字证书认证中心
1、verify = True : 默认,进行SSL证书认证
2、verify = False: 不做认证
代码:
import requests
url = "https://www.12306.cn/mormhweb/"
headers = {"User-Agent":"MOzilla/5.0"}
res = requests.get(url,headers = headers,verify = False)
res.encoding = "utf-8"
print(res.text)
2、urllib.request中Handler处理器
1、定义
自定义的urlopen()方法,urlopen()方法是一个特殊的opener(模块已定义好),不支持代理等功能,通过Handler处理器对象来自定义opener对象
2、常用方法
1、build_opener(Handler处理器对象) :创建opener对象
2、opener.open(url,参数)
3、使用流程
1、创建相关的Handler处理器对象
http_handler = urllib.request.HTTPHandler()
2、创建自定义opener对象
opener = urllib.request.build_opener(http_handler)
3、利用opener对象打开url
req = urllib.request.Request(url,headers=headers)
res = opener.open(req)
4、Handler处理器分类
1、HTTPHandler() :没有任何特殊功能
2、ProxyHandler(普通代理)
代理: {"协议":"IP地址:端口号"}
3、ProxyBasicAuthHandler(密码管理器对象) :私密代理
4、HTTPBasicAuthHandler(密码管理器对象) : web客户端认证
5、密码管理器对象作用
1、私密代理
2、Web客户端认证
3、程序实现流程
1、创建密码管理器对象
pwdmg = urllib.request.HTTPPasswordMgrWithDefaultRealm()
2、把认证信息添加到密码管理器对象
pwdmg.add_password(None,webserver,user,passwd)
3、创建Handler处理器对象
1、私密代理
proxy = urllib.request.ProxyAuthBasicHandler(pwdmg)
2、Web客户端
webbasic = urllib.request.HTTPBasicAuthHandler(pwdmg)
安装:
1、Windows :安装selenium
Anaconda Prompt下执行 :
python -m pip install selenium
2、Ubuntu :安装Scrapy框架
#### 依赖库较多,以下为全部依赖库,有些已安装 ####
1、sudo apt-get install libssl-dev
sudo apt-get install libffi-dev
sudo apt-get install python3-dev
sudo apt-get install build-essential
sudo apt-get install libxml2
sudo apt-get install libxml2-dev
sudo apt-get install libxslt1-dev
sudo apt-get install zlib1g-dev
2、sudo pip3 install Scrapy
Day04****************************************************************
1、xpath工具(解析)
1、xpath
本来是在XML文档中查找信息的语言,同样适用于HTML文档的检索
2、xpath辅助工具
1、Chrome插件 :XPath Helper
1、打开 :Ctrl + Shift + X
2、关闭 :Ctrl + Shift + X
2、Firefox插件 :XPath checker
3、XPath表达式编辑工具 :XML quire
3、xpath匹配规则
1、匹配演示
1、查找bookstore下所有节点:/bookstore
2、查找所有的book节点://book
3、查找所有book下的title节点中,lang属性为"en"的节点
//book/title[@lang="en"]
4、查找bookstore下的第2个book节点下的title节点:
/bookstore/book[2]/title/text()
2、选取节点
/ : 从根节点开始选取
// : 从整个文档中查找节点
//price 、 /bookstore/book//price
@ : 选取某个节点的属性
//title[@lang="en"]
3、 @的使用
1、选取1个节点 : //title[@lang="en"]
2、选取N个节点 : //title[@lang]
3、选取节点的属性值 : //title/@lang
2、lxml库及xpath使用
1、lxml库 :HTML/XML解析库
1、安装
python -m pip install lxml
conda install lxml
2、使用流程
1、导模块
from lxml import etree
2、利用lxml库的etree模块创建解析对象
parseHtml = etree.HTML(html)
3、解析对象调用xpath工具定位节点信息
r_list = parseHtml.xpath('xpath表达式')
### 只要调用了xpath,结果一定是列表 ###
3、示例 :见01_xpath示例.py
4、如何获取节点对象的内容
节点对象.text
5、案例1 :抓取百度贴吧帖子里面所有的图片
1、目标 :抓取指定贴吧所有图片
2、思路
1、获取贴吧主页URL,下一页:找URL规律
2、获取1页中每个帖子的URL
3、对每个帖子URL发请求,获取帖子里图片URL
4、对图片URL发请求,以wb方式写入本地文件
3、步骤
1、获取贴吧主页URL
http://tieba.baidu.com/f? + 查询参数
2、找到页面中所有帖子的URL
src : 完整链接
href : 和主URL进行拼接
/p/5926064184 千玺:p/6242828073
http://tieba.baidu.com/p/5926064184
xpath匹配链接:
写法1: //div[@class="col2_right j_threadlist_li_right"]/div/div/a/@href
写法2(推荐): //div[@class="t_con cleafix"]/div/div/div/a/@href
(好像是错的)千玺://div[@class="d_post_content j_d_post_content clearfix"]
微博://div[@box-result clearfix hover]/a/@href
3、找每个帖子中图片URL
Xpath匹配:
//img[@class="BDE_Image"]/@src
千玺://ima[@class="left_img"]/@src
4、代码实现
6、案例2 :糗事百科(详情页)-xpath
1、目标 :用户昵称、段子内容、好笑数、评论数
2、步骤
1、找URL
https://www.qiushibaike.com/8hr/page/1/
2、xpath匹配
1、基准xpath://div[contains(@id,"qiushi_tag_")]
用户昵称: ./div/a/h2
段子内容: .//div[@class="content"]/span
好笑数量: .//i
评论数量: .//i
'''02_百度贴吧图片抓取案例.py'''
import requests
from lxml import etree
import time
class BaiduImageSpider:
def __init__(self):
self.headers = {"User-Agent":"Mozilla/5.0"}
self.baseurl = "http://tieba.baidu.com"
self.pageurl = "http://tieba.baidu.com/f?"
# 获取所有帖子URL列表
def getPageUrl(self,params):
res = requests.get(self.pageurl,params=params,headers=self.headers)
res.encoding = "utf-8"
html = res.text
# 构建解析对象
parseHtml = etree.HTML(html)
# 帖子链接列表
t_list = parseHtml.xpath('//div[@class="t_con cleafix"]/div/div/div/a/@href')
# t_list : ['/p/233432','/p/2039820',..]
print(t_list)
for t_link in t_list:
# 拼接帖子完整链接
t_link = self.baseurl + t_link
self.getImageUrl(t_link)
# 获取帖子中图片URL列表
def getImageUrl(self,t_link):
res = requests.get(t_link,headers=self.headers)
res.encoding = "utf-8"
html = res.text
# 构造解析对象
parseHtml = etree.HTML(html)
img_list = parseHtml.xpath('//img[@class="BDE_Image"]/@src')
print(img_list)
for img_link in img_list:
self.writeImage(img_link)
# 保存到本地
def writeImage(self,img_link):
# 获取图片的bytes
res = requests.get(img_link,headers=self.headers)
res.encoding = "utf-8"
html = res.content
# filename
filename = img_link[-12:]
with open(filename,"wb") as f:
f.write(html)
time.sleep(0.5)
print("%s下载成功" % filename)
# 主函数
def workOn(self):
name = input("请输入贴吧名:")
begin = int(input("请输入起始页:"))
end = int(input("请输入终止页:"))
for n in range(begin,end+1):
pn = (n-1)*50
params = {
"kw":name,
"pn":str(pn)
}
self.getPageUrl(params)
if __name__ == "__main__":
spider = BaiduImageSpider()
spider.workOn()
这个代码我爬取了千玺的图片,但其中有很多其他的图片,是这样的。
中间有一些其他的,我也不知道哪来的,在页面上也没显示。
爬取王俊凯的就没有这样,就全是图片
需要注意的就是抓取的代码需单独保存在一个文件夹里面,不然爬下来的图片会很凌乱。
#03_糗事百科(详情页)-xpath
import requests
from lxml import etree
import pymongo
class QuishiSpider:
def __init__(self):
self.url = "https://www.qiushibaike.com/8hr/page/1/"
self.headers = {"User-Agent":"Mozilla/5.0"}
self.conn = pymongo.MongoClient("localhost",27017)
self.db = self.conn.Baikedb
self.myset = self.db.baikeset
def getPage(self):
res = requests.get(self.url,headers = self.headers)
res.encoding = "utf-8"
html = res.text
self.parsePage(html)
def parsePage(self,html):
parseHtml = etree.HTML(html)
#基准xpath,匹配每个段子的列表
base_list = parseHtml.xpath('//div[contains(@id,"qiushi_tag_")]')
#遍历每个段子的节点对象(base)
for base in base_list:
#用户昵称
uername = base.xpath('./div/a/h2')
if len(username) == 0:
username = "匿名用户"
else:
username = username[0].text
#段子内容
content = base.xpath('.//div[@class="content"]/span')[0].text
#好笑数量
#[,]
laughNum = base.xpath('.//i')[0].text
#评论数量
pingNum = base.xpath('.//i')[1].text
#定义为字典,存入数据库
d = {
"username":username.strip(),
"content":content.strip(),
"laughNum":laughNum.strip(),
"pingNum":pingNum.strip()
}
self.myset.insert(d)
pirnt("存入数据库成功")
if __name__ =="__main__":
spider = QuishiSpider()
spider.getPage()
爬虫基础就这样学完了,虽然还有一些值得我无仔细思量的地方,但是时间不等人,只能边学后面的边复习前面的了,加油。