import requests
import csv
import os
from lxml import etree
def getHtml(name, page):
url = "https://search.jd.com/Search?"
parmas = {"keyword": name, "enc": "utf-8", "page": page}
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"}
try:
res = requests.get(url=url, params=parmas, headers=headers)
res.encoding = res.apparent_encoding
return res.text
except Exception as e:
print(e)
def getdiv(html):
xpl = etree.HTML(html) # 解析网页,构造xpath对象
divs = xpl.xpath("//div[@class='gl-i-wrap']")
return divs
def getTitle(divs):
for i in divs:
print("-------------------------------------------------------------")
print(i.xpath('div[@class="p-name p-name-type-2"]//em/text()'))
data = i.xpath('div[@class="p-name p-name-type-2"]//em/text()')
for data1 in data:
index = data1.find(" ")
dict1 = {"商品名称": data1[0:index], "描述": data1[index + 1:]}
price = i.xpath('div[@class="p-price"]//i/text()')
shop = i.xpath('div[@class="p-shop"]//a/text()')
for data2, data3 in zip(price, shop):
dict2 = {"价格": data2, "店铺": data3}
print("评论数:", i.xpath('div[@class="p-commit"]//a'), "条评价")
# for item in i.xpath('div[@class="p-commit"]/strong'):
# print(etree.tostring(item).decode("utf-8"))
dic = {}
dic.update(dict1)
dic.update(dict2)
imgs = i.xpath('div[@class="p-img"]//img[@source-data-lazy-img]') # @[0].get("source-data-lazy-img")
for index in range(0, len(imgs)):
img = imgs[index].get("source-data-lazy-img")
dict3 = {"图片链接": img}
# print(img)
dic.update(dict3)
with open("jd.csv", "a", encoding="utf8", newline="")as f:
title = ["商品名称", "描述", "价格", "店铺", "图片链接"]
dictwri = csv.DictWriter(f, title)
if os.path.getsize('jd.csv') == 0:
dictwri.writeheader()
dictwri.writerow(dic)
if __name__ == "__main__":
for i in range(1, 100):
html = getHtml("宠物", str(i))
divs = getdiv(html)
getTitle(divs)
运算符 |
描述 |
实例 |
返回值 |
or |
或 |
price=9.80 or price=9.70 |
如果 price 是 9.80,则返回 true如果 price 是 9.50,则返回 false |
and |
与 |
price>9.00 and price<9.90 |
如果 price 是 9.80,则返回 true如果 price 是 8.50,则返回 false |
mod |
计算除法的余数 |
5 mod 2 |
1 |
\ |
计算两个节点集 |
//book \ //cd |
返回所有拥有 book 和 cd 元素的节点集 |
+ |
加法 |
6 + 4 |
10 |
- |
减法 |
6 - 4 |
2 |
* |
乘法 |
6 * 4 |
24 |
div |
除法 |
8 div 4 |
2 |
运算符 |
描述 |
实例 |
返回值 |
or |
或 |
price=9.80 or price=9.70 |
如果 price 是 9.80,则返回 true如果 price 是 9.50,则返回 false |
and |
与 |
price>9.00 and price<9.90 |
如果 price 是 9.80,则返回 true如果 price 是 8.50,则返回 false |
mod |
计算除法的余数 |
5 mod 2 |
1 |
\ |
计算两个节点集 |
//book \ //cd |
返回所有拥有 book 和 cd 元素的节点集 |
+ |
加法 |
6 + 4 |
10 |
- |
减法 |
6 - 4 |
2 |
* |
乘法 |
6 * 4 |
24 |
div |
除法 |
8 div 4 |
2 |
有时需要选取可能某些属性同时匹配了多个节点,但是只想需要其中的某个节点,如第二个节点,或者最后一个节点,这时该怎么办呢?
可以利用中括号传入索引的方法获取特定次序的节点,示例如下:
from lxml import etreehtml = etree.parse('testData.html', etree.HTMLParser())result = html.xpath('//li[1]/a/text()')print(result)result = html.xpath('//li[last()]/a/text()')print(result)result = html.xpath('//li[position()<3]/a/text()')print(result)result = html.xpath('//li[last()-2]/a/text()')print(result)
表达式 |
描述 |
nodename |
选取此节点的所有子节点 |
/ |
从当前节点选取直接子节点 |
// |
从当前节点选取子孙节点 |
. |
选取当前节点 |
.. |
选取当前节点的父节点 |
@ |
选取属性 |