文章目录
遇到的问题及解决方法
1.xpath()函数的使用-之后会练习使用find_all()函数
需要安装lxml库,xpath()方法放回的结果是一个列表
1.1 XPath 常用规则
表达式 | 描述 |
---|---|
nodename | 1 |
// | 从当前节点选取子孙节点 |
/ | 从当前节点选取子节点 |
. | 选取当前结点 |
… | 选取当前节点的父节点 |
@ | 选取属性 |
例子:
//title[@lang='eng']
这是一个 XPath 规则,代表的是选择所有名称为 title,同时属性 class 的值为 eng 的节点,后面会通过 Python 的 lxml 库,利用 XPath 进行 HTML 的解析。
1.2 获取文本
# 第一种
# 获取文本所在节点后直接获取文本
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/a/text()')
print(result)
# 第二种
# 会获取到补全代码时换行产生的特殊字符,推荐使用第一种方法,可以保证获取的结果是整洁的。
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]//text()')
print(result)
1.3 要提取的信息有大量空格
使用normalize-space()函数:
# 提取出来会有大量空格
level = html.xpath('//table[@class="info-tb"]/tr[4]/td[4]/text()')
# 使用normalize-space()
level = html.xpath('normalize-space(//table[@class="info-tb"]/tr[4]/td[4]/text())')
1.4 多属性匹配
# 直接在xpath中使用and
from lxml import etree
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
1.5 提取的网址不是完全意义上的网址
只是部分的网址,例如这个网站提取的就是缺少https://dl.58.com
的网址,所以要给加上这一块,当提取完后,可以直接这样:
return ['https://dl.58.com' + item for item in list_urls]
1.4 遇到tbody的情况如何处理:
这是网页的规范性问题,可以直接跳过,我们定位路径的时候可以直接忽略这个点
1.5 提取的内容有好多tr,td:
这个时候我们可以直接定位到某一个点:
# 第三个tr,第四个td
price = html.xpath('normalize-space(//table[@class="info-tb"]/tr[3]/td[4]/text())')
2. etree.HTML()函数解析
etree.HTML()可以用来解析字符串格式的HTML文档对象,将传进去的字符串转变成_Element对象。作为_Element对象,可以方便的使用getparent()、remove()、xpath()等方法。
url = "https://dl.58.com/xiaoqu/150/"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/87.0.4280.88 Safari/537.36"
}
rep = requests.get(url, headers=headers)
rep.encoding = 'utf-8'
# print(rep.text) 输出的是网页的全部源代码
html = etree.HTML(rep.text)
# 通过xpath筛选出所需要的代码信息
list_url = html.xpath('//ul[@class="xq-list-wrap"]/li/div[@class="pic"]/a/@href')
3. 保存到Exce:
需要调用xlwt库,同时也需要利用pip安装:pip install xlwt
import xlwt
# 创建一个workbook
workbook = xlwt.Workbook(encoding='utf-8')
# 创建表名
data_sheet = workbook.add_sheet('sheet1')
# 设置表头
row0 = ['1', '2', '3', '4', '5', '6']
# 将第一行写进去
for k in range(0, len(row0)):
data_sheet.write(0, k, row0[k])
# 利用cnt控制行数
cnt = 1
# 写入全部数据
for item in all_url:
list_informations = []
list_informations += get_information(item)
for j in range(0, len(list_informations)):
data_sheet.write(cnt, j, list_informations[j])
cnt += 1
# 保存文件
workbook.save('filename.xlsx')
4. 突然提取不出信息了,返回的是空列表的解决办法
一般这种情况,往往是因为网站觉得你操作太频繁了,需要手动验证一下,这个时候手动打开一个网页,根据网页提示进行操作一个,即可继续进行信息提取。
4.1 注意如果网页操作太频繁的话会被冻结,这个时候可以用time库里面的sleep操作:
# 生成随机数的函数randint
from random import randint
# 设置睡眠时间,即多久运行一次
from time import sleep
# 放到函数里即可,程序执行到这里会进行停顿
sleep(randint(2, 5))
源代码
爬取某同城某地区全部小区信息
from random import randint
import requests
# 直接保存到本地
from lxml import etree
from time import sleep
# 创建excel表格的
import xlwt
def get_name__url():
list_urls = []
for i in range(1, 20):
if i == 1:
url = "https://dl.58.com/xiaoqu/150/"
else:
url = "https://dl.58.com/xiaoqu/150/pn_%d/" % i
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/87.0.4280.88 Safari/537.36"
}
rep = requests.get(url, headers=headers)
rep.encoding = 'utf-8'
# print(rep.text)
html = etree.HTML(rep.text)
list_url = html.xpath('//ul[@class="xq-list-wrap"]/li/div[@class="pic"]/a/@href')
list_urls += list_url
return ['https://dl.58.com' + item for item in list_urls]
def get_information(url):
# print(url)
list_information = []
sleep(randint(2, 5))
# print(url)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/87.0.4280.88 Safari/537.36"
}
rep = requests.get(url, headers=headers)
rep.encoding = 'utf-8'
html = etree.HTML(rep.text)
name = html.xpath('//div[@class="body-wrapper"]/div[@class="title-bar"]/span/text()')
# print(name)
value = html.xpath('//div[@class="body-wrapper"]/div[@class="basic-container"]//div['
'@class="price-container"]/span/text()')[:2]
# all_information = html.xpath('//div[@class="body-wrapper"]/div[@class="basic-container"]/div['
# '@class="info - tb - container"]/table[@class="info-tb"]/tr[5]/td[2]/text()')
build_year = html.xpath('normalize-space(//table[@class="info-tb"]/tr[5]/td[2]/text())')
level = html.xpath('normalize-space(//table[@class="info-tb"]/tr[4]/td[4]/text())')
# print(level)
nums = html.xpath('normalize-space(//table[@class="info-tb"]/tr[2]/td[4]/text())')
# print(nums)
price = html.xpath('normalize-space(//table[@class="info-tb"]/tr[3]/td[4]/text())')
# print(price)
list_information += name
list_information.append(value)
list_information.append(build_year)
list_information.append(level)
list_information.append(nums)
list_information.append(price)
print(list_information)
return list_information
if __name__ == '__main__':
all_url = get_name__url()
workbook = xlwt.Workbook(encoding='utf-8')
# 创建表名
data_sheet = workbook.add_sheet('小区')
row0 = ['小区名称', '均价', '建造年代', '容积率', '户数', '物业费']
for k in range(0, len(row0)):
data_sheet.write(0, k, row0[k])
cnt = 1
for item in all_url:
# 看看执行到多少条了
print(cnt)
list_informations = []
list_informations += get_information(item)
for j in range(0, len(list_informations)):
data_sheet.write(cnt, j, list_informations[j])
cnt += 1
workbook.save('沙口区小区信息.xlsx')
print("程序执行完成")