python爬虫入门(9)
? XPath实战
? 爬取猪八戒网信息
? 猪八戒网是服务类电子商务交易平台 ,提供围绕中小微企业发展的一站式服务
一.逐步实现
1.查看页面源代码
? 看看是否直接显示在页面源代码里面,否则要使用抓包工具
找一个服务作为例子,在页面源代码中用ctrl+f查找,发现是有的
于是下一步就是提取页面源代码
2.提取页面源代码
? 先检验是否能正常爬取
import requests
url = 'https://ningbo.zbj.com/search/f/?type=new&kw=%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91'
resp=requests.get(url)
print(resp.status_code)
resp.encoding=resp.apparent_encoding
resp.close()
状态码显示为200,正常
print(resp.text)
可以正常显示
3.生成etree对象
import requests
from lxml import etree
url = 'https://ningbo.zbj.com/search/f/?type=new&kw=%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91'
resp = requests.get(url)
resp.encoding = resp.apparent_encoding
page = etree.HTML(resp.text)
resp.close()
4.得到XPath列表
每一块服务的结构都是差不多的,先实现第一个
打开检查工具,发现整个目标大概是在这一块
? 点击左上角的箭头或者按快捷键ctrl+shift+c 可以在页面中选择一个元素进行检查
然后再用小技巧,复制Xpath
? 还有一个小技巧:
在检查页面中按下ctrl+F,可以输入XPath来查找元素
通过定位,找到了目标的位置
因为每一块都是差不多的,所以我们把第一个服务的Xpath复制过来,再把索引去掉,就可以得到XPath列表
复制第一块的XPath,
得到:
/html/body/div[6]/div/div/div[4]/div[5]/div[1]/div[1]
接着把索引去掉:
/html/body/div[6]/div/div/div[4]/div[5]/div[1]/div
这时候得到的就是XPath列表,列表中是每一个服务商的XPath
5.提取所需要的信息
for div in divs:
print(div)
接下来,提取所需信息的时候就可以用相对路径了
? 作为练习,先不用直接Copy的方法,肉眼去找,找的时候,利用好折叠和展开,细心地找
提取价格
for div in divs:
price = div.xpath('./div/div/a[1]/div[2]/div[1]/span[1]/text()')
print(price)
或:
for div in divs:
pri2=div.xpath('.//span[@class ="price"]/text()')
print(pri2)
resp.close()
均可提取价格
提取标题
for div in divs:
title=div.xpath('./div/div/a[1]/div[2]/div[2]/p/text()')
或:
title2=div.xpath('.//p[@class="title"]/text()')
公司名字
for div in divs:
company = div.xpath('./div/div/a[2]/div[1]/p/text()')
或者:
company2 = div.xpath('.//p[@class="text-overflow"]/text()')
6.输出格式处理
? 这些东西都在列表里面,那么输出的时候就要从列表中拿出来
? 同时,我们发现,前面都遇到了空列表(具体原因我还没探究),这时候如果直接输出列表里的东西,比如我价格只要数字,做了如下处理:
price = div.xpath('./div/div/a[1]/div[2]/div[1]/span[1]/text()')
print(price[0].strip('¥'))
那么遇到了空列表就会报错:
于是我就加入了下面地判断条件
price = div.xpath('./div/div/a[1]/div[2]/div[1]/span[1]/text()')
if price !=[]:
print(price[0].strip('¥'))
就🆗了
上面解决了打印价格,下面先解决输出标题的问题
因为我搜索的时候keyword关键词是小程序开发,他给了高亮,那就调用join方法用”小程序开发“去把那几个东西连接起来
同样的,不输出空的
for div in divs:
title = "小程序开发".join(div.xpath('./div/div/a[1]/div[2]/div[2]/p/text()'))
if title!='':
print(title)
公司也是一样:
for div in divs:
company = div.xpath('./div/div/a[2]/div[1]/p/text()')
if company!=[]:
print(company[1].strip('\n'))
绝对路径
在检查那里复制full XPath,比如第一个服务的price,会得到
/html/body/div[6]/div/div/div[4]/div[5]/div[1]/div[1]/div/div/a[1]/div[2]/div[1]/span[1]
那么此时我们就要和前面的XPath列表进行对比
然后把前面的删去,换成.
./div/div/a[1]/div[2]/div[1]/span[1]
7.存入文件、完整代码
? 需要知道一些pandas的基础
import requests
import pandas as pd
from lxml import etree
url = 'https://ningbo.zbj.com/search/f/?type=new&kw=%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91'
resp = requests.get(url)
resp.encoding = resp.apparent_encoding
page = etree.HTML(resp.text)
divs = page.xpath('/html/body/div[6]/div/div/div[4]/div[5]/div[1]/div')
prilis=[]
titlelis=[]
companylis=[]
for div in divs:
price = div.xpath('./div/div/a[1]/div[2]/div[1]/span[1]/text()')
if price != []:
prilis.append(price[0].strip('¥'))
title = "小程序开发".join(div.xpath('./div/div/a[1]/div[2]/div[2]/p/text()'))
if title!='':
titlelis.append(title)
company = div.xpath('./div/div/a[2]/div[1]/p/text()')
if company != []:
companylis.append(company[1].strip('\n'))
name=['服务','公司','价格']
lis=[titlelis,companylis,prilis]
info=pd.DataFrame(index=name,data=lis)
info.to_csv('服务信息统计.csv',encoding='utf-8')
resp.close()
运行结果:
二.遇到的问题
1.
在解决输出格式的时候,产生了这样一个想法
import requests
from lxml import etree
url = 'https://ningbo.zbj.com/search/f/?type=new&kw=%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91'
resp = requests.get(url)
resp.encoding = resp.apparent_encoding
page = etree.HTML(resp.text)
divs = page.xpath('/html/body/div[6]/div/div/div[4]/div[5]/div[1]/div')
构造了两个函数:
def rem_emptylist(lis):
while [] in lis:
lis.remove([])
def pri_lists(lis):
for i in lis:
print(lis[0].strip("¥"))
prices=[]
for div in divs:
price = div.xpath('./div/div/a[1]/div[2]/div[1]/span[1]/text()')
prices.append(price)
rem_emptylist(prices)
pri_lists(prices)
想法来源是因为,每一个输出的price都是列表,然后我就想构造一个空列表,把每一个price都装进去
然后再把那个以列表为元素的列表用构造的rem_emptylist函数把其中的空列表删除掉,
再逐个输出,但是…报错
目前还不知道原因 😭
2.
一开始想存到csv文件里就看了👉这篇博客现学了一下,然后一开始写的columns=name,后来改成了index
|