python爬虫


查看解析html查找API



其实我们发现这就是一条json语句


去除头部和尾部就是一条json文件,解析json文件即可

Scrapy

Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。 Scrapy常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。 通常我们可以很简单的通过Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片。

1、架构图


Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler 中间的通讯,信号、数据传递等。
Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider 来处理,
Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器).
Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。
Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从 Spider出去的Requests)

2、Scrapy的运作流程

代码写好,程序开始运行...
1 引擎:Hi!Spider, 你要处理哪一个网站?
2 Spider:老大要我处理xxxx.com。
3 引擎:你把第一个需要处理的URL给我吧。
4 Spider:给你,第一个URL是xxxxxxx.com。
5 引擎:Hi!调度器,我这有request请求你帮我排序入队一下。
6 调度器:好的,正在处理你等一下。
7 引擎:Hi!调度器,把你处理好的request请求给我。
8 调度器:给你,这是我处理好的request
9 引擎:Hi!下载器,你按照老大的下载中间件的设置帮我下载一下这个 request请求
10 下载器:好的!给你,这是下载好的东西。(如果失败:sorry,这个 request下载失败了。然后引擎告诉调度器,这个request下载失败了,你记录一 下,我们待会儿再下载)
11 引擎:Hi!Spider,这是下载好的东西,并且已经按照老大的下载中间件处理过了,你自己处理一下(注意!这儿responses默认是交给def parse()这个函数处理的)
12 Spider:(处理完毕数据之后对于需要跟进的URL),Hi!引擎,我这里有 两个结果,这个是我需要跟进的URL,还有这个是我获取到的Item数据。
13 引擎:Hi !管道 我这儿有个item你帮我处理一下!调度器!这是需要跟进 URL你帮我处理下。然后从第四步开始循环,直到获取完老大需要全部信息。
14 管道调度器:好的,现在就做!
注意!只有当调度器中不存在任何request了,整个程序才会停止,(也就是说,对于下载 失败的
URL,Scrapy也会重新下载。)

3、制作Scrapy爬虫步骤

1、安装Scrapy框架


2、使用startproject命令,快速构建scrapy项目


3、爬取百度首页

import scrapy

class BaiduDemo(scrapy.Spider):
    # 爬虫的名称 用于启动爬虫
    name = 'BaiduDemo'
    # 设置允许爬取的域名
    allowed_domains = ['baidu.com']
    # 启动的url
    start_urls = ['http://www.baidu.com']

    # 解析函数
    def parse(self, response):
        print(response.text)


4、爬取京东商品评论导入数据库

爬取数据




代码

import scrapy

class JDCommentsSpider(scrapy.Spider):
    name = 'JDCommentsSpider'
    allowed_domains = ['jd.com']

    # 设定请求头 伪装成浏览器
    headers = {
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
    }

    # start_urls = ['https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1']
    # 手动的发起请求
    def start_requests(self):
        url = 'https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'
        # header 请求头
        # callback 回调函数 :设置由哪个函数去解析response
        yield scrapy.Request(url=url, headers=self.headers, callback=self.parseComment)
        
    def parseComment(self, response):
        print(response.text)

解析数据

解析思路((fetchJSON_comment98()({.*})()😉),通过使用正则表达式获取中间的json格式内容

import re
import json

# (fetchJSON_comment98\()({.*})(\);)
json_str1 = r'fetchJSON_comment98({"jwotestProduct":null,"score":0,"comments":[{"id":16704617220,"guid":"573c70c3703d3ee1d6745412533c59bf","content":"外形外观:直角边框经典设计,手感非常好。不锈钢边框很有质感\n屏幕音效:iPhone屏"}]});'
groups = re.match(r"(fetchJSON_comment98\()(.*)(\);)", json_str1)
# 返回正则表达式匹配到的整行数据
print(groups.group(0))
print(groups.group(1))
print(groups.group(2))
print(groups.group(3))

# jsonObj = json.loads(groups.group(2))
# print(jsonObj)
# print(type(jsonObj))

str1 = r'abc\tefg'
print(str1)

从爬取数据中获取json

import scrapy
import re
import json

class JDCommentsSpider(scrapy.Spider):
    name = 'JDCommentsSpider'
    allowed_domains = ['jd.com']

    # 设定请求头 伪装成浏览器
    headers = {
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
    }

    # start_urls = ['https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1']
    # 手动的发起请求
    def start_requests(self):
        url = 'https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'
        # header 请求头
        # callback 回调函数 :设置由哪个函数去解析response
        yield scrapy.Request(url=url, headers=self.headers, callback=self.parseComment)

    def parseComment(self, response):
        # print(response.text)
        json_str = re.match(r"(fetchJSON_comment98\()(.*)(\);)", response.text).group(2)
        print(json_str)
        commentDict = json.loads(json_str)
        print(commentDict)

#明确爬取目标的格式
class CommentItem(scrapy.Item):
    id = scrapy.Field()
    content = scrapy.Field()
    creationTime = scrapy.Field()
    score = scrapy.Field()
    nickname = scrapy.Field()

import scrapy
import re
import json
from ..items import CommentItem

class JDCommentsSpider(scrapy.Spider):
    name = 'JDCommentsSpider'
    allowed_domains = ['jd.com']

    # 设定请求头 伪装成浏览器
    headers = {
        'Accept': '*/*',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
        'Connection': 'keep-alive',
        'Cookie': 'shshshfpb=f3W7aXOimfXUdxcnPVcp8lg%3D%3D; shshshfpa=dd3e618e-7824-e463-e953-735fb2491a30-1572581065; __jdu=15945342777701271159704; user-key=0f674e76-283e-4314-878d-e20485b0bdf9; __jdv=76161171|direct|-|none|-|1639622083019; areaId=14; PCSYCityID=CN_340000_340100_0; ipLoc-djd=14-1116-3431-57939; jwotest_product=99; __jda=122270672.15945342777701271159704.1594534278.1639635327.1639703524.27; __jdc=122270672; token=d580f8297475335873c53a0ca9a442ab,2,910946; __tk=WkaFSLmLVcaCiAeFTLfKVkuCVUvJWceAiDl3iLl2Tce,2,910946; shshshfp=e39a2aab2d64e3d87934802270acb44f; ip_cityCode=1116; shshshsID=92d1c2eec0e0061568b20502af8aa0fb_4_1639703565703; __jdb=122270672.5.15945342777701271159704|27.1639703524; JSESSIONID=4C9F7710F36CC25E02E63C1F6D8706AD.s1; 3AB9D23F7A4B3C9B=PFFHAXCONWJKWHSOLBIBQWHWZCSNLF65GANEXSUBWYJQK3UFYOGIH3BMJJ56DKIL2GTESYLRTXH2CLWABB7Z37WOSY',
        'Host': 'club.jd.com',
        'Referer': 'https://item.jd.com/',
        'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'Sec-Fetch-Dest': 'script',
        'Sec-Fetch-Mode': 'no-cors',
        'Sec-Fetch-Site': 'same-site',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
    }

    # start_urls = ['https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1']
    # 手动的发起请求
    def start_requests(self):
        url = 'https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'
        # header 请求头
        # callback 回调函数 :设置由哪个函数去解析response
        for i in range(80):
            url = url.format(i)
            # headers 请求头
            # callback 回调函数:设置由哪个函数去解析response
            yield scrapy.Request(url=url, headers=self.headers, callback=self.parseComment)

    def parseComment(self, response):
        # print(response.text)
        json_str = re.match(r"(fetchJSON_comment98\()(.*)(\);)", response.text).group(2)
        print(json_str)
        commentDict = json.loads(json_str)
        # print(commentDict)
        #解析数据
        comments = commentDict.get('comments',None)
        if comments is not None:
            for comment in comments:
                #从response中解析数据并构建Item对象
                commentItem = CommentItem()
                commentItem['id'] = comment['id']
                commentItem['content'] = comment['content']
                commentItem['creationTime'] = comment['creationTime']
                commentItem['score'] = comment['score']
                commentItem['nickname'] = comment['nickname']
                #将遍历好的Item对象发送给piepline做后续处理
                yield commentItem

写入到MySQL

在MySQL新建数据库和字段

在pipelines.py写代码
import pymysql
class ScrapydemoPipeline:
    #初始化连接MySQL数据库
    def open_spider(self,spider):
        self.conn = pymysql.connect(user='root',passwd='123456',host='master',port=3306,db='spiders')

    def process_item(self, item, spider):
        #写入mysql
        id = item['id']
        content = item['content']
        creationTime = item['creationTime']
        score = item['score']
        nickname = item['nickname']
        #创建游标
        try:
            print("*************")
            with self.conn.cursor() as cursor:
                cursor.execute('insert into comments values(%s,%s,%s,%s,%s)',(id,nickname,score,creationTime,content))
        except Exception as e:
            print(e)
            #发生异常进行回滚
            self.conn.rollback()
        else:
            #没有异常就提交写入的数据
            self.conn.commit()
        return item
    #关闭数据库
    def close_spider(self,spider):
        self.conn.close()


爬取多页评论写入MySQL

先清空表中数据
设置停歇访问,以免被拦截

  # start_urls = ['https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1']
    # 手动的发起请求
    def start_requests(self):
        url_format = 'https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100014352539&score=0&sortType=5&page={}&pageSize=10&isShadowSku=0&fold=1'
        # header 请求头
        # callback 回调函数 :设置由哪个函数去解析response
        for i in range(80):
            url = url_format.format(i)
            # headers 请求头
            print(url_format)
            # callback 回调函数:设置由哪个函数去解析response
            yield scrapy.Request(url=url, headers=self.headers, callback=self.parseComment)



免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM