实验目的:用python语言解决实际问题。
实验要求:独立完成,并上机实践
实验内容:
分析某房产网站,利用python程序爬取重庆市二手房信息,至少爬取2万条数据以上。并且把该二手房信息存入一个Excel文件或csv文件。
实现过程:
1、导入的包
import requests
from lxml import etree
import re
import csv
说明:requests 是用来获取网页信息的;lxml 用来解析html信息;
2、网页结构分析
self.headers = {
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36’
}
查看请求信息,发现我们一般写的爬虫会默认告诉服务器自己发送了一个Python爬取请求,而一般网站是不允许被爬虫访问的,估计是因为会涉及到商业问题。最后,通过更改User-Agent字段就可以轻易骗过该网站。
User-Agent会告诉网站服务器,访问者是通过什么工具来请求的,如果是爬虫请求,一般会拒绝,如果是用户浏览器,就会应答。
如何得到:
• 打开你要爬虫的网页
• 按键盘的F12或手动去浏览器右上角的“更多工具”选项选择开发者工具
• 按键盘的F5刷新网页
• 点击Network,再点击Doc
• 点击Headers,查看Request Headers的User-Agent字段,直接复制
• 将刚才复制的User-Agent字段构造成字典形式
比如:
User-Agent通常格式:
Mozilla/5.0 (平台) 引擎版本 浏览器版本号
当时想获得图文并茂的网页,就必须宣称自己是 Mozilla 浏览器
Windows NT 10.0是指我使用的操作系统的版本
一个常用的方法是使用正则表达式,进行匹配提取,这是一种通用的字符串匹配分析方式。但对于html页面来说并没有很好地利用其结构化的特点,python第三方库lxml中的etree提供了另一种更快速方便解析提取html页面数据的方式。
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历
Python中的正则表达式方面的功能,很强大。
其中就包括re.sub,实现正则的替换。功能很强大,所以导致用法稍微有点复杂。
re.sub(pattern, repl, string, count=0, flags=0)
获取标题对应的class
获取房屋详情houseInfo、关注量followInfo、总价(万)tptalPrice、每平方米unitPrice
3、爬取二手房信息并写入文件
(1)程序说明:
a.发起请求
通过HTTP库向目标服务器发送Request,Request内可以包含额外的headers信息。
b.获取响应内容
如果服务器正常响应,会返回Response, 里面包含的就是该页面的内容。
c.解析数据
内容或许是HTML,可以用正则表达式、网页解析库进行解析。
或许是Json,可以直接转换为Json对象解析。
d.保存数据
可以存储为文本,也可以保存至数据库,或其他特定类型文件。
对应的代码部分:
保存数据
保存数据
import requests
from lxml import etree
import re
import csv
class Spider(object):
def __init__(self):
self.url = 'https://cq.ke.com/ershoufang/{}/pg{}/'
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
def response(self, url):
response = requests.get(url=url, headers=self.headers) # 获得当前页面所有的html代码
response.encoding = 'utf-8'
return response.text
def parse(self, response, write):
tree = etree.HTML(response) # 快速方便解析html页面数据的方式
# 获取以下信息:'标题', '详情', '关注量', '总价(万)', '每平方米价格'
title = tree.xpath('//ul[@class="sellListContent"]//li[@class="clear"]/div[@class="info clear"]/div/a/text()')
content = tree.xpath(
'//ul[@class="sellListContent"]//div[@class="info clear"]//div[@class="houseInfo"]/text()') # 有空值
gzl = tree.xpath(
'//ul[@class="sellListContent"]//div[@class="info clear"]//div[@class="followInfo"]/text()') # 有空值
x_pr = tree.xpath(
'//ul[@class="sellListContent"]//div[@class="info clear"]//div[@class="totalPrice"]/span/text()')
s_pr = tree.xpath(
'//ul[@class="sellListContent"]//div[@class="info clear"]//div[@class="unitPrice"]/span/text()')
new_content = []
new_gzl = []
for i in range(1, len(content), 2):
new_content.append(content[i])
new_gzl.append(gzl[i])
for a, b, c, d, e in zip(title, new_content, new_gzl, x_pr, s_pr):
write.writerow([a, re.sub('|\n', '', b), re.sub(' |\n', '', c), d, e])
def crawl(self, url, write):
response = self.response(url)
items = self.parse(response, write)
def main(self):
address_list = ['jiangbei']
key = ['标题', '详情', '关注量', '总价(万)', '每平方米价格'] # 文件首行信息
for address in address_list:
with open(r'C:\Users\35969\Desktop\c.csv', 'a', newline='', encoding='utf-8_sig') as fp:
write = csv.writer(fp)
write.writerow(key) # 写入第一行信息
print('现在爬取%s的二手房信息' % address)
flag = eval(input("是否继续爬取,继续输入1,跳过该区域的爬取输入0")) # 设置flag来控制程序变化
if flag == 1:
page_max = 1000
for page in range(1, page_max + 1):
new_url = self.url.format(address, page) # 拼接成新url
self.crawl(new_url, write) # 启动爬虫程序
print('第%s页爬取完成' % page)
print('已完成%s爬取' % address)
print('\n')
elif flag == 0:
continue
if __name__ == '__main__':
S = Spider()
S.main()
(3)运行结果截图