静态网页爬取
前言
网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。。
一、静态网站分析
例子网站:http://fitness.39.net/food/
任务要求:
第一步获取食物的大类
第二步获取所有大类里面所有分页的食材
第三步获取所有大类里面所有分页食材的营养成分和营养占比
二、所需要的依赖和插件
1.引入库
代码如下(示例):
from asyncio.windows_events import NULL
import requests
import mysql.connector
import datetime
from lxml import etree
from bs4 import BeautifulSoup
from selenium import webdriver
插件:phantomjs.exe
插件:XPath
插件介绍:
PhantomJS是一个可编程的无头浏览器.
无头浏览器:一个完整的浏览器内核,包括js解析引擎,渲染引擎,请求处理等,但是不包括显示和用户交互页面的浏览器。
2.PhantomJS的使用场景
PhantomJS的适用范围就是无头浏览器的适用范围。通常无头浏览器可以用于页面自动化,网页监控,网络爬虫等:
页面自动化测试:希望自动的登陆网站并做一些操作然后检查结果是否正常。
网页监控:希望定期打开页面,检查网站是否能正常加载,加载结果是否符合预期。加载速度如何等。
网络爬虫:获取页面中使用js来下载和渲染信息,或者是获取链接处使用js来跳转后的真实地址。
————————————————
版权声明:本文为优快云博主「violetgo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/violetgo/article/details/48105593
三、代码展示
第一步获取食物的大类
用XPath插件找到需要爬取的html组件
response = requests.get(url="http://fitness.39.net/food/")
response.encoding = 'utf-8'
# 获取一级分类的数据
html = etree.HTML(response.text)
print(html.xpath("//dl[@id='food_ele_dl_id']//dd//a" ))
items = html.xpath("//dl[@id='food_ele_dl_id']//dd//a" )
data_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") #系统时间
val = []
val1 = []
# 遍历items的集合
for item in items:
title = "".join(item.xpath("./@title"))
href = "".join(item.xpath("./@href"))
val.append((title,href,data_time))
# print(html.xpath("" ))
print(val)
mydb = mysql.connector.connect(
host="11.11.11.111",
user="root",
passwd="123456",
database="python"
)
mycursor = mydb.cursor()
#删除旧的食材分类数据
sql = "DELETE FROM p_food_type "
mycursor.execute(sql)
mydb.commit()
print(mycursor.rowcount, " 条记录删除")
#插入新数据
sql = "INSERT INTO p_food_type (title, url,create_time) VALUES (%s, %s, %s)"
mycursor.executemany(sql, val)
mydb.commit() # 数据表内容有更新,必须使用到该语句
print(mycursor.rowcount, "记录插入成功。")
第二步获取大类里面所有的小类包括分页
分析一下分页如何搞定
举例以谷物分析
通过图片我们可以找到分页的规律。
那么我们可以通过循环大类的url并拼接成分页的url去请求数据直到拼接的url请求不到数据我们判定为是最后一页而跳出本次大类进入下一大类。
#查询大类表
setsql = "SELECT * FROM p_food_type "
mycursor.execute(setsql)
myresult = mycursor.fetchall()
n = 100
sum = 0
counter = 1
#循环大类表
for x in myresult:
counter=1
while counter <= n:
# 分页的处理
print(x[2])
sun=x[2]
s1=list(sun)
print (s1[-6])
s1[-6]=str(counter)
s=''.join(s1)
print("我是分页链接"+s)
#请求分页链接
response = requests.get(url=s)
response.encoding = 'utf-8'
# 获取一级分类的数据
# print(response.text)
html = etree.HTML(response.text)
# 获取当前分页链接的所有食材
items = html.xpath("//ul[@id='sort_list_show']/li/a" )
print(items)
# 判断当前分页是不是有食材没有的话直接跳出循环进入下一个大类的循环
if items==[]:
break
data_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") #系统时间
# 遍历当前分页所有的食材
for item in items:
val1=[]
# 获取当前食材的名字和链接
title = "".join(item.xpath("./@title"))
href = "".join(item.xpath("./@href"))
print(href)
print(title)
#判断食材名字不为空
if title!="" or title!=NULL:
#这是大类的名字
print("我在这里"+x[1])
# 请求食材的url进入当前食材的详情页面
response2 = requests.get(url=href)
response2.encoding = 'utf-8'
# print(response2.text)
# 下面就是获取当前食材的营养成分和占比
html2 = etree.HTML(response2.text)
items2 = html2.xpath("//div[@class='ck-show']//ul//li/i" )
#别名
nameb="".join(html2.xpath("//span[@class='title-left']/text()"))
# 减肥指数
jfzs="".join(html2.xpath("//span[@class='ju-box']/cite/text()"))
print(jfzs)
#有利
yl= "".join(html2.xpath("//span[@class='ju']/p[1]/text()"))
print(yl)
#无利
wl ="".join(html2.xpath("//span[@class='ju']/p[2]/text()"))
print(wl)
#gi值
gi ="".join(html2.xpath("//span[@class='gi']/b/text()"))
print(gi)
# 卡路里占比经过js计算所以xpath的方式获取不到咱们就用phantomjs.exe插件获取
browser = webdriver.PhantomJS(executable_path=r'D:\\python\\phantomjs.exe')
browser.get(href)
html = browser.page_source
soup = BeautifulSoup(html, 'lxml')
# 这是phantomjs.exe获取组件的方式和xpath有所不同
# 卡路里百分比
kll=soup.find('div',{'class':"bing"}).findAll('td')
#脂肪占比
# zfzb= "".join(html2.xpath("//span[@class='down']/text()"))
p1,p2,p3=kll[1].get_text().partition('%')
zfzb=p1+p2
print(zfzb)
#碳水化合物占比
# tshhw= "".join(html2.xpath("//span[@class='up']/text()"))
p1,p2,p3= kll[4].get_text().partition('%')
tshhw=p1+p2
print(tshhw)
#蛋白质
# dbz = "".join(html2.xpath("//div[@class='bing']//table//tbody/tr[4]/td[2]/text()"))
p1,p2,p3=kll[7].get_text().partition('%')
dbz=p1+p2
print(dbz)
print(nameb)
v0 = "".join(items2[0].xpath("./text()"))
print(v0)
v30 = "".join(items2[30].xpath("./text()"))
if v30=="":
items2[30]="-"
print(items2[30])
v31 = "".join(items2[31].xpath("./text()"))
if v31=="":
items2[31]="-"
print(items2[31])
val1.append((x[1],title,href,data_time,"".join(items2[0].xpath("./text()")),"".join(items2[1].xpath("./text()")),"".join(items2[2].xpath("./text()")),"".join(items2[3].xpath("./text()")),"".join(items2[4].xpath("./text()")),"".join(items2[5].xpath("./text()")),"".join(items2[6].xpath("./text()")),"".join(items2[7].xpath("./text()")),"".join(items2[8].xpath("./text()")),"".join(items2[9].xpath("./text()")),"".join(items2[10].xpath("./text()")),
"".join(items2[11].xpath("./text()")),"".join(items2[12].xpath("./text()")),"".join(items2[13].xpath("./text()")),"".join(items2[14].xpath("./text()")),"".join(items2[15].xpath("./text()")),"".join(items2[16].xpath("./text()")),"".join(items2[17].xpath("./text()")),"".join(items2[18].xpath("./text()")),"".join(items2[19].xpath("./text()")),"".join(items2[20].xpath("./text()")),"".join(items2[21].xpath("./text()")),"".join(items2[22].xpath("./text()")),"".join(items2[23].xpath("./text()")),"".join(items2[24].xpath("./text()")),
"".join(items2[25].xpath("./text()")),"".join(items2[26].xpath("./text()")),"".join(items2[27].xpath("./text()")),"".join(items2[28].xpath("./text()")),"".join(items2[29].xpath("./text()")),items2[30],items2[31],"".join(items2[32].xpath("./text()")),"".join(items2[33].xpath("./text()")),"".join(items2[34].xpath("./text()")),"".join(items2[35].xpath("./text()")),"".join(items2[36].xpath("./text()")),"".join(items2[37].xpath("./text()")),"".join(items2[38].xpath("./text()")),
"".join(items2[39].xpath("./text()")),"".join(items2[40].xpath("./text()")),"".join(items2[41].xpath("./text()")),"".join(items2[42].xpath("./text()")),"".join(items2[43].xpath("./text()")),nameb,jfzs,yl,wl,gi,zfzb,tshhw,dbz))
print(val1)
else:
break
counter += 1