python爬虫入门(5)----- 阿里巴巴供应商爬虫

阿里巴巴供应商爬虫

起因

学了爬虫入门之后,打算找一个有难度的网站来实践,一开始打算找淘宝或者天猫(业界老大)来实践,但后续发现网上已经有很多这方面的项目,于是瞄上了阿里的国际网站阿里巴巴。开始一切顺利,没发现什么难度,后面发现供应商的联系方式需要登录,于是以其为目标开始写爬虫。

网站结构

1.阿里巴巴有个供应商分类的页面
https://www.alibaba.com/companies

2.点进去之后有个二级分类

3.再点进去就可以找到这个分类下的所有供应商

4.再进去就可以找供应商的联系方式了

5.这时要获取联系方式就需要登录

爬虫思路

1.先从供应商分类页面开始爬取,获取到所有的供应商联系方式的页面(即上面网站结构的第4步)存入数据库
2.编写另一个爬虫从数据库拿到联系方式页面,再用selenium登录获取联系方式(这一步是取巧了,但也导致爬取速度直线下降)

代码结构

#scrapy的代码结构
alibaba
    -spider
        --company.py #获取供应商联系方式页面
        --contact.py #获取联系方式的页面
    -items
    -middlewares.py
    -pipelines.py
    -setting.py

company.py

class CompanySpider(scrapy.Spider):
name = 'company'
allowed_domains = ['www.alibaba.com']
start_urls = ['https://www.alibaba.com/companies']

# 爬取大的分类信息
def parse(self, response):
    categorys = response.css(".ui-box.ui-box-normal.ui-box-wrap.clearfix .g-cate-list dl dt a")
    for cat in categorys:
        name = cat.css("::text").extract_first()
        url = cat.css("::attr(href)").extract_first()
        yield scrapy.Request(url, callback=self.parseCategory, meta={'cat': name})
    pass

# 爬取详细分类信息
def parseCategory(self, response):
    cat = response.meta['cat']
    ccats = response.css("#category-main-box .g-float-left>ul>li>a")
    for ccat in ccats:
        name = ccat.css("::text").extract_first()
        url = ccat.css("::attr(href)").extract_first()
        ccat_url = urljoin(self.start_urls[0], url)
        yield scrapy.Request(ccat_url, callback=self.parseCompany, meta={'ccat': name, 'cat': cat})
    pass

def parseCompany(self, response):
    cat = response.meta['cat']
    ccat = response.meta['ccat']

    # 爬取下一页
    next_url = response.css(".next::attr(href)").extract_first()
    if (next_url):
        yield scrapy.Request(urljoin(response.url, next_url), callback=self.parseCompany, meta={'cat': cat, 'ccat': ccat})

    # 爬取公司信息
    items = response.css(".item-main")
    for item in items:
        company = CompanyItem()
        title = item.css(".item-title .title.ellipsis a")
        company["name"] = title.css("::text").extract_first().strip()
        url = title.css("::attr(href)").extract_first()
        url = url.rpartition("/")[0]
        company["url"] = url
        attrs = item.css(".content.util-clearfix .right .attr")
        for attr in attrs:
            name = attr.css(".name::text").extract_first()
            value = attr.css(".value")
            if name == 'Main Products:':
                mainProducts = value.css("::text").extract_first()
                company["mainProducts"] = mainProducts
            elif name == "Country/Region:":
                region = value.css(".ellipsis.search::text").extract_first()
                company["region"] = region
            elif name == "Total Revenue:":
                totalRevenue = value.css(".ellipsis.search::text").extract_first()
                company["totalRevenue"] = totalRevenue
            elif name == "Top 3 Markets:":
                top3 = value.css(".ellipsis.search::text").extract()
                company["top3Markets"] = ",".join(top3)
        company["ccat"] = ccat
        company["cat"] = cat
        yield company
    pass

contact.py

class ContactSpider(scrapy.Spider):
name = 'contact'
allowed_domains = ['www.alibaba.com']
start_urls = []

count = 1000

def __init__(self):
    # selenium
    # options = Options()
    # prefs = {"profile.managed_default_content_settings.images": 2}
    # options.add_experimental_option("prefs", prefs)
    # options.headless = True
    # driver_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+"\chromedriver.exe"
    # print(driver_path)
    # 创建Firefox浏览器的一个Options实例对象
    profile = webdriver.FirefoxProfile()
    # 禁用CSS加载
    profile.set_preference('permissions.default.stylesheet', 2)
    # 禁用images加载
    profile.set_preference('permissions.default.image', 2)
    # 禁用flash插件
    fireFoxOptions = webdriver.FirefoxOptions()
    fireFoxOptions.headless = True
    profile.set_preference('dom.ipc.plugins.enabled.libflashplayer.so', False)
    self.browser = webdriver.Firefox(executable_path=settings.FIREFOX_WEBDRIVER_PATH,
                                     firefox_profile=profile, firefox_options=fireFoxOptions)
    # mysql
    self.client = pymysql.connect(
        host=settings.MYSQL_HOST,
        db=settings.MYSQL_DBNAME,
        user=settings.MYSQL_USER,
        passwd=settings.MYSQL_PASSWD,
        charset='utf8'
    )
    self.cur = self.client.cursor()
    # startUrls
    sql = "select id,url from disct_company where id <= {} and id > {}".format(settings.END, settings.START)
    try:
        self.cur.execute(sql)
        results = self.cur.fetchall()
        for url in results:
            id = url[0]
            contact_url = url[1]  # type: str
            if not (contact_url.startswith("http:") or contact_url.startswith("https:")):
                contact_url = "https:" + contact_url
            if not (contact_url.endswith("/")):
                contact_url += "/"
            contact_url += ("contactinfo.html?%d" % (id))
            self.start_urls.append(contact_url)
    except Exception as error:
        logging.error("contact spider init err:{}".format(error))
    # 关闭资源
    dispatcher.connect(receiver=self.spiderCloseHandler, signal=signals.spider_closed)

def spiderCloseHandler(self, spider):
    self.browser.quit()
    self.cur.close()
    self.client.close()

def parse(self, response):
    id = response.meta.get("id")
    item = ContactItem()
    item['id'] = id
    name = response.css(".contact-name::text").extract_first()
    if not name:
        name = response.css(".contact-info .name::text").extract_first()
        if name:
            name = name.strip()
    item['name'] = name
    department = response.css(".contact-department::text").extract_first()
    job = response.css(".contact-job::text").extract_first()
    if not (department and job):
        dds = response.css(".contact-info .dl-horizontal dd::text")
        dts = response.css(".contact-info .dl-horizontal dt::text")
        if dds:
            for i in range(len(dds)):
                dd = dds[i].extract()
                dt = dts[i].extract()
                if dt == 'Department:':
                    department = dd
                elif dt == 'Job Title:':
                    job = dd
    item['department'] = department
    item['job'] = job
    info_table = response.css(".info-table tr")
    if info_table:
        for info in info_table:
            th = info.css("th::text").extract_first()
            td = info.css("td::text").extract_first()
            if th == 'Telephone:':
                item['telephone'] = td
            elif th == 'Mobile Phone:':
                item['mobilePhone'] = td
            elif th == 'Fax:':
                item['fax'] = td
            elif th == 'Address:':
                item['address'] = td
            elif th == 'Zip:':
                item['zip'] = td
            elif th == 'Country/Region:':
                item['country'] = td
            elif th == 'Province/State:':
                item['province'] = td
            elif th == 'City:':
                item['city'] = td
    else:
        item['telephone'] = response.css(
            ".contact-detail .sensitive-info .dl-horizontal dd[data-role=phone]::text").extract_first()
        item['mobilePhone'] = response.css(
            ".contact-detail .sensitive-info .dl-horizontal dd[data-role=mobile]::text").extract_first()
        item['fax'] = response.css(
            ".contact-detail .sensitive-info .dl-horizontal dd[data-role=fax]::text").extract_first()
        dds = response.css(".contact-detail .public-info .dl-horizontal dd::text").extract()
        dts = response.css(".contact-detail .public-info .dl-horizontal dt::text").extract()
        for i in range(len(dts)):
            dt = dts[i]
            dd = dds[i]
            if dt == 'Address:':
                item['address'] = dd
            elif dt == 'Zip:':
                item['zip'] = dd
            elif dt == 'Country/Region:':
                item['country'] = dd
            elif dt == 'Province/State:':
                item['province'] = dd
            elif dt == 'City:':
                item['city'] = dd

    yield item

seleniumDownloaderMiddleware

class SeleniumDownloaderMiddleware(object):

def process_request(self, request, spider):
    if spider.name == 'contact':
        try:
            url = request.url
            spider.browser.get(url)
            time.sleep(1)
            if self.is_element_exist(".sens-mask .icbu-link-default", spider.browser):
                viewButton = spider.browser.find_element_by_css_selector(".sens-mask .icbu-link-default")
            elif self.is_element_exist(".contact-detail-mask .view-contact-trigger", spider.browser):
                viewButton = spider.browser.find_element_by_css_selector(".contact-detail-mask .view-contact-trigger")
            if viewButton:
                spider.browser.execute_script("arguments[0].click();", viewButton)
            # spider.browser.execute_script("arguments[0].scrollIntoView();", viewButton)
            time.sleep(2)
            if self.is_element_exist(".sc-hd-prefix2-dialog-bd", spider.browser):
                spider.browser.execute_script("arguments[0].click();", spider.browser.find_element_by_css_selector(".sc-hd-prefix2-tab-trigger"))
                time.sleep(1)
                spider.browser.switch_to.frame("alibaba-login-box")
                spider.browser.find_element_by_id("fm-login-id").send_keys("your username")
                time.sleep(1)
                spider.browser.find_element_by_id("fm-login-password").send_keys("your password")
                time.sleep(1)
                # submit = spider.browser.find_element_by_id("fm-login-submit")
                spider.browser.execute_script("document.getElementById('fm-login-submit').click();")
                # spider.browser.execute_script("arguments[0].scrollIntoView();", submit)
                # submit.click()
                time.sleep(5)
                spider.browser.switch_to.default_content()
        except Exception as error:
            logging.error("{} err:{}".format(url, error))
        return HtmlResponse(spider.browser.current_url, body=spider.browser.page_source, encoding='utf-8',
                            request=request)
    return None

def is_element_exist(self, css, browser):
    s = browser.find_elements_by_css_selector(css_selector=css)
    if len(s) == 0:
        return False
    elif len(s) == 1:
        return True
    else:
        return False

项目地址

项目已上传github:https://github.com/shuo123/alibabaSpider

原文地址:https://www.cnblogs.com/wuweishuo/p/10606577.html

时间: 2024-10-06 16:16:16

python爬虫入门(5)----- 阿里巴巴供应商爬虫的相关文章

4.Python爬虫入门之二之爬虫基础了解

1.什么是爬虫 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一只蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛,如果它遇到资源,那么它就会抓取下来.想抓取什么,就靠你自己去控制它. 比如它在抓取一个网页,在这个网中它发现了一条道路,其实就是指向网页的超链接,那么它就可以爬虫另一张网上来获取数据.这样,整个连在一起的大网对这只蜘蛛来说触手可及,爬下来都不是什么难事. 2.浏览网页的过程 在用户浏览网页的过程中,我们可能会看到许多好多的照片,比如 http://image.baid

爬虫入门-5-1.正则表达式在爬虫中的应用

1.爬取百思不得姐段子 1 import requests 2 import re 3 4 5 def parse_url(url): 6 headers = { 7 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' 8 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36' 9 } 10 response = requests.ge

python爬虫入门01:教你在 Chrome 浏览器轻松抓包

通过 python爬虫入门:什么是爬虫,怎么玩爬虫? 我们知道了什么是爬虫 也知道了爬虫的具体流程 那么在我们要对某个网站进行爬取的时候 要对其数据进行分析 就要知道应该怎么请求 就要知道获取的数据是什么样的 所以我们要学会怎么抓咪咪! 哦,不对. 我们要学会怎么数据抓包   虽然小馒头也是包的一种 ok...anyway... 打开我们的 Chrome 浏览器 在这里 小帅b 提醒大家一句 尽量不要用国产浏览器 很多是有后门的 所以 Chrome 是首选! ok,打开 Chrome 浏览器之后

爬虫入门系列(三):用 requests 构建知乎 API

爬虫入门系列目录: 爬虫入门系列(一):快速理解HTTP协议 爬虫入门系列(二):优雅的HTTP库requests 爬虫入门系列(三):用 requests 构建知乎 API 在爬虫系列文章 优雅的HTTP库requests 中介绍了 requests 的使用方式,这一次我们用 requests 构建一个知乎 API,功能包括:私信发送.文章点赞.用户关注等,因为任何涉及用户操作的功能都需要登录后才操作,所以在阅读这篇文章前建议先了解Python模拟知乎登录.现在假设你已经知道如何用 reque

Python爬虫入门七之正则表达式

在前面我们已经搞定了怎样获取页面的内容,不过还差一步,这么多杂乱的代码夹杂文字我们怎样把它提取出来整理呢?下面就开始介绍一个十分强大的工具,正则表达式! 1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑. 正则表达式是用来匹配字符串非常强大的工具,在其他编程语言中同样有正则表达式的概念,Python同样不例外,利用了正则表达式,我

转 Python爬虫入门七之正则表达式

静觅 » Python爬虫入门七之正则表达式 1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. 正则表达式是用来匹配字符串非常强大的工具,在其他编程语言中同样有正则表达式的概念,Python同样不例外,利用了正则表达式,我们想要从返回的页面内容提取出我们想要的内容就易如反掌了. 正则表达式的大致匹配过程是:1.依次拿出表达式和文本中的字符比较,2.如果每一个

Python爬虫入门六之Cookie的使用

大家好哈,上一节我们研究了一下爬虫的异常处理问题,那么接下来我们一起来看一下Cookie的使用. 为什么要使用Cookie呢? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密) 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的.那么我们可以利用Urllib2库保存我们登录的Cookie,然后再抓取其他页面就达到目的了. 在此之前呢,我们必须先介绍一个opener的概念. 1.Opener 当你获取一个

(原)python爬虫入门(2)---排序爬取的辽宁科技大学热点新闻

发现科大网页的源码中还有文章的点击率,何不做一个文章点击率的降序排行.简单,前面入门(1)基本已经完成我们所要的功能了,本篇我们仅仅需要添加:一个通过正则获取文章点击率的数字:再加一个根据该数字的插入排序.ok,大功告成! 简单说一下本文插入排序的第一个循环,找到列表中最大的数,放到列表 0 的位置做观察哨. 上代码: # -*- coding: utf-8 -*- # 程序:爬取点击排名前十的科大热点新闻 # 版本:0.1 # 时间:2014.06.30 # 语言:python 2.7 #--

Python爬虫入门一之综述

首先爬虫是什么? 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本. 根据我的经验,要学习Python爬虫,我们要学习的共有以下几点: Python基础知识 Python中urllib和urllib2库的用法 Python正则表达式 Python爬虫框架Scrapy Python爬虫更高级的功能 1.Python基础学习 首先,我们要用Python写爬虫,肯定要了解Python的基础吧,万丈高楼平地起,