当当网内容爬取
这次我需要将当当网中图书的图片,名字,作者名字,价格给爬取下来,因为本人小白一个,途中碰到问题居多,我查看了非常多篇文章,看看能不能给大家做个参考。
我们先打开当当网,进入青春文学-爱情内容里
现在当当网和网上视频教学的不太一样,它也是使用了js的懒加载,可是现在由于书籍变多,一次性加载服务器肯定受不了,我第一个实战项目的懒加载只是将内容写在了另一个类里,很容易爬取,但是这个我们可以通过开发者工具来观察
首先就是它的a是会刷新加载的,现在它的最后一个a的title是“女博士恋爱手册”
我们往下滑一下,发现它下面突然多出了很多的内容
我们再换到网络里面观察,发现它一直在请求内容,那我们就不能以普通的视角去看了
我一开始是使用scrapy进行爬取的,我建立好文件夹,通过xpath进行内容查询,定位到我所需的内容
可以看到我需要爬取的内容都在a里面,图片在span内,而我所需要的作者,书名,价格都在div[@class="bookinfo"]里
我将它们以xpath形式写入,并打印出来
import scrapy
class DangSpider(scrapy.Spider):
name = "dang"
allowed_domains = ["e.dangdang.com"]
start_urls = ["https://e.dangdang.com/list-AQQG-dd_sale-0-1.html"]
def parse(self, response):
list_a = response.xpath('//div[@id="book_list"]/a')
for a in list_a:
img = a.xpath('.//span[@class="bookcover"]/img[2]/@src')
title = a.xpath('.//div[@class="bookinfo"]/div[@class="title"]').extract_first()
text = a.xpath('.//div[@class="bookinfo"]/div[@class="author"]').extract_first()
price = a.xpath('.//div[@class="bookinfo"]/div[@class="price"]/span[@class="now"]').extract_first()
print(img, title, text, price)
list_a 是为了方便我们进行遍历,extract_first()是为了提取出里面的内容,在终端输入scrapy crawl dang,运行程序,发现没有进行报错但是我们提取到的img是有问题的
我们点进去看看,发现输出的是这些东西,这很明显不是我们想要的图片
我们将我写的img的xpath放入浏览器里看看发现所输出的与我们所获取的内容不一致,这时我们就应该发现了,它采用的懒加载使我们所提取的图片全部换成了XML
那么scrapy似乎就行不通了,因为它需要我们进行滑动才能将数据加载出来,这时我就想到了selenium,这个可以真正使网页启动并且操作运行,为了方便我决定使用handless,这样可以使程序运行更快
注:handless是一个无头浏览器,它可以让浏览器不显示在后台自主运行
CHROME_PATH = r'C:\Program Files\Google\Chrome\Application\chrome.exe'
URL = 'https://e.dangdang.com/list-AQQG-dd_sale-0-1.html'
#handless的封装
def share_browser():
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
# path是你自己的chrome浏览器的文件路径
path = CHROME_PATH
chrome_options.binary_location = path
browser = webdriver.Chrome(chrome_options=chrome_options)
return browser
我们直接进行handless的封装,将网址浏览器输入进去,紧接着进行调用
browser = share_browser()
# 设置要访问的URL
url = URL
browser.get(url)
这时我们就需要思考怎么样让数据刷新出来,首先通过资料查询我知道了在JavaScript里面有个网页最大高度,因为我们每次滑动网页它会加载内容,这会使网页高度变大,我们只需要获取并记录网页的最大高度将它与上一个网页的最大高度进行比较,如果相等了就说明已经到底了。
all_window_heights = [] # 创建一个列表,用于记录每一次滚动后的页面最大高度
all_window_heights.append(browser.execute_script("return document.body.scrollHeight;")) # 当前页面的最大高度加入列表
while True:
# 使用window.scrollBy()向下滚动10000像素(可能需要调整这个值以适应不同页面)
browser.execute_script("window.scrollBy(0, 10000);")
time.sleep(3) # 等待页面加载
# 获取当前页面的最大高度
current_height = browser.execute_script("return document.body.scrollHeight;")
# 如果当前页面的最大高度与上一次相等,则可能已经到达页面底部
if current_height == all_window_heights[-1]:
break
else:
all_window_heights.append(current_height) # 将新的页面最大高度加入列表
这样我们就获取到了完整的网页信息
接下来我们就使用selenium自带的定位进行内容的提取,格式和xpath的差不多,我还加入了报错提示,可以提示哪里出了问题以便修改
content = browser.page_source
with open('../dang.html', 'w', encoding='utf-8') as fp:
fp.write(content)
list_a = browser.find_elements_by_xpath( '//div[@id="book_list"]/a')
for a in list_a:
try:
img_url = a.find_element_by_xpath ('.//span[@class="bookcover"]/img[2]').get_attribute('src')
title = a.find_element_by_xpath( './/div[@class="bookinfo"]/div[@class="author"]').text
author = a.find_element_by_xpath ('.//div[@class="bookinfo"]/div[@class="author"]').text
price = a.find_element_by_xpath( './/div[@class="bookinfo"]/div[@class="price"]/span[@class="now"]').text
download_img(img_url,IMG_PATH, f"{title}_{author}_{price}.jpg")
print(f"Image: {img_url}, Title: {title}, Text: {author}, Price: {price}")
except Exception as e:
print(f"Error extracting data from element: {e}")
其中我添加了一个下载函数downlad_img可以将我需要的内容图片进行下载,最后进行输出
这个图片下载我首先需要获取三个函数,并将内容以(标题-作者-价格,jpg)的形式下载下来,如果成功了就会显现打印成功,失败输出下载失败,
IMG_PATH = "当当网内容爬取/dangdang_img"
def download_img(url, img_path,img_name):
try:
response = requests.get(url)
if response.status_code == 200:
full_path = f"{img_path}/{img_name}"
with open(full_path, 'wb') as f:
f.write(response.content)
print(f"图片打印成功:{img_name}")
else:
print("图片下载失败!")
except Exception as e:
print("图片下载失败!", e)
最后运行的结果
如果我们还需要下载其他的页码只需要将url更改,并加上遍历即可实现,只不过这些就需要大家自己动手了。
难点:懒加载滑动的处理,图片的保存,无头浏览器的运行,最大高的对比