Python爬⾍笔记(四)——动态页⾯的处理(上篇)
什么是动态页⾯
我们知道js可以操纵DOM,可以请求后台,因此我们最终看到的html页⾯可能是js执⾏的结果,如果我们单纯⽤爬⾍获取动态页⾯的html,看到的可能就是⼀堆js
动态页⾯的处理
我⾃⼰总结了两种⽅式,1、获取后台接⼝,2、通过selenium+chromdriver,这篇博客先介绍第⼀种,这两种⽅式各有优劣
⽅式⼀:
动态页⾯有⼀个特点,它所需要的数据需要⾃⼰去请求后台,不是写死在html中的,因此只要到这个后台接⼝即可,采⽤这种⽅式,优点是快,缺点是解析难度⽐较⼤,需要解析js或是抓包分析获得后台接⼝
⽅式⼆:
基本上可以为所欲为,因为本⾝就是模拟浏览器的⾏为,它可以⾃动解析js,⽣成最终的html页⾯,因为需要解析js,因此爬取速度较慢,解析js会占⽤较多的cpu计算资源,由于⽐较吃硬件,所以并发能⼒⽐较弱
下⾯以爬取⾖瓣top 250的电影为例⼦,讲解第⼀种⽅式,之所以选择⾖瓣,是因为⾖瓣top250的后台接⼝⼏乎就暴露在我们⾯前,由于是练习,所以步骤⽐较繁琐:
获取后台接⼝
点击加载更多,⼀定会发送数据给后台,只需要捕获请求即可,不需要去看冗长的js代码(并且js代码可能进⾏了混淆,导致可读性极差),使⽤chrome开发者⼯具等抓包⼯具抓取请求路径如下:
返回数据格式解析
该请求返回json数据,观察请求参数,page_limit应该和返回的json条⽬有关,返回的json格式如下:
{
"subjects": [
{
"rate": "9.0",
"cover_x": 3375,
"title": "少年派的奇幻漂流",
"url": "https:\/\/movie.douban\/subject\/1929463\/",
"playable": true,
"cover": "img3.doubanio\/view\/photo\/s_ratio_poster\/public\/p1784592701.webp",
"id": "1929463",哪些bd收费培训比较好
"cover_y": 5000,
"is_new": false
}
]
}
这⾥单纯解析json格式,就没贴太多返回数据
可以使⽤python的json模块解析json,使⽤的函数如下:
#json字符串中{}内部的数据会解析成字典,[]会解析成列表
json.loads(jsonString)
数据存储⽅式
将爬取的数据存储在excel中,使⽤python中的xlwt,使⽤的函数如下:
#相当于创建⼀个excel
Workbook(encoding='utf-8')
#向excel中添加名为movie_info的页
add_sheet('movie_info')
#向页的某⾏、某列写⼊某个数据,这个函数参数不⽌这么多,详情请参照⽂档
write(row,colunm,data)
url管理
我们需要有⼀个url的管理者,若因异常导致重新爬取,便不必在对处理过的url进⾏处理,考虑到需要永久记录url的状态,我们使⽤数据库,我将数据库的管理者⾓⾊封装了⼀下,由于每次爬取任务的表结构不⼀样,因此实例化时需要⾃⼰指定sql语句、sql参数、表名等数据:
tor.pooling
tion
class db_manager:
#创建数据库连接池
def __init__(self,database,user,password,host,
select_url_sql,
update_status_downloads_sql,
update_status_finish_sql,
insert_db
):
self.select_url_sql=select_url_sql
self.update_status_downloads_sql=update_status_downloads_sql
self.update_status_downloads_sql=update_status_downloads_sql
self.update_status_finish_sql=update_status_finish_sql
self.insert_db=insert_db
try:
dbconfig = {
"user":      user,
"password":  password,
"host":      host,
"port":      3306,
"database":  database,
"charset":    "utf8"
}
print(arg)
#获取未爬取的url,将状态设置为download 记得commit
def getUrl(self):
_connection()
cursor=con.cursor()
try:
result=cursor.fetchone()
if result==None:
return None
sql=self.update_status_downloads_sql % result[0]
conmit()
except Exception as Arg:
print(Arg)python请求并解析json数据
return None
finally:
if con:
小舍得在线免费观看con.close()
if cursor:
cursor.close()
return result
#插⼊url数据,刚开始爬取时,获取img标签的url
def inserturl(self,para):
delphi手册_connection()
curson=con.cursor()
try:
conmit()
except Exception as Arg:
print(Arg)
finally:
if con:
con.close()
if curson:
curson.close()
#爬取完毕后,将状态置为finish
def finishCrawle(self,index):
_connection()
cursor=con.cursor()
try:
sql=self.update_status_finish_sql%index
conmit()
except Exception as Arg:
print(Arg)
print(Arg)
finally:
if con:
con.close()
if cursor:
cursor.close()
#出现异常后,将当前url的status置为new
def setStatusToNew(self,index):
_connection()
cursor=con.cursor()
try:
sql=self.set_status_to_new%index
conmit()
except Exception as Arg:
print(Arg)
finally:
if con:
con.close()
if cursor:
cursor.close()
页⾯分析
1、影⽚类型在标签<span property="v:genre"><span/>标签内
2、评分的html标签也具有⼀定的特点,其class="ll rating_num"
3、影⽚名字的html标签也具有⼀定特点
⼤多数情况下,⽹页制作⼈员都会做出⼀个前端模板出来,然后通过js等⼿段进⾏填值,因此,上述情况应该在⾖瓣的⼤多数影⽚介绍的页⾯有效
编辑代码
from urllib import request
from urllib import parse
import json
from dbmanager_template import db_manager
from lxml import etree
from xlwt import Workbook
import time
#xpath使⽤text属性获得标签值
def getMovieUrl():
temp='⾖瓣⾼分'
temp=parse.quote(temp)
req=request.Request('movie.douban/j/search_subjects?type=movie&tag='+temp+'&sort=rank&page_limit=250&page_start=0')
jsonString=request.urlopen(req).read().lower().decode("utf-8")
json_dict=json.loads(jsonString)
for index in range(0,len(json_dict['subjects'])):
url=json_dict['subjects'][index]['url'].replace('\\','')
dbmanager.inserturl((url))
def getMovie_info(url,row):
req=request.Request(url)
response=request.urlopen(req)
html_ad().lower().decode('utf-8')
html_parse=etree.HTML(html_page)
try:
type_list=html_parse.xpath('//span[@property="v:genre"]')
comment=html_parse.xpath('//strong[@class="ll rating_num"]')[0].text
title=html_parse.xpath('//span[@property="v:itemreviewed"]')[0].text
TypeString=type_list[0].text
for index in range(1,len(type_list)):
TypeString=TypeString+' '+type_list[index].text
print(title+' '+comment+' '+TypeString)
movie_info.write(row,0,title)
movie_info.write(row,1,comment)
movie_info.write(row,2,TypeString)
return 1
except Exception as arg:
print(arg)
if 'IP' in html_page:
print("IP被禁")
ps简易网页制作步骤return -1
else:
selected 代购print(url+":元素不存在")

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。