php抓取网页表格信息 Python | 爬爬爬:爬百度云,爬*敏*感*词*,爬爱奇艺
优采云 发布时间: 2022-06-17 16:36php抓取网页表格信息 Python | 爬爬爬:爬百度云,爬*敏*感*词*,爬爱奇艺
寻找并分析百度云的转存api
首先你得有一个百度云盘的账号,然后登录,用浏览器(这里用火狐浏览器做示范)打开一个分享链接。F12打开控制台进行抓包。手动进行转存操作:全选文件->保存到网盘->选择路径->确定。点击【确定】前建议先清空一下抓包记录,这样可以精确定位到转存的api,这就是我们中学时学到的【控制变量法】2333。
可以看到上图中抓到了一个带有 “transfer” 单词的 post 请求,这就是我们要找的转存(transfer)api 。接下来很关键,就是分析它的请求头和请求参数,以便用代码模拟。
点击它,再点击右边的【Cookies】就可以看到请求头里的 cookie 情况。
cookie分析
因为转存是登录后的操作,所以需要模拟登录状态,将与登录有关的 cookie 设置在请求头里。我们继续使用【控制变量法】,先将浏览器里关于百度的 cookie 全部删除(在右上角的设置里面,点击【隐私】,移除cookies。具体做法自己百度吧。)
然后登录,右上角进入浏览器设置->隐私->移除cookie,搜索 "bai" 观察 cookie 。这是所有跟百度相关的 cookie ,一个个删除,删一个刷新一次百度的页面,直到删除了 BDUSS ,刷新后登录退出了,所以得出结论,它就是与登录状态有关的 cookie 。
同理,删除掉 STOKEN 后,进行转存操作会提示重新登录。所以,这两个就是转存操作所必须带上的 cookie 。
弄清楚了 cookie 的情况,可以像下面这样构造请求头。
除了上面说到的两个 cookie ,其他的请求头参数可以参照手动转存时抓包的请求头。这两个 cookie 预留出来做参数的原因是 cookie 都是有生存周期的,过期了需要更新,不同的账号登录也有不同的 cookie 。
参数分析
接下来分析参数,点击【Cookies】右边的【Params】查看参数情况。如下:
上面的query string(也就是?后跟的参数)里,除了框起来的shareid、from、bdstoken需要我们填写以外,其他的都可以不变,模拟请求的时候直接抄下来。
前两个与分享的资源有关,bdstoken与登录的账号有关。下面的form data里的两个参数分别是资源在分享用户的网盘的所在目录和刚刚我们点击保存指定的目录。
所以,需要我们另外填写的参数为:shareid、from、bdstoken、filelist 和 path,bdstoken 可以手动转存抓包找到,path 根据你的需要自己定义,前提是你的网盘里有这个路径。其他三个需要从分享链接里爬取,这个将在后面的【爬取shareid、from、filelist,发送请求转存到网盘】部分中进行讲解。
搞清楚了参数的问题,可以像下面这样构造转存请求的 url 。
爬取shareid、from、filelist,发送请求转存到网盘
以上面这个资源链接为例(随时可能被河蟹,但是没关系,其他链接的结构也是一样的),我们先用浏览器手动访问,F12 打开控制台先分析一下源码,看看我们要的资源信息在什么地方。控制台有搜索功能,直接搜 “shareid”。
定位到4个shareid,前三个与该资源无关,是其他分享资源,最后一个定位到该 html 文件的最后一个标签块里。双击后可以看到格式化后的 js 代码,可以发现我们要的信息全都在里边。如下节选:
可以看到这两行
yunData.PATH 只指向了一个路径信息,完整的 filelist 可以从 yunData.FILEINFO 里提取,它是一个 json ,list 里的信息是Unicode编码的,所以在控制台看不到中文,用Python代码访问并获取输出一下就可以了。
直接用request请求会收获 404 错误,可能是需要构造请求头参数,不能直接请求,这里博主为了节省时间,直接用selenium的webdriver来get了两次,就收到了返回信息。第一次get没有任何 cookie ,但是baidu 会给你返回一个BAIDUID ,在第二次 get 就可以正常访问了。
yunData.FILEINFO 结构如下,你可以将它复制粘贴到里,可以看得更清晰。
清楚了这三个参数的位置,我们就可以用正则表达式进行提取了。代码如下:
爬取到了这三个参数,就可以调用之前的 transfer 方法进行转存了。
爬取*敏*感*词*上的帖子
我们想获取贴吧上帖子的标题。
解决方法为:在相应的网页的html代码中找到title出现的地方。然后提取正则表达式。
根据上面的截图:提取的正则表达式如下:
pattern=pile(r',re.S)
因此,得到帖子的标题的代码可以这么写。
#得到帖子的标题def getPageTitle(self,pageNum):content=self.getPageContent(pageNum)#得到网页的html代码pattern=pile(r',re.S)
title=re.search(pattern,content)
if title:
#print title.group(1).strip() 测试输出
return title.group(1).strip()
else:
printNone
同样的道理,我们可以得到获取帖子作者的代码如下:
#得到帖子的作者
def getPageAuthor(self,pageNum):
content=self.getPageContent(pageNum) #
pattern=re.compile(r'',re.S)
author=re.search(pattern,content) if author: print author.group(1).strip()#测试输出
return author.group(1).strip() else : print None<p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;" /></p>
同样的道理,可以得到任何我们想要的内容。比例:帖子的回复总数等。
下面是完整代码:
#encoding=utf-8#功能:抓取*敏*感*词*中帖子的内容import urllib2import urllibimport re#定义一个工具类来处理内容中的标签class Tool:
#去除img标签,7位长空格
removeImg=re.compile('| {7}|') #去除超链接标签
removeAddr=re.compile('|</a>') #把换行的标签换为\n
replaceLine=re.compile('|||') #将表格制表替换为\t
replaceTD=re.compile('') #把段落开头换为\n加空两格
replacePara=re.compile('') #将换行符或双换行符替换为\n
replaceBR=re.compile('
|
') #将其余标签删除
removeExtraTag=re.compile('') def replace(self,x):
x=re.sub(self.removeImg,"",x)
x=re.sub(self.removeAddr,"",x)
x=re.sub(self.replaceLine,"\n",x)
x=re.sub(self.replaceTD,"\t",x)
x=re.sub(self.replacePara,"\n ",x)
x=re.sub(self.replaceBR,"\n",x)
x=re.sub(self.removeExtraTag,"",x) return x.strip()#定义一个类class BaiduTieBa:
#初始化,传入地址,以及是否只看楼主的参数,floorTag:为1就是往文件中写入楼层分隔符
def __init__(self,url,seeLZ,floorTag):
self.url=url
self.seeLZ="?see_lz="+str(seeLZ)
self.tool=Tool() #全局的文件变量
self.file=None
#默认标题,如果没有获取到网页上帖子的标题,此将作为文件的名字
self.defultTitle="*敏*感*词*"
#是否往文件中写入楼与楼的分隔符
self.floorTag=floorTag #楼层序号
self.floor=1
#根据传入的页码来获取帖子的内容太
def getPageContent(self,pageNum):
url=self.url+self.seeLZ+"&pn="+str(pageNum)
user_agent="Mozilla/5.0 (Windows NT 6.1)"
headers={"User-Agent":user_agent} try:
request=urllib2.Request(url,headers=headers)
response=urllib2.urlopen(request)
content=response.read().decode("utf-8") #print content #测试输出
return content except urllib2.URLError,e: if hasattr(e,"reason"): print e.reason #得到帖子的标题
def getPageTitle(self,pageNum):
content=self.getPageContent(pageNum)
pattern=re.compile(r'(.*?)',re.S)
items=re.findall(pattern,content)
floor=1
contents=[] for item in items: #将每个楼层的内容进行去除标签处理,同时在前后加上换行符
tempContent="\n"+self.tool.replace(item)+"\n"
contents.append(tempContent.encode("utf-8")) #测试输出
#print floor,u"楼-------------------------------------------\n"
#print self.tool.replace(item)
#floor+=1
return contents #将内容写入文件中保存
def writedata2File(self,contents):
for item in contents: if self.floorTag=="1": #楼与楼之间的分隔符
floorLine=u"\n"+str(self.floor)+u"-------------------\n"
self.file.write(floorLine) print u"正在往文件中写入第"+str(self.floor)+u"楼的内容"
self.file.write(item)
self.floor+=1
#根据获取网页帖子的标题来在目录下建立一个同名的.txt文件
def newFileAccTitle(self,title):
if title is not None:
self.file=open(title+".txt","w+") else:
self.file=open(defultTitle+".txt","w+") #写一个抓取贴吧的启动程序
def start(self,pageNum):
#先获取html代码
content=self.getPageContent(pageNum) #第二步:开始解析,获取帖子的标题和作者
title=self.getPageTitle(pageNum) #根据title建立一个即将用于写入的文件
self.newFileAccTitle(title)
author=self.getPageAuthor(pageNum) #第三步:获取帖子各个楼层的内容
contents=self.getContent(pageNum) #第四步:开始写入文件中
try:
self.writedata2File(contents) except IOError,e: print "写入文件发生异常,原因"+e.message finally: print "写入文件完成!"#测试代码如下:#url=raw_input("raw_input:")url="http://www.tieba.baidu.com/p/4197307435"seeLZ=input("input see_lz:")
pageNum=input("input pageNum:")
floorTag=raw_input("input floorTag:")
baidutieba=BaiduTieBa(url,seeLZ,floorTag)#实例化一个对象baidutieba.start(pageNum)#content=baidutieba.getPageContent(pageNum)#调用函数#开始解析得到帖子标题#baidutieba.getPageTitle(1)#开始解析得到帖子的作者#baidutieba.getPageAuthor(1)#baidutieba.getPageTotalPageNum(1)#解析帖子中的内容#baidutieba.getContent(pageNum)</p>
自己动手敲敲代码,运行一下试试吧!
攻破爱奇艺 VIP 视频防线