新发地数据爬虫

北京新发地数据 新发地-价格行情 (xinfadi.com.cn)

适合新手爬 练习线程池

1. 请求网页

抓包

网页是动态渲染的 没法直接从源码里解析

所以我们要用抓包软件抓到他的XHR请求

非常轻松的就抓到了

可以看到他的请求url是 http://xinfadi.com.cn/getPriceData.html

请求方式是POST

2.jpg
2.jpg

点了第三页抓到发送的数据 中current变成了3

所以待会换页就修改current就可以了

3.jpg
3.jpg

查看返回的数据可以看出返回的json数据

那就很简单了


代码实例

已知这些就可以开始写代码了

import requests

url = 'http://xinfadi.com.cn/getPriceData.html'

header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60"
}

def postHtml(url, data, header):
    resp = requests.post(url, data=data, headers=header)
    return resp.json()

创建postHtml函数

发送post请求 1

将获取到了resp转换成json格式数据

2. 处理json数据

查看获取到的json数据

{
    "current": 1,
    "limit": 20,
    "count": 543249,
    "list": [
        {
            "id": 1517943,
            "prodName": "大白菜",
            "prodCatid": 1186,
            "prodCat": "蔬菜",
            "prodPcatid": null,
            "prodPcat": "",
            "lowPrice": "0.35",
            "highPrice": "0.5",
            "avgPrice": "0.43",
            "place": "冀晋",
            "specInfo": "",
            "unitInfo": "斤",
            "pubDate": "2023-10-18 00:00:00",
            "status": null,
            "userIdCreate": 138,
            "userIdModified": null,
            "userCreate": "admin",
            "userModified": null,
            "gmtCreate": null,
            "gmtModified": null
            # 部分数据
        } 
    ]
}

我们需要将获取到的数据存储到CSV


代码

先写出我们需要的数据的头

csvTitle = ["一级分类", '品名', '最低价', "平均价", "最高价", "规格", "产地", "单位", "发布日期"]
import csv

def parseData(jsonData):
    jsonD = jsonData['list']
    for i in jsonD:
        tmpRow = [i["prodCat"], i["prodName"], i["lowPrice"], i["highPrice"], i["avgPrice"], i["specInfo"], i["place"],i["unitInfo"], i["pubDate"]]
        csvWriter.writerow(tmpRow)

将我们需要的数据获取下来 存到tmpRow 作为一行数据 然后写入csv文件

3. 线程池

def fetch_and_parse_data(data):
    jsonData = postHtml(url, data, header)
    parseData(jsonData)

创建用于线程池的函数 在里面调用其他函数

with ThreadPoolExecutor(100) as t:
        for i in range(1, 200):  # 总共27028页   全爬太慢了
            data = {
                "limit": "20",
                "current": f"{i}",
                "pubDateStartTime": "",
                "pubDateEndTime": "",
                "prodPcatid": "",
                "prodCatid": "",
                "prodName": ""
            }
            t.submit(fetch_and_parse_data, data)

创建 线程池任务 data中current跟着range()的数字走

总共有27028页 全部爬的话 即便线程池也很慢

我们这里只爬前200页

最后的运行啦

import csv
fileData = open('data.csv', 'w', encoding='utf-8', newline="")
csvWriter = csv.writer(fileData)
csvWriter.writerow(csvTitle)

打开data.csv没有则创建, 编码为utf-8 newline=""是不换行

先把csv的title写入文件


import requests
import csv
from concurrent.futures import ThreadPoolExecutor

header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60"
}

url = 'http://xinfadi.com.cn/getPriceData.html'

csvTitle = ["一级分类", '品名', '最低价', "平均价", "最高价", "规格", "产地", "单位", "发布日期"]


def postHtml(url, data, header):
    resp = requests.post(url, data=data, headers=header)
    return resp.json()


def parseData(jsonData):
    jsonD = jsonData['list']
    for i in jsonD:
        tmpRow = [i["prodCat"], i["prodName"], i["lowPrice"], i["highPrice"], i["avgPrice"], i["specInfo"], i["place"],
                  i["unitInfo"], i["pubDate"]]
        csvWriter.writerow(tmpRow)


def fetch_and_parse_data(data):
    jsonData = postHtml(url, data, header)
    parseData(jsonData)


if __name__ == '__main__':
    fileData = open('data.csv', 'w', encoding='utf-8', newline="")
    csvWriter = csv.writer(fileData)
    csvWriter.writerow(csvTitle)

    # 线程池
    with ThreadPoolExecutor(100) as t:
        for i in range(1, 200):  # 总共27028页   全爬太慢了
            data = {
                "limit": "20",
                "current": f"{i}",
                "pubDateStartTime": "",
                "pubDateEndTime": "",
                "prodPcatid": "",
                "prodCatid": "",
                "prodName": ""
            }
            t.submit(fetch_and_parse_data, data)

            print(data["current"], "下载完毕")

这里是完整代码

程序也是非常不错的运行了下来~


  1. data内容在下面写出