requests库爬取当当商品信息I
requests库爬取当当商品信息(requests,lxml)
为了便于回顾和总结实习期间所学之知识与经验教训,特此简单记录一下实习学习爬虫相关内容。本次实践主要涉及利用requests库从当当网等电商平台获取数据,并从豆瓣网等多个社交平台获取信息,随后通过使用jieba词语切分工具对手上获取的所有评论文本进行初步整理与分析,再应用WordCloud工具生成关键词分布图,此外在数据清洗过程中还采用Lxml技术来精炼网页内容,并将整个处理流程划分为若干阶段以便逐步完成
1. 通过requests库向目标网站发送fetch请求
使用的工具——requests库,在其中调用get方法执行fetch操作以连接目标服务器,并获取该服务器返回的信息内容。这一过程本质上相当于模拟一个浏览器发送请求至目标网站的行为。
#-*-coding=utf-8-*-
#@Time: 2020/11/2 15:48
#@File : spider_dangdang.py
#@Software: PyCharm
#@Author:miko
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"}
def spider_all(url):
response=requests.get(url,headers=headers)
juge=response.status_code
print(juge)
print(response.text)
在游览器的开发者工具中可以方便地找到headers这一功能项。通过按下键盘快捷键F12打开开发者工具后,在页面左侧侧边栏中的【Network


requests.get方法获取到的访问是一个response类型,这个类有status_code的属性,能得到访问到的网站的状态码,200是访问成功,400,500,404等是访问失败,也就是你爬虫被发现了。
而返回的这个response类型中的text属性,能让你得到网页的源码,我们也就是利用这个方法去得到网页的源码,对网页源码中我们需要的信息进行筛选和处理。所以,我们会用到lxml库中的html这个包。
2,使用lxml库中的html包对获取到的网页源码进行信息筛选
lxml库在处理网站源码信息时相较于正则表达式(re)更为方便。它要求使用者具备对网站结构熟悉的能力即可上手操作。
html包中的fromstring()方法接收的参数即为你的源码文本。
该方法能够将你的源码转换为一个lxml.html HtmlElement对象。
//”表示从任何位置开始搜索标签,
"@”允许获取标签内的属性值,
"text()"则用于获取标签内的具体内容。
#
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"}
def spider_all(url):
response=requests.get(url,headers=headers)
print(response.status_code)
html_code=response.text
datas=html.fromstring(html_code)
print(type(datas))
data=etree.HTML(html_code)
print(type(data))
spider_all("https://movie.douban.com/top250?start=0&filter=")
etree的这种方式也可以实现与fromstring类似的效果。具体来说,在lxml.etree模块中定义了一个_EtreeNode类(_Element实际上是其父类),我们还可以利用xpath方法从html网页代码结构中提取所需的信息。
http://search.dangdang.com/?key=python%B1%E0%B3%CC%20%B4%D3%C8%EB%C3%C5%B5%BD%CA%B5%BC%F9&act=input
通过查看该商品搜索页面我们可以发现有很多特殊字符这些字符体现的是URL传递参数的方式体现了前后端的数据交互机制前端使用URL作为地址并在其中包含后端所需的必要信息通常参数部分从?开始这一部分的值经过解码处理(是不是很有趣呢?)其中编码遵循URL编码规则这里正是我们深入研究的重点区域当我们翻至下一页时会发现URL中多了一个新的参数
&page_index=2
是不是感觉有点奇妙吗?没猜错的话,“这个”其实就是当前显示的页面数值。
因此这里也就是我们进入的重点区域。通过这种方式,
从而使得我们可以自由地访问多个页面内容,
调节访问范围大小,
而如果想要全面探索整个网页内容,
那么如何确定整个网页的具体范围呢?
这个问题困扰着我很久。
其实有一种更为便捷的方式来解决这个问题。
步骤4:通过操作翻页按钮定位下一页链接地址。具体来说,在浏览器中按下Ctrl+Sftl键打开f12调试器窗口,在页面源代码面板中查看元素位置信息。接着锁定到翻页按钮定位到该按钮元素上,在其父容器节点处获取对应的url地址并存储下来。随后,在代码中持续更新爬虫脚本中的url参数设置以获取新页面内容。利用xpath查找功能在未找到目标时返回None这一特性,在适当的位置停止执行循环操作以避免无限循环或遗漏数据采集的情况。
next_page=item.xpath('//div[@class="paging"]/ul[1]/li[@class="next"]/a/@href')
if len(next_page)==0:
url=None
else:
url="http://search.dangdang.com"+next_page[0]
#此处代码为当当网商品信息爬取的测试实例。
#-*-coding=utf-8-*-
#@Time: 2020/11/2 15:48
#@File : spider_dangdang.py
#@Software: PyCharm
#@Author:miko
import requests
from lxml import html
import time
import urllib
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"}
def spider_all(url):
response=requests.get(url,headers=headers)
juge=response.status_code
information=[]
if juge==200:
html_code=response.text
data=html.fromstring(html_code)
for i in range(1,61):
product_code=data.xpath("//div[@id='search_nature_rg']/ul/li[@ddt-pit="+str(i)+"]")
shop_nub=len(product_code)
print(shop_nub)
for items in product_code:
item={}
title=items.xpath("./p[@class='name']/a/@title")[0]
item["title"]=title
link=items.xpath("./p[@class='name']/a/@href")
item["link"]=link
price=items.xpath("./p[@class='price']/span/text()")
item["price"]=price
shop=items.xpath("./p[@class='search_shangjia']/a/@title")
item["shop"]=shop
information.append(item)
time.sleep(0.1)
return information
else:print("the website is not allow you to access")
#single_one
def spider_title(url):
response=requests.get(url,headers=headers)
print(response.status_code) #获取到网页状态码
#404 未找到网页 200 可以访问 500服务器内部有问题
html_code=response.text
data=html.fromstring(html_code)
title_list=[]
for i in range(1,61):
title=data.xpath("//div[@id='search_nature_rg']/ul/li[@ddt-pit="+str(i)+"]/p/a/@title")[0]
title_list.append(title)
time.sleep(0.1)
return title_list
def spider_prise(url):
response=requests.get(url)
print(response.status_code) #获取到网页状态码
#404 未找到网页 200 可以访问 500服务器内部有问题
html_code=response.text
data=html.fromstring(html_code)
price_list=[]
for i in range(1,61):
price=data.xpath("//div[@id='search_nature_rg']/ul/li[@ddt-pit="+str(i)+"]/p[@class='price']/span/text()")[0]
price_list.append(price)
time.sleep(0.1)
return price_list
if __name__=="__main__":
#对中文进行url的再编码
# search_book=input().encode()
# data=urllib.parse.quote_plus(search_book)
# print(data)
data=input()
for i in range(1,2):
title=spider_title("http://search.dangdang.com/?key=python%B1%E0%B3%CC%20%B4%D3%C8%EB%C3%C5%B5%BD%CA%B5%BC%F9&act=input&page_index="+str(i))
print(title)
price=spider_all("http://search.dangdang.com/?key=python%B1%E0%B3%CC%20%B4%D3%C8%EB%C3%C5%B5%BD%CA%B5%BC%F9&act=input&page_index=1")
print(price)
for i in range(1,2):
items=spider_all("http://search.dangdang.com/?key=python%B1%E0%B3%CC%20%B4%D3%C8%EB%C3%C5%B5%BD%CA%B5%BC%F9&act=input&page_index="+str(i))
print(items)
此处整套当当网爬虫系统的所有代码均为完整内容属于该系统完整内容欢迎下载),其中一些地方用到的一些库没有在当前笔记中列出如若想深入了解请参考文章末尾提供的链接(PS:最近比较忙后续代码将会陆续上传)
#此处是实际项目使用的爬虫代码,将爬虫写为了类,利用类的特性。
#-*-coding=utf-8-*-
#@Time: 2020/11/4 11:47
#@File : spider_dangdang.py
#@Software: PyCharm
#@Author:miko
import urllib
from selenium import webdriver
import requests
from lxml import html
import time
import jieba
import imageio
from wordcloud import WordCloud
headers={
"Request URL": "https://movie.douban.com/cinema/later/yingkou/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36",
}
class Spider_DD:
def __init__(self,name):
data=name
self.url = f"http://search.dangdang.com/?key={data}&act=input&page_index=1"
self.headers=headers
self.links=[]
def spider(self,url):
print(url)
response=requests.get(url)
time.sleep(1.5)
print(response.status_code)
html_code=response.text
data=html.fromstring(html_code)
items = data.xpath('//div[@id="search_nature_rg"]/ul/li')
print(len(items))
information = []
juge_lpage=None
for item in items:
dic = {}
title=item.xpath('./a/@title')[0]
dic["name"] = title
link=item.xpath('./a/@href')[0]
dic["link"] = link
self.links.append(link)
price=item.xpath('./p[@class="price"]/span[@class="search_now_price"]/text()')
if len(price)==0:
price=item.xpath('./div[@class="ebook_buy"]/p/span[@class="search_now_price"]/text()')[0]
price=price.replace("¥","")
dic["price"]=float(price)
else:
price = price[0].replace("¥", "")
dic["price"]=float(price[0])
shop = item.xpath('./p[@class="search_shangjia"]/a/text()')
if shop == []:
dic["shop"] = "自营"
else:
dic["shop"] = shop[0]
information.append(dic)
next_page=item.xpath('//div[@class="paging"]/ul[1]/li[@class="next"]/a/@href')
if len(next_page)==0:
self.url=None
else:
self.url="http://search.dangdang.com"+next_page[0]
# if len(items)==60:
# juge_lpage = "http://search.dangdang.com" + str(data.xpath('//div[@class="paging"]/ul/li[@class="next"]/a/@href')[0])
# print(juge_lpage)
# if len(juge_lpage)==0:
# self.url=None
# else:
# self.url=juge_lpage
# else:self.url=None
return information
def get_comments(self,com_url="http://product.dangdang.com/24003310.html"):
url=com_url
opt = webdriver.ChromeOptions() # 创建浏览器
# 阻止网页自动关闭
# 关闭“chrome正受到自动测试软件的控制”
# V75以及以下版本
# option.add_argument('disable-infobars')
# V76以及以上版本
opt.add_experimental_option('useAutomationExtension', False)
opt.add_experimental_option('excludeSwitches', ['enable-automation'])
# 不自动关闭浏览器
opt.add_experimental_option("detach", True)
driver = webdriver.Chrome("C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe",
options=opt) # 创建浏览器对象
driver.get(url) # 打开网页
driver.maximize_window() # 最大化窗口
time.sleep(3) # 加载等待
# #滚动到底部
js = "return action=document.body.scrollHeight"
height = driver.execute_script(js)
# 将滚动条调整至页面底部
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
response = requests.get(url, headers=self.headers)
time.sleep(1)
print(response.status_code)
html_code = driver.page_source
data=html.fromstring(html_code)
nub=10
comments = ""
i=0
while nub==10:
boxs=data.xpath('//div[@id="comment_list"]/div[1]/div')
nub=len(boxs)
for item in boxs:
try:
comments+=item.xpath('./div[1]/div[2]/span/a/text()')[0]
except IndexError:
continue
try:
driver.find_element_by_xpath('//div[@id="comment_list"]/div[2]/div/a[last()]').click()
except :
break
time.sleep(1)
i+=1
if i==10:
break
driver.quit()
return comments
def drawing(self,comments,i):
data_list = jieba.lcut(comments)
data = " ".join(data_list)
mask = imageio.imread("./file/yuansheng.png") # 蒙版
cloud = WordCloud(
background_color="pink",
width=1200,
height=1200,
font_path="msyh.ttc",
mask=mask
)
dic = {}
for str in data_list:
if 2 <= len(str) <= 3:
if dic.get(str) != None:
dic[str] += 1
else:
dic[str] = 1
lists = list(dic.items())
lists.sort(key=lambda x: x[1], reverse=True)
print(lists)
try:
cloud.generate(data).to_file(f"./file/img/draw{i.strip()}.png")
except:
pass
#这里之后还得进行优化,处理重名,多数据的情况
def run(self):
datas=[]
i=0
while self.url!=None:
print("success")
datas.extend(self.spider(self.url))
if i ==10:
break
i+=1
datas.sort(key=lambda x:x["price"])
# for i in datas:
# comments=self.get_comments(i["link"])
# self.drawing(comments,i["name"])
# print("success")
return datas
if __name__ == '__main__':
search_book = "python"
data=Spider_DD(search_book)
datas=data.run()
print(datas)
