多网爬虫项目
项目背景
大数据、人工智能技术飞速发展,数据是大数据和人工智能的基础,如何从互联网上获取数据是我们大数据和人工智能企业的一大难题。通常企业会通过爬虫从互联网上获取其想要的数据,本项目就是从多个网站通过爬虫去获取数据。
项目概述
项目简介
在各大公司开发平台中,或多或少都要用到从其他网站平台中获取对应的数据来做数据分析、处理等等,那么对于其他网站平台中的数据需要做相关的数据采集操作,并用于对公司相关的项目研发。那么则需要在互联网中获取数据。
而互联网是由一个个站点和网络设备组成的大网,我们通过浏览器访问站点,站点把HTML、JS、CSS代码返回给浏览器,这些代码经过浏览器解析、渲染,将丰富多彩的网页呈现我们眼前。
如果我们把互联网比作一张大的蜘蛛网,数据便是存放于蜘蛛网的各个节点,而爬虫就是一只小蜘蛛,沿着网络抓取自己的猎物(数据)爬虫指的是:向网站发起请求,获取资源后分析并提取有用数据的程序。
所以从技术层面来说就是通过程序模拟浏览器请求站点的行为,把站点返回的HTML代码/JSON数据/二进制数据(图片、视频) 爬到本地,进而提取自己需要的数据,存放起来使用;
项目客户群
1、数据采集公司:实现多线程采集数据;
2、网站可视化平台系统:实现后端数据采集功能。
项目需求
1、使用多线程技术爬取诗词名句网中的作者和作者对应的诗词。
2、使用多线程技术爬取北京链家二手房小区名、户型、面积、朝向、楼层、单价等信息,并保存到csv中
3、使用requests库单线程爬取猫眼电影top100榜单中标题、主演、上映时间、评分等信息,并输出到csv。
项目目标
通过完成本项目,您将能够:
1.掌握爬虫项目环境的搭建(Requests、Parsel)
2.掌握网页解析以及处理网页内容的能力
3.掌握多线程爬虫以及编写具有逻辑性函数的能力
4.通过本项目可以综合提升学生的能力,从任务需求、网页解析、到数据获取和数据处理以及存储,可以让刚刚步入职场的同学胜任python爬虫工程师基础岗位
项目环境
实验环境 | 版本信息 |
---|---|
操作系统 | Ubuntu-18.04 桌面版 |
内存信息 | ≥8G |
硬盘信息 | ≥60G |
开发工具 | Pycharm-2021 |
开发语言 | Python-3.6.9 |
软件清单
产品 | 版本号 | 功能描述 |
---|---|---|
parsel | latest | 基于lxml构建的高效网页解析库,提供了强大而灵活的工具,用于解析HTML和XML文档。 |
requests | latest | 一个用于发送 HTTP 请求的流行 Python 库,可以完成多种 HTTP 请求操作。 |
fake-useragent | latest | 一个第三方Python库,用于生成随机的User-Agent标头。 |
项目开发
任务 | 岗位 | 详细说明 | 交付标准 |
---|---|---|---|
环境搭建 | python运维工程师 | python运维工程师在开发前与python爬虫工程师对接,了解项目所需环境,进行环境配置。配置环境时要避免重新安装、版本不兼容、更换版本等问题产生,保证开发过程的顺畅。配置完成并通过测试后,对接给python爬虫工程师 | 各组件测试可正常运行 |
诗词名句多线程爬取 | python爬虫工程师 | python爬虫工程师从公司部门主管处获取任务书,了解任务详情和开发内容要求后,首先梳理整体的项目逻辑,然后根据需求设计项目模块,并确定各个模块需具备的功能及相互之间的联系。从网络运维工程师那里获取到开发环境后,进行实际开发工作 | 项目文件格式准确;采集内容准确,代码梳理清楚 |
北京链家二手房多线程爬取 | python爬虫工程师 | python爬虫工程师从公司部门主管处获取任务书,了解任务详情和开发内容要求后,首先梳理整体的项目逻辑,然后根据需求设计项目模块,并确定各个模块需具备的功能及相互之间的联系。从网络运维工程师那里获取到开发环境后,进行实际开发工作 | 项目文件格式准确;采集内容准确,代码梳理清楚 |
爬取猫眼电影top100 | python爬虫工程师 | python爬虫工程师从公司部门主管处获取任务书,了解任务详情和开发内容要求后,首先梳理整体的项目逻辑,然后根据需求设计项目模块,并确定各个模块需具备的功能及相互之间的联系。从网络运维工程师那里获取到开发环境后,进行实际开发工作 | 项目文件格式准确;采集内容准确,代码梳理清楚 |
任务一 环境搭建
任务场景
python运维工程师在开发前与python爬虫工程师对接,了解项目所需环境,进行环境配置。配置环境时要避免重新安装、版本不兼容、更换版本等问题产生,保证开发过程的顺畅。配置完成并通过测试后,对接给python爬虫工程师。
1.1 安装parsel
parsel
是一个基于lxml构建的高效网页解析库,专为Python开发者设计,提供了强大而灵活的工具,用于解析HTML和XML文档。
pip install parsel
1.2 安装requests
requests
是一个用于发送 HTTP 请求的流行 Python 库。
pip install requests
# 因为该环境中已经自带了requests库,会提示以下内容,所以可以不用安装
1.3 安装fake_useragent
fake_useragent
是一个Python库,用于生成随机的User-Agent标头。
pip install fake_useragent
1.4 启动pycharm并创建项目文件
①、双击桌面的【Pycharm】开发者工具,勾选【同意协议】选款,点击【continue】继续:
②、在欢迎界面,点击【New Project】创建新的项目:
③、为项目命名为spider_project(名称可自定义),选择python解释器版本完成创建:
④、将弹出的每日更新【Tip of the day】点击【Close】关闭即可。
任务二 诗词名句多线程爬取
2.1 创建ShiCiMingJu.py
爬虫文件
在项目名称上右击鼠标,依次选择【New】,【Python file】:
输入代码文件名称ShiCiMingJu(名称可自定义),点击回车完成创建。
此时创建完成:
2.2 实现思路
(1)导入需要的包
import requests
from queue import Queue
from parsel import Selector
import math
from concurrent.futures import ThreadPoolExecutor
(2)创建爬虫类,类名:SCMJ,在__init__
函数中创建一个队列,并设置初始的url以及headers
class SCMJ(object):
def __init__(self):
# 创建一个队列
self.queue = Queue()
# 初始的url
self.base_url = "http://www.shicimingju.com"
self.headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36'}
(3)在SCMJ
类中创建get_url
函数,将每个诗人对应的url,添加到队列中
def get_url(self):
"""根据13035为诗人生成每个诗人对应的url,然后入队列"""
for page in range(1, 13036):
url = "http://www.shicimingju.com/chaxun/zuozhe/{}.html".format(page)
self.queue.put(url)
(4)在SCMJ
类中创建get_response
函数,获取网页资源
def get_response(self, url):
try:
# 发送请求,获取响应内容
response = requests.get(url=url, headers=self.headers)
response.encoding = "utf-8"
response.raise_for_status()
return response.text
except Exception as e:
print(e.args)
(5)在SCMJ
类中创建get_author
函数,用于获取作者页面的作者名称、信息、年代以及所著作品的页面数量
def get_author(self, response):
selector = Selector(response)
# 诗人姓名
author = selector.xpath('//*[@id="main_right"]/div[1]/div[2]/div[1]/h4/a/text()').get()
# 诗人朝代
year = selector.xpath('//*[@id="main_right"]/div[1]/div[3]/div[1]/div[2]/a/text()').get()
# 诗人简介
_intro = selector.xpath('//*[@id="main_right"]/div[1]/div[2]/div[1]/div//text()').getall()
intro = "".join(_intro).strip()
# 该诗人的诗的页码
_sc_count = selector.xpath('//*[@id="main_right"]/div[1]/div[3]/div[2]/div[2]/a/text()').get()
sc_count = _sc_count.replace("首", "")
page = math.ceil(int(sc_count) / 20)
return author, year, intro, page
(6)在SCMJ
类中创建zp
函数,用于获取作品内容、注释以及标题
def zp(self, response):
selector = Selector(response)
# 获取诗的内容
_sc = selector.xpath("//div[@class='item_content']/text()").getall()
sc = "".join(_sc).strip()
# 获取诗的注释
_comments = selector.xpath("//div[@class='shangxi_content']//text()").getall()
comments = "".join(_comments).strip()
# 获取诗的标题
title = selector.xpath('//*[@id="zs_title"]/text()').getall()
title = "".join(title).strip()
return sc, comments, title
(7)在SCMJ
类中创建zp_urls
函数,用于获取作者的作品链接
def zp_urls(self, zz_url, page, author, writefile):
for i in range(1, page + 1):
# 构建每一页的url
zp_url = zz_url.replace(".html", "") + f"_{i}" + ".html"
# 向每一页的url发送请求得到响应
zp_res = self.get_response(zp_url)
selector = Selector(zp_res)
# 获取该页所有诗句的url
zp_urls = selector.xpath("//div[@class='shici_list_main']/h3/a/@href").getall()
# 将获取的url和基准url拼接成完整的url
zp_url = [self.base_url + url for url in zp_urls]
# 遍历每一篇诗的url
for url in zp_url:
# 获取相应
res = self.get_response(url)
sc, comments, title = self.zp(res)
# 打印诗的标题-作者-诗的内容
print("{}-[{}]{}".format(title, author, sc))
writefile.write("{}-[{}]{}".format(title, author, sc) + "\n")
(8)在SCMJ
类中创建parse
函数,用于从队列中获取我们刚才采集到作者的url
def parse(self):
# 只要队列不为空,就一直循环取url
while not self.queue.empty():
with open("shicimingju.txt", "a+", encoding="utf-8-sig")as writefile:
# 取到一个诗人的url
zz_url = self.queue.get()
print(zz_url)
# 获取该url的响应内容
zz_res = self.get_response(url=zz_url)
# print(zz_res)
# 从响应内容中获取作者,年份
author, year, intro, page = self.get_author(zz_res)
print(author)
writefile.write(author + "\n")
self.zp_urls(zz_url, page, author, writefile)
(9)在SCMJ
类中创建run
函数,用于执行上述创建的函数,以及将队列中的内容使用多线程获取数据
def run(self):
# 将url入队列
self.get_url()
# self.parse()
loop = ThreadPoolExecutor()
for _ in range(1):
loop.submit(self.parse)
(10)最后在外部初始化实例对象SCMJ
类,用于启动执行我们创建SCMJ
类中的run
函数。
if __name__ == '__main__':
spider = SCMJ()
spider.run()
(11)执行完成后会生成一个shicimingju.txt
文件
执行结果:
shicimingju.txt
文件:
文件大致内容:
任务三 北京链家二手房多线程爬取
3.1 创建lianjia.py
爬虫文件
在项目名称上右击鼠标,依次选择【New】,【Python file】:
输入代码文件名称lianjia(名称可自定义),点击回车完成创建。
此时创建完成:
3.2 实现思路
(1)导入需要的包
import random
import requests
from fake_useragent import UserAgent
from parsel import Selector
from queue import Queue
from concurrent.futures import ThreadPoolExecutor
import csv
(2)创建爬虫类,类名:BjLianJia,在__init__
函数中添加全局变量的实例对象,用于后续存放获取到的数据内容。
class BjLianJia(object):
def __init__(self, url, esf_queue):
self.url = url
self.esf_queue = esf_queue
self._headers = ""
self._esf_url = ""
(3)在BjLianJia
类中创建random_ua
函数,调用UserAgent库用于随机获取请求头,并传回给全局变量的实例对象_headers
# 随机请求头
def random_ua(self):
user_agent = []
for i in range(10):
user_agent.append(UserAgent().random)
headers = {
"user-agent": random.choice(user_agent)
}
self._headers = headers
(4)在BjLianJia
类中创建get_response
函数,
# 下载页面
def get_response(self, url):
try:
response = requests.get(url, headers=self._headers)
response.encoding = "utf-8"
response.raise_for_status()
return response
except Exception as e:
print(e.args)
(5)在BjLianJia
类中创建parse_url
函数,用于获取二手房的链接。
# 解析主页面
def parse_url(self, response):
'''获取二手房的链接'''
selector = Selector(response.text)
esf_href = selector.xpath("//div[@class='nav typeUserInfo']//ul/li[1]/a/@href").get() # 二手房链接
self._esf_url = esf_href
(6)在BjLianJia
类中创建parse_esf_house_url
函数,用于获取二手房链接地址。
# 获取二手房链接
def parse_esf_house_url(self):
response = self.get_response(url=self._esf_url)
selector = Selector(response.text)
a_list = selector.xpath("//div[@data-role='ershoufang']/div/a")
for a in a_list:
area_href = a.xpath("./@href").get()
area_url = self._esf_url + "/" + area_href.split('/')[2]
esf_response = self.get_response(url=area_url)
html = Selector(esf_response.text)
count = html.xpath("//h2[@class='total fl']/span/text()").get()
page = int(count) // 30
if page > 100 :
for i in range(1, 101):
url = area_url + f"/pg{i}"
self.esf_queue.put(url)
else:
for i in range(1, page + 1):
url = area_url + f"/pg{i}"
self.esf_queue.put(url)
(7)在BjLianJia
类中创建parse_esf_info
函数,用于获取二手房数据信息,并将数据信息传到save_csv
函数中进行存储。
# 获取二手房信息
def parse_esf_info(self, url):
print("开始下载url:%s" % url)
response = self.get_response(url)
selector = Selector(response.text)
li_list = selector.xpath("//ul[@class='sellListContent']/li")
for li in li_list:
item = {}
item['house_estate'] = li.xpath(".//div[@class='flood']/div/a[1]/text()").get() # 小区名
house_info = li.xpath(".//div[@class='address']/div/text()").get()
item['house_price'] = li.xpath(".//div[@class='unitPrice']/@data-price").get() # 房屋单价
try:
info = house_info.split("|")
item['house_type'] = info[0].strip() # 户型
item['house_square'] = info[1].strip() # 面积
item['cx'] = info[2].strip() # 朝向
item['house_floor'] = info[4].strip() # 楼层
except Exception:
continue
self.save_csv(item)
(8)在BjLianJia
类中创建save_csv
函数,用于存储数据信息到csv中
# 保存到csv中
def save_csv(self, item):
writer.writerow([item['house_estate'], item['house_type'], item['house_square'], item['cx'], item['house_floor'],item['house_price']])
(9)最后在外部初始化实例对象BjLianJia
类,用于启动执行我们创建BjLianJia
类中的函数。
if __name__ == '__main__':
file = open("bj.csv", "a+", encoding="utf-8", newline="")
writer = csv.writer(file)
writer.writerow(['house_estate', 'house_type', 'house_square', 'cx', 'house_floor','house_price'])
url = "https://bj.lianjia.com/"
esf_queue = Queue()
pool = ThreadPoolExecutor()
spider = BjLianJia(url, esf_queue)
response = spider.get_response(url)
spider.parse_url(response)
spider.parse_esf_house_url()
[pool.submit(spider.parse_esf_info, esf_queue.get()) for i in range(esf_queue.qsize())]
(11)执行完成后会生成一个bj.csv
文件
运行结果:
bj.csv
文件:
文件大致内容:
任务四 爬取猫眼电影top100
4.1 创建猫眼电影Top100.py
爬虫文件
在项目名称上右击鼠标,依次选择【New】,【Python file】:
输入代码文件名称MaoYanTop100(名称可自定义),点击回车完成创建。
此时创建完成:
4.2 实现思路
(1)导入需要的包
import requests
import time
from parsel import Selector
import csv
import random
(2)构建headers请求头,用于提交请求内容。
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
"Cookie": "__mta=146634635.1712557172318.1712557192570.1712557204707.5; uuid_n_v=v1; "
"uuid=F54CCC50F56F11EE9F28D3BFFA06DA49EB5A95FF3CF14D26A4881C9771D506F6; "
"_csrf=4e4d27908ba0258010a72890e719979e54dc042f04e5f155711346c8ef8a7c2b; "
"_lxsdk_cuid=18ebc5ca1dec8-01a6116ca7d783-26001a51-1fa400-18ebc5ca1dec8; "
"_lxsdk=F54CCC50F56F11EE9F28D3BFFA06DA49EB5A95FF3CF14D26A4881C9771D506F6; "
"Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1712557172; "
"__mta=146634635.1712557172318.1712557175625.1712557183386.3; "
"Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1712557205; _lxsdk_s=18ebc5ca1de-6a5-12b-0f6%7C%7C10",
"Host": "www.maoyan.com"
}
(3)创建get_rseponse
函数,用于获取网页内容。
def get_rseponse(url):
resp = requests.get(url=url, headers=headers)
return resp.content.decode()
(4)创建parse
函数,用于获取网页内容,并存储到csv文件中。
def parse(response, writer):
selector = Selector(response)
dd_list = selector.xpath("//dl[@class='board-wrapper']/dd")
for dd in dd_list:
title = dd.xpath("./a/@title").get()
star_ = dd.xpath(".//p[@class='star']/text()").get()
star = star_.split(":")[1].strip()
time_ = dd.xpath(".//p[@class='releasetime']/text()").get()
time = time_.split("上映时间:")[1]
score_ = dd.xpath(".//p[@class='score']//i/text()").getall()
score = "".join(score_)
print(title, star, time, score)
writer.writerow([title, star, time, score])
(5)创建main函数,用于循环执行网页页面的获取。
def main():
file = open("猫眼榜单Top100.csv", "a", encoding="utf-8", newline="")
writer = csv.writer(file)
writer.writerow(["标题", "主演", "上映时间", "评分"])
for page in range(0, 100, 10):
url = f"https://www.maoyan.com/board/4?timeStamp={int(time.time() * 1000)}&" \
f"channelId=40011&index=10&signKey=d4d37de466ea172ad50776cea0b81e4d&sVersion=1&webdriver=false&offset={page}"
response = get_rseponse(url)
parse(response, writer)
time.sleep(random.randint(1, 3))
(6)最后在外部调用main
函数,用于启动执行整个项目。
if __name__ == '__main__':
main()
(7)执行完成后会生成一个猫眼榜单Top100.csv
文件
运行结果:
猫眼榜单Top100.csv
文件:
文件大致内容:
辅助文档
项目完成后,可参考辅助文档
创建Demo目录用于存储下载训练代码
输入目录名称Demo,回车完成创建。
下载ShiCiMingJu.py
训练代码
wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/ShiCiMingJu.py
复制到Demo项目目录下
cp ShiCiMingJu.py ~/PycharmProjects/spider_project/Demo/
下载lianjia.py
训练代码
wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/lianjia.py
复制到Demo项目目录下
cp lianjia.py ~/PycharmProjects/spider_project/Demo/
下载MaoYanTop100.py
训练代码
wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/MaoYanTop100.py
复制到Demo项目目录下
cp MaoYanTop100.py ~/PycharmProjects/spider_project/Demo/
CiMingJu.py ~/PycharmProjects/spider_project/Demo/
[外链图片转存中...(img-7A8KCUiL-1742113008771)]
下载`lianjia.py`训练代码
```python
wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/lianjia.py
[外链图片转存中…(img-83jur4Hp-1742113008771)]
复制到Demo项目目录下
cp lianjia.py ~/PycharmProjects/spider_project/Demo/
[外链图片转存中…(img-wbNez4ZT-1742113008771)]
下载MaoYanTop100.py
训练代码
wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/MaoYanTop100.py
[外链图片转存中…(img-IgkIu79F-1742113008771)]
复制到Demo项目目录下
cp MaoYanTop100.py ~/PycharmProjects/spider_project/Demo/