网址:【数据挖掘】2019年最新python3 数据分析与数据爬虫实战
https://www.bilibili.com/video/av22571713/?p=26
第三周第二节课
1抓包分析实战
作业讲解(成功)
# -*- coding: utf-8 -*-
# coding=utf-8
import requests
import urllib.request
import re
keyname="科技"
key=urllib.request.quote(keyname)#编码 处理不了中文 所以处理一下
headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
opener=urllib.request.build_opener()
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
for i in range(1,2):
url="http://www.58pic.com/tupian/keji-0-0-"+str(i)+".html"
data=urllib.request.urlopen(url).read().decode("gbk")#decode解码
#fh=open("F:/file2.txt","w")
#fh.write(data)
#fh.close()
pat='class="card-title-new" ><a href="//(.*?)"'
imagelist=re.compile(pat).findall(data)
for j in range(0,len(imagelist)):
try:
thisimg=imagelist[j]
thisimgurl="http://"+thisimg
thisimgdata=urllib.request.urlopen(thisimgurl).read().decode("gbk")#decode解码
imgpat='<img src="//(.*?)" class="show-area-pic"'
bigimg=re.compile(imgpat).findall(thisimgdata)
bigimgurl="http://"+bigimg[0]
#file="D:/FHLAZ/Python37/test2019.2.10/img2/"+str(i)+str(j)+".jpg"
file="F:/img2/"+str(i)+str(j)+".jpg"
urllib.request.urlretrieve(bigimgurl,filename=file)
print("第"+str(i)+"页第"+str(j)+"个图片爬取成功")
except urllib.error.URLError as e:
if hasattr(e,"code"):#判断是都有状态吗
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
except Exception as e:
print(e)
成功了。
这个代码的整体思路是先去爬科技页面下图片的网址,然后打开这个网址获得图片的网址,然后爬取下来。
中间遇到了很多问题,比如说解码乱码了。
错误代码:data=urllib.request.urlopen(url).read().decode(“utf-8”)
UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0xb1 in position 0: invalid start byte
将这句话里面的utf-8改成了gbk。虽然原理不太懂。
也参考了一些文章,比如说:http://www.cnblogs.com/liuq/p/9849960.html
有很多人说的python3,python2的解决方法都没有用。最后是把utf-8改成了gbk格式解决了问题。
通过这个代码查看了网页的格式
# coding=utf-8
import requests
r = requests.get('http://www.******')
print(r.encoding) # gbk
print(r.apparent_encoding) # GB2312
通过这个代码把爬取下来的文件写入txt里面,对比发现,没有乱码。
url="http://www.58pic.com/tupian/keji-0-0-"+str(i)+".html"
data=urllib.request.urlopen(url).read().decode("gbk")#decode解码
fh=open("F:/file2.txt","w")
fh.write(data)
fh.close()
乱码的后续环节在应用中继续研究
抓包分析概述
抓包分析是将网络传输发送与接收的数据包进行抓取的操作,做爬虫时,数据并不一定就在HTML源码中,很可能隐藏在一些网址中,所以,我们要抓取某些数据,就需要进行抓包,分析出对应数据所隐藏在的网址,然后分析规律并爬取。
使用fiddler进行抓包分析(成功)
抓包工具有很多,Fiddler是其中一种,我们在爬虫项目中经常会使用Fiddler进行抓包。接下来通过实战为大家讲解如何使用Fiddler进行抓包分析。
首先下载了fiddler软件,我是通过这个网址下载的,https://pc.qq.com/detail/10/detail_3330.html, 然后基本上是默认安装,后来看视频说要用火狐浏览器,但是按照视频操作之后无法访问淘宝,最后看弹屏说现在的fiddler不需要设置其它了,我就直接用360浏览器打开淘宝网,任意打开一个商品:https://detail.tmall.com/item.htm?spm=a230r.1.14.110.352e7dc3go8AnB&id=591612488712&ns=1&abbucket=7,然后找他的评论语言和图
我打算找这句话:妈妈很喜欢
然后查找源代码 发现没有这句话 说明需要用到抓包分析
最开始没成功,乱码了,后来在syntaxview里面成功了 但是再次尝试的时候又失败了,上网查了乱码状态,是通过这个操作解决的:
打开注册表编辑器,找到HKCU\Software\Microsoft\Fiddler2\,在里面添加一个字符串值,名叫HeaderEncoding,值设置为默认编码。建议设成GB18030。然后要记得重启Fiddler才能生效。
具体步骤:
1、windows按钮+R
2、输入regedit +回车+是
3、HKEY_CURRENT_USER\Software\Microsoft\Fiddler2
4、右键新建,选字符串值 加上HeaderEncoding 然后值输入 GBK
好了,最后现在成功了。
抓取HTTPS数据包(没有做,但是360也可以使用)
Fiddler默认抓取HTTP的数据,抓不到HTTPS的数据,如果享用Fiddler抓HTTPS的数据,需要进行相应设置,具体可参考:https://ask.hellobi.com/blog/weiwei/5159
不知道实际上现在还需要不,我在火狐浏览器里面按照操作做过的,但是我现在用的是360浏览器,默认不需要吧,如果需要再重新操作一遍吧。
爬取腾讯视频的评论(成功)
接下来为大家讲解如何抓取腾讯视频的评论数据,这些评论数据是需要抓包分析才能够得到的,同时为大家讲解如何实现自动加载评论。
抓的网址是这个:https://v.qq.com/detail/0/0dfpyvfa7tp0ewe.html
查看源代码发现 评论不在原代码里面 所以需要抓包
clear可以清除很多网址,如图
选定一个js开头的网址,右键获取url:https://coral.qq.com/article/1266957829/comment?commentid=0&reqnum=10&tag=&callback=jQuery1124022771892025629548_1557407079041&_=1557407079042, 打开可以看到下图,也就是把response里面的内容展开显示了,
“content”:"\u9c7c\u8d8a\u6b64\u65f6\u6d77\uff0c\u82b1\u5f00\u5f7c\u5cb8\u5929\u3002"
u是一种编码,可以通过u""解码
再次遇到乱码问题,这次参考:https://blog.csdn.net/quiet_girl/article/details/50577828解决了
选定一个js开头的网址,右键获取url:http://video.coral.qq.com/filmreviewr/c/replycomment/0dfpyvfa7tp0ewe/6166554264058015735?&callback=jQuery111108960334196749054_1557407875717&g_tk=1509469071&logintype=11&open_openid=152CBFA75410E2C4B19CF1B62009113B&open_access_token=41B86AE53C04B5FDE9F7069F884D3A29&open_appid=101483052&code=0&reqnum=10&commentid=&_=1557407875718
“title”:"\u300a\u9752\u4e91\u5fd7\u300b\u4e2d\u5f20\u5c0f\u51e1\u7684\u611f\u60c5\u548c\u6027\u683c",
“abstract”:"\u770b\u4e86\u8bdb\u4ed9\u7684\u4e66\u597d\u591a\u5e74\u4e86\uff0c\u56e0\u4e3a\u9752\u4e91\u5fd7\u8981\u64ad\uff0c\u524d\u6bb5\u65f6\u95f4\u628a\u4e66\u53c8\u770b\u4e86\u4e00\u904d\u3002\u4e00\u76f4\u8bb0\u5f97\u4e66\u4e2d\u90a3\u4e2a\u6ca1\u6709\u591a\u5c11\u8bdd\uff0c\u4f46\u662f\u7ed9\u4eba\u5b89\u5168\u611f\u7684\u7537\u4eba\u8270\u96be\u7684\u6210\u957f\u7ecf\u5386\u3002\u5bf9\u4e8e\u5c0f\u5c0f\u51e1\u548c\u5927\u5c0f\u51e1\u6211\u90fd\u5f88\u6ee1\u610f\uff0c\u8bf4\u8bf4\u5230\u73b0\u5728\u4e3a\u6b62\u611f\u53d7\u5230\u7684\u5c0f\u51e1\u7684\u611f\u60c5\u548c\u6027\u683c\u5427\uff01\u611f\u60c5\u65b9\u9762\u5bf9\u5e08\u7236\u5e08\u5a18\uff0c\u662f\u656c\u754f\u7684\u3002\u5c31\u60f3\u4ed6\u5e08\u7236\u5f62\u5bb9\u7684\uff0c\u4e00\u89c1\u4e86\u4ed6\u5c31\u50cf\u8001\u9f20\u89c1\u4e86\u732b\u3002\u5c31\u597d\u50cf\u5b66\u4e60\u4e0d\u597d\u7684\u5b66\u751f\u89c1\u4e86\u8001\u5e08\uff0c\u63a5\u53d7\u8001\u5e08\u6279\u8bc4\u7684\u65f6\u5019\u4f1a\u6127\u759a\u81ea\u8d23\uff0c\u8001\u5b9e\u70b9\u7684\u4e00\u822c\u4e0d\u4f1a\u8fd8\u5634\uff0c\u53ea\u4f1a\u9ed8\u9ed8\u7684\u542c\u7740\u3002\u65f6\u95f4\u4e45\u4e86\u5c31\u66f4\u4e0d\u6562\u548c\u8001\u5e08\u4ea4\u6d41\u4e86\uff0c\u6210\u4e86\u95f7\u846b\u82a6\u3002\u770b\u5230\u5e08\u7236\u8bad\u5c0f\u51e1…"
“content”:"
\u770b\u4e86\u8bdb\u4ed9\u7684\u4e66\u597d\u591a\u5e74\u4e86\uff0c\u56e0\u4e3a\u9752\u4e91\u5fd7\u8981\u64ad\uff0c\u524d\u6bb5\u65f6\u95f4\u628a\u4e66\u53c8\u770b\u4e86\u4e00\u904d\u3002\u4e00\u76f4\u8bb0\u5f97\u4e66\u4e2d\u90a3\u4e2a\u6ca1\u6709\u591a\u5c11\u8bdd\uff0c\u4f46\u662f\u7ed9\u4eba\u5b89\u5168\u611f\u7684\u7537\u4eba\u8270\u96be\u7684\u6210\u957f\u7ecf\u5386\u3002
第二次点更多评论抓第二个评论,右键url为:
https://video.coral.qq.com/filmreviewr/c/upcomment/0dfpyvfa7tp0ewe?commentid=6165885358242861936&reqnum=3&callback=jQuery112405017607121457284_1557408985934&_=1557408985936
第三个url:https://video.coral.qq.com/filmreviewr/c/upcomment/0dfpyvfa7tp0ewe?commentid=6165793094371986503&reqnum=3&callback=jQuery112405017607121457284_1557408985934&=1557408985937
第四个url:https://video.coral.qq.com/filmreviewr/c/upcomment/0dfpyvfa7tp0ewe?commentid=6145719163485233240&reqnum=3&callback=jQuery112405017607121457284_1557408985934&=1557408985938
查找规律:
可以发现commentid的内容不一样,打开第二个url,查找第三个url的关键字6165793094371986503
import urllib.request
import re
import urllib.error
headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
opener=urllib.request.build_opener()
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
comid="6165885358242861936"
url="https://video.coral.qq.com/filmreviewr/c/upcomment/0dfpyvfa7tp0ewe?commentid="+comid+"&reqnum=3&callback=jQuery112405017607121457284_1557408985934&_=1557408985936"
for i in range(0,2):
data=urllib.request.urlopen(url).read().decode()#decode解码
patnext='"last":"(.*?)"'
nextid=re.compile(patnext).findall(data)[0]
patcom='"content":"(.*?)",'
comdata=re.compile(patcom).findall(data)
for j in range(0,len(comdata)):
print("---第"+str(i)+str(j)+"条评论内容是:")
print(eval('u"'+comdata[0]+'"'))
url="https://video.coral.qq.com/filmreviewr/c/upcomment/0dfpyvfa7tp0ewe?commentid="+nextid+"&reqnum=3&callback=jQuery112405017607121457284_1557408985934&_=1557408985936"
2微信爬虫实战(失败)
失败的我会后续回来,看看能否解决,更新。
什么是微信爬虫
所谓微信爬虫,即自动获取微信的相关文章信息的一种爬虫。微信对我们的限制是很多的,所以,我们需要采用一些手段解决这些限制,主要包括伪装浏览器,使用代理IP等方式。
微信爬虫编写实战
req和url的区别
我的理解是url是网址
req是请求
可以通过代码将url转化为请求
url="http://www.baidu.com/s?wd="+keywd#如果是https的话就不行,因为协议问题
req=urllib.request.Request(url)#要转化为请求
data=urllib.request.urlopen(req).read()
#http://weixin.sogou.com/
import re
import time
import urllib.error
import urllib.request
#自定义函数,功能为使用代理服务器爬一个网址
def use_proxy(proxy_addr,url):
#建立异常处理机制
try:
req=urllib.request.Request(url)
req.add_header("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
proxy=urllib.request.ProxyHandler({'http':proxy_addr})
opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
urllib.request.install_opener(opener)
data=urllib.request.urlopen(req).read()
return data
except urllib.request.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
#若为URLError异常,延时10s执行
time.sleep(10)
except Exception as e:
print("exception:"+str(e))
#若为Exception异常,延时1执行
time.sleep(1)
#设置关键词
key="python"
#设置代理服务器,该代理服务器可能失效,读者需要换成新的代理服务器
proxy="127.0.0.1:8888"
#爬多少页
for i in range(0,10):
key=urllib.request.quote(key)
thispageurl="https://weixin.sogou.com/weixin?type=2&query="+key+"&page="+str(i)
thispagedata=use_proxy(proxy,thispageurl)
print(len(str(thispagedata)))
pat1='<a href="(.*?)"'
rs1=re.compile(pat1,re.S).findall(str(thispagedata))
if(len(rs1)==0):
print("此次("+str(i)+"页)没成功")
continue
for j in range(0,len(rs1)):
thisurl=rs1[j]
thisurl=thisurl.replace("amp;","")
file="F:/result/第"+str(i)+"页第"+str(j)+"篇文章"
thisdata=use_proxy(proxy,thisurl)
try:
fh=open(file,"wb")
fh.write(thisdata)
fh.close()
print("第"+str(i)+"页第"+str(j)+"篇文章成功")
except Exception as e:
print(e)
print("第"+str(i)+"页第"+str(j)+"篇文章失败")
代理ip被封了 而且url无法直接获取页面,需要验证码,所以目前失败了
查看本地ip和端口的方法:如何查看本机ip地址和端口 查看本地ip地址和端口方法
3多线程爬虫实战
什么是多线程爬虫?
所谓多线程,即程序中某些程序段并行执行,合理地设置多线程,可以让爬虫的效率更高
普通的糗事百科段子爬虫(成功)
import re
import urllib.error
import urllib.request
#headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36")
headers = {'User-Agent': 'User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
opener=urllib.request.build_opener()
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
for i in range(1,2):
url="https://www.qiushibaike.com/8hr/page/"+str(i)
pagedata=urllib.request.urlopen(url).read().decode()
pat='src="(.*?)"'
datalist=re.compile(pat,re.S).findall(str(pagedata))
for j in range(0,len(datalist)):
print("第"+str(i)+"页第"+str(i)+"个段子内容是:")
print(datalist[j])
报错了
运行时报错:
http.client.RemoteDisconnected: Remote end closed connection without response
原因:服务器限制了部分User-Agent的访问。
参考解决方法:https://blog.csdn.net/u010883226/article/details/80183366
然而未解决
在后续挣扎了很久,我都想单独开个糗事百科爬取失败史了,现在回过头来在这里整理吧。先说需要的困难和我尝试解决过程。
失败 and 找解决方案历史
这个查找了网站,是ua浏览器代理有问题,但是我调整了ua也没有成功。
user-agent:http://www.manongjc.com/article/69909.html
参考链接:https://blog.csdn.net/weixin_41931602/article/details/80679623
我考虑了user-agent的问题,但是改了user-agent也不行。
考虑了ip的问题,但是改了ip也不行。
?我真的不行了,有大神来帮忙看下吗?
调整ip代码然而没用的代码(也放上去吧,可以忽略,主要是调上面的代码)
import re
import urllib.error
import urllib.request
def use_proxy(url,proxy_addr):
headers = ('User-Agent','User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36')
proxy=urllib.request.ProxyHandler({"http":proxy_addr})#地址:端口
opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
data=urllib.request.urlopen(url).read().decode("utf-8","ignore")
return data
proxy_addr="121.40.203.107:80"#多个代理ip:roxy_addr=["120.40.253.74:9999",""]
for i in range(1,2):
url="https://www.qiushibaike.com/8hr/page/"+str(i)
pagedata=use_proxy(url,proxy_addr)
pat='src="(.*?)"'
datalist=re.compile(pat,re.S).findall(str(pagedata))
for j in range(0,len(datalist)):
print("第"+str(i)+"页第"+str(i)+"个段子内容是:")
print(datalist[j])
正确解决方案
我把url转换为req请求,添加了浏览器代理req=urllib.request.Request(url, headers=headers)
,就成功了.
但是很奇怪,opener不是已经全局了,urllib.request.install_opener() 将自定义的 opener 对象 定义为 全局opener,表示之后凡是调用urlopen,都将使用这个opener来打开。所以说我这里的opener添加浏览器代理是失败了。
如果大神知道上面的代码我哪里错了,求解释?。
import re
import urllib.error
import urllib.request
#user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = {'User-Agent':user_agent}
opener=urllib.request.build_opener()
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
for i in range(1,2):
url="https://www.qiushibaike.com/text/page/"+str(i)
req=urllib.request.Request(url, headers=headers)
pagedata=urllib.request.urlopen(req).read().decode()
pat='src="(.*?)"'
datalist=re.compile(pat,re.S).findall(str(pagedata))
for j in range(0,len(datalist)):
print("第"+str(i)+"页第"+str(j)+"个段子链接是:")
print(datalist[j])
爬取内容的代码:
import re
import urllib.error
import urllib.request
headers={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
opener=urllib.request.build_opener()
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
for i in range(1,2):
url="https://www.qiushibaike.com/text/page/"+str(i)
req=urllib.request.Request(url, headers=headers)
pagedata=urllib.request.urlopen(req).read().decode()
pat='<div class="content">.*?<span>(.*?)</span>'
datalist=re.compile(pat,re.S).findall(str(pagedata))
for j in range(0,len(datalist)):
print("第"+str(i)+"页第"+str(j)+"个段子内容是:")
print(datalist[j])
提取一页是ok的,但是提取多页出现了一个问题
也就是说错误提示是:UnicodeEncodeError: ‘UCS-2’ codec can’t encode characters in position 114-114: Non-BMP character not supported in Tk。
我的参考解决方案是:https://blog.csdn.net/qq_16272049/article/details/79492020
这个错误产生原因是因为包含特殊字符,代码如下
import sys
non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)
name=name.translate(non_bmp_map)
其中name就是包含特殊字符 这样处理后就不会报错了
修改成功代码:
import sys
non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)
import re
import urllib.error
import urllib.request
headers={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
opener=urllib.request.build_opener()
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
for i in range(1,20):
url="https://www.qiushibaike.com/text/page/"+str(i)
req=urllib.request.Request(url, headers=headers)
pagedata=urllib.request.urlopen(req).read().decode("utf-8","ignore")
pat='<div class="content">.*?<span>(.*?)</span>'
datalist=re.compile(pat,re.S).findall(str(pagedata))
for j in range(0,len(datalist)):
print("第"+str(i)+"页第"+str(j)+"个段子内容是:")
datalist[j]=datalist[j].translate(non_bmp_map)
print(datalist[j])
多线程糗事百科段子爬虫(成功)
import threading
class A(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(0,10):
print("我是线程A")
class B(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(0,10):
print("我是线程B")
t1=A()
t1.start()
t2=B()
t2.start()
多线程效果图:
import sys
non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)
import re
import threading
import urllib.error
import urllib.request
#headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36")
headers = {'User-Agent': 'User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
opener=urllib.request.build_opener()
opener.addHeaders=[headers]
urllib.request.install_opener(opener)
class One(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(0,36,2):
url="https://www.qiushibaike.com/text/page/"+str(i)
req=urllib.request.Request(url, headers=headers)
pagedata=urllib.request.urlopen(req).read().decode("utf-8","ignore")
pat='<div class="content">.*?<span>(.*?)</span>'
datalist=re.compile(pat,re.S).findall(str(pagedata))
for j in range(0,len(datalist)):
print("第"+str(i)+"页第"+str(j)+"个段子内容是:")
datalist[j]=datalist[j].translate(non_bmp_map)
print(datalist[j])
class Two(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(1,36,1):
url="https://www.qiushibaike.com/text/page/"+str(i)
req=urllib.request.Request(url, headers=headers)
pagedata=urllib.request.urlopen(req).read().decode("utf-8","ignore")
pat='<div class="content">.*?<span>(.*?)</span>'
datalist=re.compile(pat,re.S).findall(str(pagedata))
for j in range(0,len(datalist)):
print("第"+str(i)+"页第"+str(j)+"个段子内容是:")
datalist[j]=datalist[j].translate(non_bmp_map)
print(datalist[j])
t1=One()#实例化
t1.start()#开了
t2=Two()
t2.start()
最好还是加异常处理。在内部的for循环以及外部的for循环