动态网页抓取(动态网页信息的爬取(一)_博客_)
优采云 发布时间: 2021-11-26 16:17动态网页抓取(动态网页信息的爬取(一)_博客_)
第一个博客从爬虫开始。虽然之前学过爬虫,但还是花了很长时间才重新上手。今天就来说说爬取动态网页信息。
先介绍一下抓取网页信息的基本思路:1.使用爬虫请求网页,获取网页源码2.分析源码,在源码中找到自己想要的信息;3.如果还有url地址,再次请求,重复步骤1和2。
找到我们想要的信息的url,有些url并不是我们想要的信息的真实url。查看源代码时,找不到所需的数据。这是因为这部分信息是动态获取的。下面以游牧之星今日推荐为例,获取信息类别、信息标题、信息介绍、发布时间、阅读数、评论数、图片路径等路径。网址=''
单页信息获取
网页如下
查看网页的源代码,在源代码中找到你需要的所有信息:
发现需要的信息在代码块中,但是评论数中没有值,说明动态获取评论数,找到了评论数的真实URL。
查看网页在网络中的情况,获得评论数的真实联系
js代码是
所述joincount要获得的评论的数量,而id是评论的数量以%2C1120919%2C1120764%2C1120676%2C1120483%2C1120737%2C1120383%2C1120344%2C1120301%2C1120184%2C1118361%2C1100332%2C1054392&_ = 65实际网址=”
现在的目的是获取id,id可以从源码中的data-sid属性中获取。
找到要获取的信息后,就是请求网页,解析代码。下面使用lxml进行解析,代码如下:
from lxml import etree
import requests
#获取单页的信息
def one_page_info():
url='https://www.gamersky.com/news/'
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'}
r=requests.get(url,headers=headers)
r_text=r.content.decode('utf-8')
html=etree.HTML(r_text) #解析源代码
#所有信息都在div,属性为Mid2L_con block的li标签中,获取所有li标签
all_li=html.xpath('//div[@class="Mid2L_con block"]/ul[@class="pictxt contentpaging"]/li')
all_inf=[]
#遍历li标签,获取每一个li标签中的信息
for one_li in all_li:
one_type=one_li.xpath('./div[1]/a[1]/text()')[0]#资讯类型
one_name=one_li.xpath('./div[1]/a[2]/text()')[0]#资讯名
one_info=one_li.xpath('string(./div[3]/div[1]/text())')
one_info=str(one_info).replace('\n','')#资讯信息,其中有些信息换行了,将换行符替换
one_time=one_li.xpath('./div[3]/div[2]/div[1]/text()')[0]#发布时间
one_read=one_li.xpath('./div[3]/div[2]/div[2]/text()')[0]#阅读数量
one_id=one_li.xpath('./div[3]/div[2]/div[3]/@data-sid')[0]#获取id
comment_url='https://cm.gamersky.com/commentapi/count?callback=jQuery183006329225718227227_1541342483946&topic_source_id='+one_id
#获取评论数
r_comment=requests.get(comment_url,headers=headers)
r_text=r_comment.text
one_comment=json.loads(r_text[42:-2])['result'][one_id]['joinCount']
one_img=one_li.xpath('./div[2]/a[1]/img/@src')[0]
all_inf.append({"type":one_type,"title":one_name,"info":one_info,"time":one_time,"visited":one_read,"comment":one_comment,"img":one_img})
return all_inf
#保存文件
def save_to_file(all_info):
with open("D:/gamersky.txt",'a',encoding='utf-8') as file:
for o in all_info:
file.write("%s::%s::%s::%s::%s::%s::%s\n"%(o['type'],o['title'],o['time'],o['visited'],o['comment'],o['img'],o['info']))
运行代码后,得到的信息如下:
在下方抓取多页信息
翻页信息获取
步骤还是和单页一样。当我们翻页的时候,发现网址没有变
并且查看源码,发现信息还在第一页,所以当有多个页面时,也是动态获取的。检查网络以找到该信息的真实链接。
查看这里的预览,找到信息的真实链接,下一步就是获取链接中的参数并拼接链接。
对比两个页面的链接,发现只有页面参数和两个页面链接末尾的数字不同,末尾的数字是时间参数。
因此,2页后的真正链接是 url='"{"type"%3A"updatenodelabel"%2C"isCache"%3Atrue%2C"cacheTime"%3A60%2C"nodeId"%3A"11007"%2C"isNodeId "%3A"true"%2C"page"%3A"+page+"}&_="+now_time'
替换 page=1 也是适用的。因此,上面是每个页面所需信息的通用链接(实际上,在翻页时,这里的li标签替换了源代码中的li标签)。
下一步就是请求每个页面的网页,获取每个页面的li标签,然后像单个页面一样获取。
代码:
#爬取多页动态网页,找出url之间的规则,传递所要爬取的页
def more_page_info(page):
now_time=str(time.time()).replace('.','')[0:13]
#每页想要获取信息的url
page_url="https://db2.gamersky.com/LabelJsonpAjax.aspx?callback=jQuery18308577910192677702_1541300651736&jsondata=%7B%22type%22%3A%22updatenodelabel%22%2C%22isCache%22%3Atrue%2C%22cacheTime%22%3A60%2C%22nodeId%22%3A%2211007%22%2C%22isNodeId%22%3A%22true%22%2C%22page%22%3A"+str(page)+"%7D&_="+now_time
headers={
"referer": "https://www.gamersky.com/news/",
"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"
}
r=requests.get(page_url,headers=headers)
html=json.loads(r.text[41:-2])['body']#将json字符串转换为字典
r_text=etree.HTML(html)
all_li=r_text.xpath('//li')#获取所有的li标签
all_inf=[]
for one_li in all_li:
one_type=one_li.xpath('./div[1]/a[1]/text()')[0]
one_name=one_li.xpath('./div[1]/a[2]/text()')[0]
one_info=one_li.xpath('string(./div[3]/div[1]/text())')
one_info=str(one_info).replace('\n','')
one_time=one_li.xpath('./div[3]/div[2]/div[1]/text()')[0]
one_read=one_li.xpath('./div[3]/div[2]/div[2]/text()')[0]
one_id=one_li.xpath('./div[3]/div[2]/div[3]/@data-sid')[0]
comment_url='https://cm.gamersky.com/commentapi/count?callback=jQuery183006329225718227227_1541342483946&topic_source_id='+one_id
#获取评论数
r_comment=requests.get(comment_url,headers=headers)
r_text=r_comment.text
one_comment=json.loads(r_text[42:-2])['result'][one_id]['joinCount']
one_img=one_li.xpath('./div[2]/a[1]/img/@src')[0]
all_inf.append({"type":one_type,"title":one_name,"info":one_info,"time":one_time,"visited":one_read,"comment":one_comment,"img":one_img})
return all_inf
def save_to_file(all_info):
with open("D:/gamersky.txt",'a',encoding='utf-8') as file:
for o in all_info:
file.write("%s::%s::%s::%s::%s::%s::%s\n"%(o['type'],o['title'],o['time'],o['visited'],o['comment'],o['img'],o['info']))
获取前3页信息
for page in range(1,4):
info=more_page_info(page)
save_to_file(info)
print('第%d页下载完成'%page)
综上所述,这取决于需要的信息是静态加载还是动态加载。判断是否是动态网页的简单方法就是看源码中是否可以找到你要获取的信息。动态网页的关键是找到所需信息的真实URL,比较每个页面的URL,找出规则并传递参数,如果参数是从其他动态URL中获取的,则找到参数信息的URL ,然后按个人信息获取。