多网爬虫项目

多网爬虫项目

项目背景

大数据、人工智能技术飞速发展,数据是大数据和人工智能的基础,如何从互联网上获取数据是我们大数据和人工智能企业的一大难题。通常企业会通过爬虫从互联网上获取其想要的数据,本项目就是从多个网站通过爬虫去获取数据。

项目概述

项目简介

在各大公司开发平台中,或多或少都要用到从其他网站平台中获取对应的数据来做数据分析、处理等等,那么对于其他网站平台中的数据需要做相关的数据采集操作,并用于对公司相关的项目研发。那么则需要在互联网中获取数据。

而互联网是由一个个站点和网络设备组成的大网,我们通过浏览器访问站点,站点把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

软件清单

产品版本号功能描述
parsellatest基于lxml构建的高效网页解析库,提供了强大而灵活的工具,用于解析HTML和XML文档。
requestslatest一个用于发送 HTTP 请求的流行 Python 库,可以完成多种 HTTP 请求操作。
fake-useragentlatest一个第三方Python库,用于生成随机的User-Agent标头。

项目开发

任务岗位详细说明交付标准
环境搭建python运维工程师python运维工程师在开发前与python爬虫工程师对接,了解项目所需环境,进行环境配置。配置环境时要避免重新安装、版本不兼容、更换版本等问题产生,保证开发过程的顺畅。配置完成并通过测试后,对接给python爬虫工程师各组件测试可正常运行
诗词名句多线程爬取python爬虫工程师python爬虫工程师从公司部门主管处获取任务书,了解任务详情和开发内容要求后,首先梳理整体的项目逻辑,然后根据需求设计项目模块,并确定各个模块需具备的功能及相互之间的联系。从网络运维工程师那里获取到开发环境后,进行实际开发工作项目文件格式准确;采集内容准确,代码梳理清楚
北京链家二手房多线程爬取python爬虫工程师python爬虫工程师从公司部门主管处获取任务书,了解任务详情和开发内容要求后,首先梳理整体的项目逻辑,然后根据需求设计项目模块,并确定各个模块需具备的功能及相互之间的联系。从网络运维工程师那里获取到开发环境后,进行实际开发工作项目文件格式准确;采集内容准确,代码梳理清楚
爬取猫眼电影top100python爬虫工程师python爬虫工程师从公司部门主管处获取任务书,了解任务详情和开发内容要求后,首先梳理整体的项目逻辑,然后根据需求设计项目模块,并确定各个模块需具备的功能及相互之间的联系。从网络运维工程师那里获取到开发环境后,进行实际开发工作项目文件格式准确;采集内容准确,代码梳理清楚

任务一 环境搭建

任务场景

python运维工程师在开发前与python爬虫工程师对接,了解项目所需环境,进行环境配置。配置环境时要避免重新安装、版本不兼容、更换版本等问题产生,保证开发过程的顺畅。配置完成并通过测试后,对接给python爬虫工程师。

1.1 安装parsel

parsel是一个基于lxml构建的高效网页解析库,专为Python开发者设计,提供了强大而灵活的工具,用于解析HTML和XML文档。

pip install parsel

image-20240408151052023

1.2 安装requests

requests是一个用于发送 HTTP 请求的流行 Python 库。

pip install requests
# 因为该环境中已经自带了requests库,会提示以下内容,所以可以不用安装

image-20240415153023816

1.3 安装fake_useragent

fake_useragent是一个Python库,用于生成随机的User-Agent标头。

pip install fake_useragent

image-20240408174937856

1.4 启动pycharm并创建项目文件

①、双击桌面的【Pycharm】开发者工具,勾选【同意协议】选款,点击【continue】继续:

image-20240403162501336

②、在欢迎界面,点击【New Project】创建新的项目:

image-20240403162801169

③、为项目命名为spider_project(名称可自定义),选择python解释器版本完成创建:

image-20240409093203007

④、将弹出的每日更新【Tip of the day】点击【Close】关闭即可。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

任务二 诗词名句多线程爬取

2.1 创建ShiCiMingJu.py爬虫文件

在项目名称上右击鼠标,依次选择【New】,【Python file】:

image-20240409093424715

输入代码文件名称ShiCiMingJu(名称可自定义),点击回车完成创建。

image-20240408151751708

此时创建完成:

image-20240409093510982

2.2 实现思路

(1)导入需要的包

import requests
from queue import Queue
from parsel import Selector
import math
from concurrent.futures import ThreadPoolExecutor

image-20240408151947520

(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'}

image-20240408155736816

(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)

image-20240408155744992

(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)

image-20240408155757546

(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

image-20240520174113903

(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

image-20240520174753953

(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")

image-20240520174729915

(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)

image-20240520174810086

(9)在SCMJ类中创建run函数,用于执行上述创建的函数,以及将队列中的内容使用多线程获取数据

def run(self):
    # 将url入队列
    self.get_url()
    # self.parse()
    loop = ThreadPoolExecutor()
    for _ in range(1):
        loop.submit(self.parse)

image-20240520174821537

(10)最后在外部初始化实例对象SCMJ类,用于启动执行我们创建SCMJ类中的run函数。

if __name__ == '__main__':
    spider = SCMJ()
    spider.run()
    

image-20240520174832314

(11)执行完成后会生成一个shicimingju.txt文件

执行结果:

image-20240408160000098

shicimingju.txt文件:

image-20240520175431639

文件大致内容:

image-20240520175520523

任务三 北京链家二手房多线程爬取

3.1 创建lianjia.py爬虫文件

在项目名称上右击鼠标,依次选择【New】,【Python file】:

image-20240409093748041

输入代码文件名称lianjia(名称可自定义),点击回车完成创建。

image-20240408163505073

此时创建完成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

image-20240408175342960

(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 = ""

image-20240523094944339

(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

image-20240523094958522

(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)

image-20240523095012874

(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

image-20240523095225005

(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)

image-20240523095259351

(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)

image-20240523095331163

(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']])

image-20240523095349360

(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())]

image-20240523095701278

(11)执行完成后会生成一个bj.csv文件

运行结果:

image-20240409095235433

bj.csv文件:

image-20240520175704421

文件大致内容:

image-20240408180124352

任务四 爬取猫眼电影top100

4.1 创建猫眼电影Top100.py爬虫文件

在项目名称上右击鼠标,依次选择【New】,【Python file】:

image-20240409093748041

输入代码文件名称MaoYanTop100(名称可自定义),点击回车完成创建。

image-20240521092324149

此时创建完成:

image-20240521092727798

4.2 实现思路

(1)导入需要的包

import requests
import time
from parsel import Selector
import csv
import random

image-20240409100057913

(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"
}

image-20240409100941868

(3)创建get_rseponse函数,用于获取网页内容。

def get_rseponse(url):
    resp = requests.get(url=url, headers=headers)
    return resp.content.decode()

image-20240409101048886

(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])

image-20240409101120431

(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))

image-20240409101236752

(6)最后在外部调用main函数,用于启动执行整个项目。

if __name__ == '__main__':
    main()

image-20240409102310044

(7)执行完成后会生成一个猫眼榜单Top100.csv文件

运行结果:

image-20240409102505701

猫眼榜单Top100.csv文件:

image-20240521092515583

文件大致内容:

image-20240409102552664

辅助文档

项目完成后,可参考辅助文档

创建Demo目录用于存储下载训练代码

image-20240415160038849

输入目录名称Demo,回车完成创建。

image-20240415160052696

下载ShiCiMingJu.py训练代码

wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/ShiCiMingJu.py

image-20240415160415491

复制到Demo项目目录下

cp ShiCiMingJu.py ~/PycharmProjects/spider_project/Demo/

image-20240415160509121

下载lianjia.py训练代码

wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/lianjia.py

image-20240520170842632

复制到Demo项目目录下

cp lianjia.py ~/PycharmProjects/spider_project/Demo/

image-20240520171158959

下载MaoYanTop100.py训练代码

wget res.zhonghui.vip/python-2/duowang_spider_project/duowang_spider_project_code/MaoYanTop100.py

image-20240415160903923

复制到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/

image-20240415160930219

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值