ajax抓取网页内容(【投稿】本文中爬虫常用的库,用之前需要先下载好)
优采云 发布时间: 2021-12-13 05:02ajax抓取网页内容(【投稿】本文中爬虫常用的库,用之前需要先下载好)
本文是读者提交的第二篇文章。如果你想投稿,可以后台联系我。作者:parkson知乎:喜欢的可以关注,点击原文直接阅读。
本文的一般路线
首先列出一些python中爬虫常用的库。您需要先下载它们,然后才能使用它们。本文假设您已经安装了相应的库。
下载库:
0、Urllib 库
1、requests 在发出请求时使用
2、将使用selenium自动化
解析库:
3、正则匹配重新解析网页
4、用于Xpath的lxml第三方库
5、beautifulSoup 解析网页
6、pyquery 网页解析库类似于beautifulSoup
数据库操作库:
7、pymysql 操作mysql数据
8、pymongo 操作MongoDB数据库
9、redis 非关系型数据库
10、jupyter 在线笔记本
一、 Ajax的简单理解
1、AJAX是一种技术,一种创建快速动态网页的技术;不是一种新的编程语言,而是一种使用现有标准的新方法。
2、AJAX=Asynchronous JavaScript and XML(异步 JavaScript 和 XML)
3、AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下更新网页的某个部分。如果需要更新传统网页的内容(不使用 AJAX),则必须重新加载整个网页。
4、 Ajax 技术的核心是 XMLHttpRequest 对象(简称 XHR,即 AJAX 创建一个 XMLHttpRequest 对象并向服务器发送请求),它可以使用 XHR 对象从服务器获取数据,然后通过DOM Presentation将数据插入页面(AJAX加载的数据由浏览器渲染显示)。虽然名称中收录XML,但Ajax通信与数据格式无关(它是网页制作中的一种方法和技术),因此我们的数据格式可以是XML或JSON等格式。
二、 爬行AJAX动态加载网页案例
爬虫,简单的说就是自动从网上下载你感兴趣的信息。一般分为下载和解析两个步骤。
Ajax一般返回json格式的数据,直接用requests来post或获取(下载)ajax地址,返回json格式的数据,解析json数据得到你想要的信息(分析)。
如果我们使用AJAX加载的动态网页,我们如何抓取动态加载的内容?一般有两种方法:
方法一、通过selenium模拟浏览器爬行
方法二、通过浏览器review元素解析地址
case 一、URL保持不变,tab中第二个请求的URL按照一定的规则变化
以豆瓣电影为例:#/?sort=T&range=0,10&tags=%E5%8A%B1%E5%BF%97,点击加载更多刷新页面。
方法一、通过selenium模拟浏览器爬行,Beautiful Soup解析网页
这里有两种请求方式,设置一定的点击次数,不断点击加载更多
##设置一定的点击次数
from bs4 import BeautifulSoup
from selenium import webdriver
import time
import re
browser = webdriver.Chrome()###版本 68.0.3440.106(正式版本) (64 位)
browser.get('https://movie.douban.com/tag/#/?sort=T&range=0,10&tags=')
browser.implicitly_wait(3)##浏览器解释JS脚本是需要时间的,但实际上这个时间并不好确定,如果我们手动设定时间间隔的话,设置多了浪费时间,设置少了又会丢失数据
##implictly_wait函数则完美解决了这个问题,给他一个时间参数,它会只能等待,当js完全解释完毕就会自动执行下一步。
time.sleep(3)
browser.find_element_by_xpath('//*[@id="app"]/div/div[1]/div[1]/ul[4]/li[6]/span').click()###自动选择励志电影类型
i = 0
for i in range(5):##这里设置点击5次“加载更多”
browser.find_element_by_link_text("加载更多").click()
time.sleep(5)###如果网页没有完全加载,会出现点击错误,会点击到某个电影页面,所以加了一个睡眠时间。
##browswe.page_source是点击5次后的源码,用Beautiful Soup解析源码
soup = BeautifulSoup(browser.page_source, 'html.parser')
items = soup.find('div', class_=re.compile('list-wp'))
for item in items.find_all('a'):
Title = item.find('span', class_='title').text
Rate = item.find('span', class_='rate').text
Link = item.find('span',class_='pic').find('img').get('src')
print(Title,Rate,Link)
------------------------------------------------------------------------------------------------
###一直不断点击,直到加载完全
from bs4 import BeautifulSoup
from selenium import webdriver
import time
import re
browser = webdriver.Chrome()###版本 68.0.3440.106(正式版本) (64 位)
browser.get('https://movie.douban.com/tag/#/?sort=T&range=0,10&tags=')
browser.implicitly_wait(3)
time.sleep(3)
browser.find_element_by_xpath('//*[@id="app"]/div/div[1]/div[1]/ul[4]/li[6]/span').click()###自动选择励志电影类型
soup = BeautifulSoup(browser.page_source, 'html.parser')
while len(soup.select('.more'))>0:##soup.select(),返回类型是 list,判断只要长度大于0,就会一直不断点击。
browser.find_element_by_link_text("加载更多").click()
time.sleep(5)###如果网页没有完全加载,会出现点击错误,会点击到某个电影页面,所以加了一个睡眠时间。
soup = BeautifulSoup(browser.page_source, 'html.parser')
##将 加载更多 全部点击完成后,用Beautiful Soup解析网页源代码
items = soup.find('div', class_=re.compile('list-wp'))
for item in items.find_all('a'):
Title = item.find('span', class_='title').text
Rate = item.find('span', class_='rate').text
Link = item.find('span', class_='pic').find('img').get('src')
print(Title, Rate, Link)
方法二、直接根据tab中的URL规则构造第二个请求的URL
该网页通过 ajax 加载,一次显示 20 部电影。
点击加载更多
在Network选项卡中可以发现多了一个new_search,就是点击加载更多后需要重新加载的页面。对比几个new_searches,你会发现Request URL的结尾是start=i,i总是20的倍数,这样就可以直接写一个循环爬取多页电影信息了。
import requests
from requests.exceptions import RequestException
import time
import csv
import json
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
def get_one_page(url):
try:
response = requests.get(url,headers=headers)
if response.status_code == 200:
return response.json()##将返回的json数据转换为python可读的字典数据,.json是requests库自带的函数。
return None
except RequestException:
print("抓取失败")
def parse_one_page(d):
try:
datum = d['data']
for data in datum:
yield{
'Title':data['title'],
'Director':data['directors'],
'Actors':data['casts'],
'Rate':data['rate'],
'Link':data['url']
}
if data['Title','Director','Actors','Rate','Link'] == None:
return None
except Exception:
return None
def main():
for i in range(10):###这里就抓取10个网页,如果需求更多数据,将将数字改更大些即可。
url = 'https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=%E5%8A%B1%E5%BF%97&start={}'.format(i*20)
d = get_one_page(url)
print('第{}页抓取完毕'.format(i+1))
for item in parse_one_page(d):
print(item)
##将输出字典依次写入csv文件中
with open('Movie.csv', 'a', newline='',encoding='utf-8') as f: # file_path 是 csv 文件存储的路径,默认路径
fieldnames = ['Title', 'Director', 'Actors', 'Rate', 'Link']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for item in parse_one_page(d):
writer.writerow(item)
if __name__=='__main__':
main()
case 二、URL不变,tab中第二个请求的URL不规则
以CSDN网站为例,抓取CSDN首页文章列表:CSDN-专业IT技术社区 当CSDN-专业IT技术社区下拉时URL保持不变,第二次请求的URL标签中不规则,网页下拉刷新。
方法一、通过selenium模拟浏览器爬行,用正则表达式解析网页
from selenium import webdriver
import re
import time
browser = webdriver.Chrome()
browser.get('https://www.csdn.net/')
browser.implicitly_wait(10)
i = 0
for i in range(5):###设置下拉5次,如果想获取更多信息,增加下拉次数即可
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')##下拉,execute_script可以将进度条下拉到最底部
time.sleep(5)##睡眠一下,防止网络延迟,卡顿等
data = []
pattern = re.compile('.*?(.*?)</a>.*?(.*?)</a>'
'.*?(.*?).*?',re.S)
items = re.findall(pattern,browser.page_source)##这里网页源代码为下拉5次后的代码
for item in items:
data.append({
'Title':item[0].strip(),
'Author' : item[1].strip(),
'ReadNum' : item[2] + item[3]
})
print(data)
方法二、通过浏览器review元素解析真实地址
import requests
headers = {'cookie':'uuid_tt_dd=3844871280714138949_20171108; kd_user_id=e61e2f88-9c4f-4cf7-88c7-68213cac17f7; UN=qq_40963426; BT=1521452212412; Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=1788*1*PC_VC; smidV2=20180626144357b069d2909d23ff73c3bc90ce183c8c57003acfcec7f57dd70; __utma=17226283.14643699.1533350144.1533350144.1534431588.2; __utmz=17226283.1533350144.1.1.utmcsr=zhuanlan.zhihu.com|utmccn=(referral)|utmcmd=referral|utmcct=/p/39165199/edit; TY_SESSION_ID=f49bdedd-c1d4-4f86-b254-22ab2e8f02f6; ViewMode=contents; UM_distinctid=165471259cb3e-02c5602643907b-5d4e211f-100200-165471259cc86; dc_session_id=10_1534471423488.794042; dc_tos=pdlzzq; Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1534515139,1534515661,1534515778,1534515830; Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac=1534515830; ADHOC_MEMBERSHIP_CLIENT_ID1.0=d480c872-d4e9-33d9-d0e5-f076fc76aa83',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
def get_page():
r =requests.get('https://www.csdn.net/api/articles?type=more&category=home&shown_offset=1534516237069160',headers=headers)
d=r.json()#一般ajax返回的都是json格式数据,将返回的数据json格式化,.json()是requests库自带函数
articles = d['articles']#字典形式
for article in articles:
yield {
'article':article['title'],
'Link':article['user_url'],
'View':article['views']
}
for i in get_page():
print(i)
##这里应该有关于抓取不同页文章标题的操作,但是还没有解决。
案例二参考链接:
注意:CSDN爬取基础咨询需要注意会有top信息,使用selenium+Beautiful Soup或者xpath解析时需要单独注意,否则代码会一直报错。
不管是静态网页还是动态网页,爬虫的核心都是下载和解析。