├── .circleci └── config.yml ├── .env.sample ├── .github └── dependabot.yml ├── .gitignore ├── .python-version ├── .rsync-filter ├── GNUmakefile ├── LICENSE ├── README.md ├── feedgen_hasname ├── __init__.py ├── asgi.py ├── settings.py ├── settings_dev.py ├── settings_test.py ├── urls.py └── wsgi.py ├── general ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── services │ ├── __init__.py │ ├── proxy_socks5_service.py │ └── requests_service.py ├── tests │ ├── __init__.py │ ├── html_bookwalker_lightnovel.txt │ ├── html_bookwalker_manga.txt │ ├── html_cakeresume.txt │ ├── html_dcard_board.txt │ ├── html_dcard_main.txt │ ├── html_job1111.txt │ ├── html_job518.txt │ ├── html_rent591.txt │ ├── html_taipeimetrotimetable.txt │ ├── html_youtube.txt │ ├── json_dcard_popular.txt │ ├── json_job104.txt │ ├── json_meetjobs.txt │ ├── json_momoshop.txt │ ├── json_pchome.txt │ ├── json_pchome_lightnovel.txt │ ├── json_plurk_search.txt │ ├── json_plurk_top_zh.txt │ ├── json_shopee.txt │ ├── json_yourator.txt │ ├── test_index.py │ ├── test_robotstxt.py │ └── test_smoke.py ├── urls.py └── views │ ├── __init__.py │ ├── bookwalker.py │ ├── cakeresume.py │ ├── dcard.py │ ├── index.py │ ├── job104.py │ ├── job1111.py │ ├── job518.py │ ├── meetjobs.py │ ├── momoshop.py │ ├── pchome.py │ ├── plurk.py │ ├── rent591.py │ ├── robotstxt.py │ ├── shopee.py │ ├── taipeimetrotimetable.py │ ├── yourator.py │ └── youtube.py ├── manage.py ├── pyproject.toml ├── uv.lock └── uwsgi.ini /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | jobs: 4 | test: 5 | docker: 6 | - image: python:3.13 7 | steps: 8 | - checkout 9 | - restore_cache: 10 | keys: 11 | - v1-deps-{{ checksum "uv.lock" }} 12 | - v1-deps 13 | - run: pip install -U pip uv 14 | - save_cache: 15 | key: v1-deps-{{ checksum "uv.lock" }} 16 | paths: 17 | - /home/circleci/.cache/pypoetry/virtualenvs 18 | - run: make test 19 | 20 | workflows: 21 | build_and_test: 22 | jobs: 23 | - test 24 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | SENTRY_DSN="" 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "pip" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.retry 2 | .coverage 3 | .dev.sqlite3 4 | .env 5 | .ruff_cache 6 | .venv 7 | GNUmakefile.local 8 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.13 2 | -------------------------------------------------------------------------------- /.rsync-filter: -------------------------------------------------------------------------------- 1 | - .git/ 2 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # 2 | -include GNUmakefile.local 3 | 4 | # 5 | .DEFAULT_GOAL:= rundev 6 | .PHONY: .env build rundev test 7 | 8 | .env:: 9 | test $(shell wc -l .env | cut -d ' ' -f 1) -eq $(shell wc -l .env.sample | cut -d ' ' -f 1) 10 | 11 | clean:: 12 | rm -f .coverage .dev.sqlite3 db.sqlite3 13 | 14 | deploy:: 15 | ifndef DEPLOY_HOST 16 | $(error $$DEPLOY_HOST is not defined in GNUmakefile.local) 17 | endif 18 | ifndef DEPLOY_USER 19 | $(error $$DEPLOY_USER is not defined in GNUmakefile.local) 20 | endif 21 | rsync \ 22 | -Favz \ 23 | --delete-after \ 24 | --exclude-from=.gitignore \ 25 | ./ \ 26 | ${DEPLOY_USER}@${DEPLOY_HOST}:~${DEPLOY_USER}/feedgen/ 27 | ssh ${DEPLOY_USER}@${DEPLOY_HOST} "systemctl --user restart feedgen.service" 28 | 29 | run:: 30 | pkill -QUIT uwsgi; sleep 1; uv run uwsgi --ini uwsgi.ini > /dev/null 2>&1 & 31 | 32 | rundev:: 33 | uv run ./manage.py runserver --settings=feedgen_hasname.settings_dev 34 | 35 | test:: 36 | uv run coverage run --source=. ./manage.py test --settings=feedgen_hasname.settings_test 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-2025 Gea-Suan Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # feedgen [![CircleCI](https://circleci.com/gh/hasname/feedgen.svg?style=svg)](https://circleci.com/gh/hasname/feedgen) 2 | 3 | Generate Atom feeds for sites which do not support feeds, mostly in Taiwan. 4 | 5 | ## Install 6 | 7 | You need to set up `.env` first. The sample environment file is in `.env.sample`. 8 | 9 | ## Run 10 | 11 | We use `uv` to manage the running environment along with `uwsgi` to run the uWSGI server, therefore you choose whatever you like to adopt these utilities. 12 | 13 | ## Development 14 | 15 | There are two commands in `GNUmakefile` to help you develop: 16 | 17 | make rundev 18 | make test 19 | 20 | ## Update 21 | 22 | For `GNUmakefile.local`, you can set something like this: 23 | 24 | # 25 | DEPLOY_HOST= server.example.com 26 | DEPLOY_USER= service-feedgen 27 | 28 | Then you can use `make deploy` to update the service. Scripts in `GNUmakefile` will call `rsync` to update code via SSH and re-run `uwsgi` services via userland systemd. 29 | 30 | ## Supporting platforms 31 | 32 | Recruting platform search systems (求職平台): 33 | * https://meet.jobs/ 34 | * https://www.104.com.tw/ 35 | * https://www.1111.com.tw/ 36 | * https://www.518.com.tw/ 37 | * https://www.cakeresume.com/ 38 | * https://www.yourator.co/ 39 | 40 | EC search systems (電子商務平台): 41 | * https://24h.pchome.com.tw/ (including other PChome's EC systems) 42 | * https://shopee.tw/ 43 | * https://www.momoshop.com.tw/ 44 | 45 | Housing platform (租屋平台): 46 | * https://rent.591.com.tw/ 47 | 48 | Social networks (社群平台): 49 | * https://www.dcard.tw/ (main section) 50 | * https://www.plurk.com/ (popular section) 51 | * https://www.youtube.com/ (search system) 52 | 53 | Others (其他): 54 | * https://24h.pchome.com.tw/books/store/?fq=/R/DJAZ/new 55 | * https://web.metro.taipei/img/ALL/timetables/079a.PDF (Taipei metro timetable) 56 | * https://www.bookwalker.com.tw/more/fiction/1/3 57 | 58 | ## Endpoint 59 | 60 | We have set up a public service since I use it and you can test it as well, but please set up your own service if you use it heavily. 61 | 62 | * https://feedgen.hasname.com/ 63 | 64 | ## Examples 65 | 66 | * https://feedgen.hasname.com/104/devops 67 | * https://feedgen.hasname.com/104company/devops 68 | * https://feedgen.hasname.com/1111/devops 69 | * https://feedgen.hasname.com/518/devops 70 | * https://feedgen.hasname.com/bookwalker-lightnovel 71 | * https://feedgen.hasname.com/bookwalker-manga 72 | * https://feedgen.hasname.com/cakeresume/devops 73 | * https://feedgen.hasname.com/dcard/board/mood 74 | * https://feedgen.hasname.com/dcard/main 75 | * https://feedgen.hasname.com/meetjobs/test 76 | * https://feedgen.hasname.com/momoshop/測試 77 | * https://feedgen.hasname.com/pchome-lightnovel 78 | * https://feedgen.hasname.com/pchome/測試 79 | * https://feedgen.hasname.com/plurk/search/test 80 | * https://feedgen.hasname.com/plurk/top/zh 81 | * https://feedgen.hasname.com/rent591/1/忠孝東路 (region = `1` means `台北市`, please check 591 site) 82 | * https://feedgen.hasname.com/shopee/測試 83 | * https://feedgen.hasname.com/taipeimetrotimetable/079a 84 | * https://feedgen.hasname.com/yourator/測試 85 | * https://feedgen.hasname.com/youtube/測試 86 | 87 | ## License 88 | 89 | See [LICENSE](LICENSE). 90 | -------------------------------------------------------------------------------- /feedgen_hasname/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasname/feedgen/6365ea93df41dbd20188fa2b6831ec71a99ff1b5/feedgen_hasname/__init__.py -------------------------------------------------------------------------------- /feedgen_hasname/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for feedgen_hasname project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'feedgen_hasname.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /feedgen_hasname/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for feedgen_hasname project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.0.6. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '^oj$^+__e7^i#)6#(cr3g7lzgkg%k-(nivdxw(!8p5!eu+0yny' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = False 27 | 28 | ALLOWED_HOSTS = [ 29 | 'feedgen.hasname.com', 30 | ] 31 | 32 | 33 | # Application definition 34 | 35 | INSTALLED_APPS = [ 36 | ] 37 | 38 | MIDDLEWARE = [ 39 | 'django.middleware.gzip.GZipMiddleware', 40 | ] 41 | 42 | ROOT_URLCONF = 'feedgen_hasname.urls' 43 | 44 | TEMPLATES = [ 45 | { 46 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 47 | 'DIRS': [], 48 | 'APP_DIRS': True, 49 | 'OPTIONS': { 50 | 'context_processors': [ 51 | ], 52 | }, 53 | }, 54 | ] 55 | 56 | WSGI_APPLICATION = 'feedgen_hasname.wsgi.application' 57 | 58 | 59 | # Database 60 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases 61 | 62 | DATABASES = { 63 | 'default': { 64 | 'ENGINE': 'django.db.backends.sqlite3', 65 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 66 | } 67 | } 68 | 69 | 70 | # Password validation 71 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators 72 | 73 | AUTH_PASSWORD_VALIDATORS = [ 74 | ] 75 | 76 | 77 | # Internationalization 78 | # https://docs.djangoproject.com/en/3.0/topics/i18n/ 79 | 80 | LANGUAGE_CODE = 'en-us' 81 | 82 | TIME_ZONE = 'UTC' 83 | 84 | USE_I18N = True 85 | 86 | USE_L10N = True 87 | 88 | USE_TZ = True 89 | 90 | 91 | # Static files (CSS, JavaScript, Images) 92 | # https://docs.djangoproject.com/en/3.0/howto/static-files/ 93 | 94 | STATIC_URL = '/static/' 95 | 96 | # Sentry 97 | import dotenv 98 | import sentry_sdk 99 | from sentry_sdk.integrations.django import DjangoIntegration 100 | dotenv.load_dotenv() 101 | sentry_sdk.init( 102 | dsn=os.getenv('SENTRY_DSN', ''), 103 | integrations=[DjangoIntegration()], 104 | ) 105 | -------------------------------------------------------------------------------- /feedgen_hasname/settings_dev.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import string 4 | 5 | os.environ['SENTRY_DSN'] = '' 6 | 7 | from .settings import * 8 | 9 | ALLOWED_HOSTS = [ '127.0.0.1', ] 10 | DATABASES = { 11 | 'default': { 12 | 'ENGINE': 'django.db.backends.sqlite3', 13 | 'NAME': '.dev.sqlite3', 14 | } 15 | } 16 | DEBUG = True 17 | LOGGING = { 18 | 'version': 1, 19 | 'disable_existing_loggers': False, 20 | 'handlers': { 21 | 'console': { 22 | 'class': 'logging.StreamHandler', 23 | }, 24 | }, 25 | 'root': { 26 | 'handlers': ['console'], 27 | 'level': 'DEBUG', 28 | }, 29 | } 30 | SECRET_KEY = ''.join(random.SystemRandom().choice(string.ascii_letters) for _ in range(50)) 31 | 32 | # SQLite3 Database for dev 33 | import os 34 | from django.core.management import execute_from_command_line 35 | -------------------------------------------------------------------------------- /feedgen_hasname/settings_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import string 4 | 5 | os.environ['SENTRY_DSN'] = '' 6 | 7 | from .settings import * 8 | 9 | ALLOWED_HOSTS = [ '127.0.0.1', ] 10 | DATABASES = { 11 | 'default': { 12 | 'ENGINE': 'django.db.backends.sqlite3', 13 | 'NAME': ':memory:', 14 | } 15 | } 16 | LOGGING = {} 17 | SECRET_KEY = ''.join(random.SystemRandom().choice(string.ascii_letters) for _ in range(50)) 18 | 19 | # Test environment 20 | import os 21 | from django.core.management import execute_from_command_line 22 | 23 | execute_from_command_line(['', 'makemigrations']) 24 | execute_from_command_line(['', 'migrate']) 25 | -------------------------------------------------------------------------------- /feedgen_hasname/urls.py: -------------------------------------------------------------------------------- 1 | """feedgen_hasname URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.urls import include, path 17 | 18 | urlpatterns = [ 19 | path('', include('general.urls')), 20 | ] 21 | -------------------------------------------------------------------------------- /feedgen_hasname/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for feedgen_hasname project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'feedgen_hasname.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /general/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasname/feedgen/6365ea93df41dbd20188fa2b6831ec71a99ff1b5/general/__init__.py -------------------------------------------------------------------------------- /general/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /general/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class GeneralConfig(AppConfig): 5 | name = 'general' 6 | -------------------------------------------------------------------------------- /general/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasname/feedgen/6365ea93df41dbd20188fa2b6831ec71a99ff1b5/general/migrations/__init__.py -------------------------------------------------------------------------------- /general/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /general/services/__init__.py: -------------------------------------------------------------------------------- 1 | from .proxy_socks5_service import ProxySocks5Service 2 | from .requests_service import RequestsService 3 | -------------------------------------------------------------------------------- /general/services/proxy_socks5_service.py: -------------------------------------------------------------------------------- 1 | from service_objects.services import Service 2 | import os 3 | 4 | class ProxySocks5Service(Service): 5 | db_transaction = False 6 | 7 | def process(self): 8 | return os.getenv('FEEDGEN_HTTP_PROXY') 9 | -------------------------------------------------------------------------------- /general/services/requests_service.py: -------------------------------------------------------------------------------- 1 | from service_objects.services import Service 2 | import requests 3 | 4 | class RequestsService(Service): 5 | db_transaction = False 6 | 7 | def process(self): 8 | class sessions(requests.Session): 9 | def request(self, *args, **kwargs): 10 | kwargs.setdefault('timeout', 10) 11 | return super(sessions, self).request(*args, **kwargs) 12 | 13 | s = sessions() 14 | s.headers.update({'User-Agent': 'feedgen'}) 15 | 16 | return s 17 | -------------------------------------------------------------------------------- /general/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasname/feedgen/6365ea93df41dbd20188fa2b6831ec71a99ff1b5/general/tests/__init__.py -------------------------------------------------------------------------------- /general/tests/html_taipeimetrotimetable.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasname/feedgen/6365ea93df41dbd20188fa2b6831ec71a99ff1b5/general/tests/html_taipeimetrotimetable.txt -------------------------------------------------------------------------------- /general/tests/json_dcard_popular.txt: -------------------------------------------------------------------------------- 1 | {"pageKey":"6fb3f360-aa10-40b9-a841-3bb4c6ac8b38","nextKey":"916ee80d-0eba-4364-b99d-70a105dad474","items":[{"id":"42851318-b9e2-4a75-8a05-9fe180becefe","name":"感情","alias":"relationship","posts":[{"id":237888017,"title":"色色的時候🙈🙈發現男友屁股黑黑的","excerpt":"之前跟男友色色的時候,發現在他屁股蛋下緣黑黑的有顆粒,跟他講了之後,他立馬給我衝到鏡子前掰著屁股看,身為一個比女生還女生的男生(繞口令??給我當場崩潰說:「我的屁屁不年輕了」請問你平常是在賣屁股嗎?到"}]},{"id":"75a726e6-d4e3-4902-a410-2430a39fffcb","name":"心情","alias":"mood","posts":[{"id":237886619,"title":"我確診新冠肺炎了","excerpt":"更,謝謝關心我、祝我早日康復的大家️,我在陽性的情況下是沒有打算也絕對不會回台灣,不用擔心我增加台灣醫護負擔,我知道大家都很辛苦,另外這趟也是去找家人,不是趴趴走爽玩,以美國現狀來說可能搭個公車地鐵都會"}]},{"id":"255fd275-fec2-49d2-8e46-2e1557ffaeb0","name":"閒聊","alias":"talk","posts":[{"id":237886440,"title":"很討厭捷運上貼鋼管的人","excerpt":"因為瘋子太多,現在都不敢在捷運上隨便糾正別人,怕等一下就被抓頭髮,只好很廢的上來發文埋怨,不管多少人要抓她就是很死命貼在上面,是不是要跳鋼管啦氣死🤬🤬🤬"}]},{"id":"cbd5285f-3cba-4bfc-86d0-1ab52d201459","name":"美妝","alias":"makeup","posts":[{"id":237883197,"title":"#試色 這個月花了十萬塊買的眼影","excerpt":"買的都是看到覺得漂亮的。因為前個月看到漂亮的眼影,就覺得眼影很漂亮,所以就開始買眼影了。然後因為明天還要補習所以沒有辦法試色完,就先用了一部分。這個月大概買了這些。其實我也不知道多少錢,但應該是12-"}]},{"id":"f72e3b1d-3c9a-4fec-8a61-41c76cc317af","name":"女孩","alias":"girl","posts":[{"id":237889090,"title":"Keanna和OZI?","excerpt":"3/27、紅髮,文末標ØZI,這中間感覺有什麼關聯🤔"}]},{"id":"de977130-f3eb-467b-822e-b0e91124e9eb","name":"美食","alias":"food","posts":[{"id":237883292,"title":"牛排這樣140合理嗎","excerpt":"更),新聞網址:B68,記者表示我拿到的跟上面的照片差不多:),提醒之後還要去採訪的記者,不要只聽店家單一說法就下結論,甚至直接說是我誤會耶覺得誇張,店家是在上第一則新聞後才趕快修正外送平台的備註欄("}]},{"id":"a1aaa6e6-2594-4968-b7dc-e1b14bea96f4","name":"有趣","alias":"funny","posts":[{"id":237887522,"title":"在洗衣機裡做蛋炒飯?","excerpt":"去自助洗衣店洗衣服的時候,有人意外發現滾筒洗衣機裡有大量黃色、白色、橘色的顏色混雜,乍看之下極像蛋炒飯,白色是白飯、黃色是炒蛋、橘色是醬油,怎麼那麼剛好是醬油蛋炒飯🤣🤣🤣,喔~原來是衣服裡的棉絮啊"}]},{"id":"b5b2653a-6304-4564-9ea0-a4cec0be7aee","name":"彩虹","alias":"rainbow","posts":[{"id":237881180,"title":"(破案了)交往兩年男友從來不跟我做愛😶","excerpt":"交往了兩年 有親親 有抱抱 有用手解決,但是一直沒有做愛,當初我追的他,他以前的交往對象都是女生,也有做過,每次當我想進一步的時候他都會拒絕,那我也只好放棄,然後互相解決,他是不是只想跟女生做啊,我有"}]},{"id":"06e07db4-c8b5-4dae-851f-e8a8236e770c","name":"梗圖","alias":"meme","posts":[{"id":237878850,"title":"令人感動(˶‾᷄ ⁻̫ ‾᷅˵)","excerpt":""}]},{"id":"6eeeafb2-9dac-4d81-ae4b-ffecf0ad4444","name":"工作","alias":"job","posts":[{"id":237878393,"title":"年終獎金","excerpt":"無論年資多寡,年終獎金永遠只有一個月的薪水,甚至連一個月全薪不到,2w6,請問年終獎金這樣話是不是公司發展、制度很差,年終獎金只有一個月不到,三節只會發禮卷金額還都不到$1000,請問各行各業的年終獎"}]},{"id":"14f573f5-3f02-4821-8e18-f561d7b7db91","name":"追星","alias":"entertainer","posts":[{"id":237887664,"title":"#集中討論 陳庭妮和胡宇威結婚了","excerpt":"是吧?手上的鑽戒啊啊,還是只是什麼品牌的合作?但留言都是恭喜啊(?是結婚吧,B50有新聞 是真的,——————補個宇威也發了!,真的不是什麼品牌合作吧(超怕被騙,這是真的結婚吧,剛剛太緊張了🤣補一下我"}]},{"id":"ba0145a2-adff-4229-9a84-9b26ebd2f7f0","name":"戲劇綜藝","alias":"tvepisode","posts":[{"id":237887759,"title":"胡宇崴的婚禮看得到藍隊三代同堂嗎?","excerpt":"先想遠一點,不知道如果辦了婚禮 藍2,藍3會不會參加,雖然藍2 藍3可能都跟他不太熟,但多少身為藍隊元老的主將又是大家熟知的學長,感覺多少還是有點連結,如果真的看到藍隊全員三代同堂的話 尤其是隊長,會"}]},{"id":"be1a095b-175e-4523-9e06-66a05d939676","name":"穿搭","alias":"dressup","posts":[{"id":237888910,"title":"UNIQLO新厚T 這個CP值好像有點高 #開箱大使","excerpt":"#開箱大使,大家安安!!,首先感謝Dcard官方讓我可以接到這麼讚的業配,附上小弟,身材介紹,182CM 62KG 肩寬45CM,日常穿衣尺碼:(L),以下所有衣服尺寸都是(L),先放上白貓穿搭照,"}]},{"id":"0a859162-88d8-4406-8111-71c57aae84a1","name":"Netflix","alias":"netflix","posts":[{"id":237882583,"title":"#詢問 這是什麼陣容啦⋯⋯⋯⋯","excerpt":"這三季演得完嗎‍"}]},{"id":"b7db78c7-7b32-4da5-a565-907a892259d7","name":"YouTuber","alias":"youtuber","posts":[{"id":237882111,"title":"喜歡坤達的人是不是只看外表?","excerpt":"最近木曜主持的跨年掀起很多討論,像是遲到 超尬 不敬業…,但我對木曜的坤達比較好奇,在網絡上擁護坤達的人很多,但幾乎都是,「他好帥」「顏值勝過一切」「不用開口就贏了」這種只有外型才能拿出來稱讚的話,而"}]},{"id":"4c6964fc-8b39-4480-a844-847f09e4e09d","name":"星座","alias":"horoscopes","posts":[{"id":237889437,"title":"關於風象星座的特質","excerpt":"大家好,可能有一些人會覺得,與風向星座聊天很愉快,什麼都能掰,但是在問到一系列的事物的時候,常常會亂跳亂跳,好像不知所云,可是卻又連得起來,其實這與風向星座的大腦運作模式有點關係,打個比方來說,每一個"}]},{"id":"f11e8d02-6756-4376-9db3-e1cca4d2a66c","name":"結婚","alias":"marriage","posts":[{"id":237878515,"title":"這個婚真要結?","excerpt":"我發現我懷孕了⋯,這期間我男朋友在我們家,他明明都有機會可以和我一起去說。我以為他會開口,但我沒想到是我開口說我懷孕了🤰,而他第一句是我們兩個私下討論的婚事⋯(和他原本跟我說要和我媽媽說得話完全不一樣"}]},{"id":"919f8537-6268-4404-b319-0cf46111ba34","name":"牙齒矯正","alias":"orthodontics","posts":[{"id":237889799,"title":"光一個牙齒矯正,就能改變你的容貌!","excerpt":"偶然看到了這篇文章,其實很心疼原po,我以前也是因為外貌被霸凌,甚至有些同學也都會嘲笑我怎麼不去整形,「你怎麼不把剪劉海的錢存下來拿去整形」「你的嘴巴怎麼合不起來」「有沒有人說你長得像河童」「欸河童」"}]},{"id":"3bceb81c-574e-4a96-8050-4df56096d0df","name":"理財","alias":"money","posts":[{"id":237882831,"title":"30歲存到110萬","excerpt":"朋友下午傳110萬的截圖給我看,這兩年做業務工作,以前都在咖啡上班當文青,一個月兩萬多塊,後來被34D女友分手,說他沒上進心,他便去應徵綠色房仲,常常聽他在幹譙屋主幹譙買方,但他也很認真,剛好這兩年房"}]},{"id":"7ee21581-1307-4ba9-b9dc-82028bdcca49","name":"寵物","alias":"pet","posts":[{"id":237888900,"title":"收容所令人傻眼的作業疏失( ・᷄ὢ・᷅ )","excerpt":"#不要上臉書和新聞,也不是要攻擊這間收容所,因為我家寶貝也是在這領養的,但這真的太瞎了 還是想說出來,有機會的話能讓收容所的員工重視一下,是這樣的 我一直很喜歡重點色虎斑,但這種貓咪真的炙手可熱,永遠"}]},{"id":"8a2a0b9a-7664-49b0-bff7-58389ef73a0d","name":"減肥","alias":"weight_loss","posts":[{"id":237889266,"title":"每天喝2000ml的水真的有差嗎實驗","excerpt":"在減肥版潛水已久 一直沒有減肥成功,所以想說來試試最簡單的每天喝2公升水,試個1個月看看有沒有什麼改變,廢話不多說直接揭曉成果,體重體脂身形沒啥變,不意外 努力試過這麼多,如果喝水就瘦,那我真的被上天"}]},{"id":"d43f33f9-873f-46b3-9f24-38c90056b96c","name":"考試","alias":"exam","posts":[{"id":237881415,"title":"111學測發雞排+珍奶🧋","excerpt":"有鑑於很多同學輕忽「國文」及「社會」這兩科,導致與醫學系、牙醫系或頂尖大學失之交臂,(今年名額最多的醫學系:中國醫及馬偕都要採計社會),本人決定於111/3/5,111學測成績公佈當週星期六下午2點在"}]},{"id":"c573dca4-8afd-4c56-8c53-4402ead7bdad","name":"精品","alias":"boutique","posts":[{"id":237886926,"title":"#開箱 我的第一個小香包 2.55 reissue","excerpt":"有時候,買精品就是要一股衝動。想買Chanel包好久了,本來想說等去歐洲玩可以買,沒想到因爲疫情旅行被取消,後來還生了一個小孩。短期內要旅行更難了!這樣拖拉小香包都已經漲了好幾輪。有一天早上起來,不需"}]},{"id":"d5ee9d02-510e-4f81-96e9-ab59b56e21ca","name":"網路購物","alias":"buyonline","posts":[{"id":237886456,"title":"蝦皮店到店 開車可以開兩天","excerpt":"如果多花$60可以不用等這麼久,我真的願意,這個東西快斷貨了QQ,他如果還給我寄不見 我真的會暴走,賣家都幫我那麼早出貨了,真的是雷到爆,不是阿,如果你系統還沒處理好 店面也不普及,你就不要一次開那麼"}]},{"id":"16b1b561-788e-4214-b4b7-e3102a35fa0d","name":"美甲","alias":"manicure","posts":[{"id":237881334,"title":"我願稱之為華燈初上","excerpt":"大家好,我是姬。最近華燈初上真的超紅,但我沒有看,意外做了一款感覺有這部劇氛圍感的美甲,因此就用劇名為這款美甲命名了,我是在哀居上看到別的店家做的圖,然後拿圖給我的美甲師做的,附上原圖,因為這個店家好"}]},{"id":"62268850-d2b4-4c21-a7a3-26e71702a276","name":"美髮","alias":"hairsalon","posts":[{"id":237886764,"title":"笑死剪壞的公主切","excerpt":"前幾天剪ㄌ短髮公主切,朋友說像海苔(你禮貌嗎???請問各位這種怎麼救 還是已經沒救,有考慮要不要去修 可是切的部分剪很短 怕修下去更短,現在這頭髮醜到哭,理髮師說可以再去找她修但真的不太敢⋯-.-"}]},{"id":"58dba906-09c2-4808-9206-11c008c9ef16","name":"研究所","alias":"graduate_school","posts":[{"id":237882493,"title":"安了啦 繼續讀囉","excerpt":""}]},{"id":"2fb88b62-aa28-4b18-af51-dda08dd037a9","name":"股票","alias":"stock","posts":[{"id":237883580,"title":"#分享 金融股小本無腦存股分享","excerpt":"各位好 我只是來分享金融股存了一段時間,這篇主要是歡迎從當沖畢業或是剛出社會想投資點穩到不行的東西的人看的,現在加入我大金融股的行列 定期定額加上不定期不定額 (有自信的人全部都不定期不定額,讓我們加"}]},{"id":"99602190-dde4-4ba0-82da-068d65bbe2ff","name":"梗影","alias":"funny_video","posts":[{"id":237884153,"title":"一切都發生的多麼自然","excerpt":""}]},{"id":"ffc2ebb1-9985-4ce8-8f30-7dfdca609afa","name":"超商","alias":"cvs","posts":[{"id":237883658,"title":"#全家 全家福袋 中了Ryan和室椅!超爆可愛實體開箱🥳","excerpt":"最近常看朋友一直在限動洗版全家福袋,還有人抽中保溫瓶,覺得好像還不錯,就跟風買了一個來開箱,這袋零食我稱它童年回憶包 因為都是小時候很愛長大不會買的贈品拿到一個超童趣的飲料提袋,原本還有點難過,當我不"}]}]} 2 | -------------------------------------------------------------------------------- /general/tests/json_job104.txt: -------------------------------------------------------------------------------- 1 | {"data":[{"appearDate":"20241017","applyCnt":4,"coIndustry":1001001003,"coIndustryDesc":"\u7db2\u969b\u7db2\u8def\u76f8\u95dc\u696d","custName":"\u3010\u4f01\u696d\u5c08\u6848\u62db\u52df\u3011104\u672a\u4f86\u7121\u9650\u6574\u5408\u62db\u52df\u4e2d\u5fc3","custNo":"99999999000","description":"\u203b\u61c9\u5fb5\u672c\u8077\u7f3a\u7d93\u5be9\u6838\u901a\u904e\u8005\uff0c\u5c07\u9080\u7d04\u51fa\u5e2d11\/1(\u4e94) \u5a92\u5408\u6703\u73fe\u5834\u9762\u8ac7\uff0c\u672c\u5be6\u9ad4\u6d3b\u52d5\u70ba\u6843\u5712\u5e02\u653f\u5e9c\u9752\u5e74\u4e8b\u52d9\u5c40\u4e4b\u5c08\u6848\u6d3b\u52d5\n\n1.Develop and maintain team oriented tools\/scripts to increase test productivity.\n2.Perform device check and performance and stress tests and later write scripts to automate them\n(Iperf\/FIO\/Stress\/memtest,etc.)\n3.Expertise in scripting & programming languages such as Python, Shell, Bash, BAT, TTL, etc.\n4.Responsible for testing L2-L4 network products, monitoring test output and performance, maintaining SOP of test plans and test procedures, and supporting debugging of fault units in collaboration with RD.\n5.Report hardware and software issues into bug tracking systems with very detailed information to allow hardware engineers and developers to easily duplicate","descSnippet":"\u203b\u61c9\u5fb5\u672c\u8077\u7f3a\u7d93\u5be9\u6838\u901a\u904e\u8005\uff0c\u5c07\u9080\u7d04\u51fa\u5e2d11\/1(\u4e94) \u5a92\u5408\u6703\u73fe\u5834\u9762\u8ac7\uff0c\u672c\u5be6\u9ad4\u6d3b\u52d5\u70ba\u6843\u5712\u5e02\u653f\u5e9c\u9752\u5e74\u4e8b\u52d9\u5c40\u4e4b\u5c08\u6848\u6d3b\u52d5\n\n1.Develop and maintain team oriented tools\/scripts to increase test productivity.\n2.Perform device check and performance and stress tests and later write scripts to automate them\n(Iperf\/FIO\/Stress\/memtest,etc.)\n3.Expertise in scripting & programming languages such as Python, Shell, Bash, BAT, TTL, etc.\n4.Responsible for testing L2-L4 network products, monitoring test output and performance, maintaining SOP of test plans and test procedures, and supporting debugging of fault units in collaboration with RD.\n5.Report hardware and software issues into bug tracking systems with very detailed information to allow hardware engineers and developers to easily duplicate","mrtDist":0,"jobAddress":"\u5fa9\u8208\u4e09\u8def500\u865f(\u8fd1\u6797\u53e3\u9577\u5e9a)","jobAddrNo":6001005008,"jobAddrNoDesc":"\u6843\u5712\u5e02\u9f9c\u5c71\u5340","jobName":"(16C2)\u7cfb\u7d71\u6574\u5408\u6e2c\u8a66\u5de5\u7a0b\u5e2b(SIT)\uff5c\u795e\u6e96\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8_11\/1(\u4e94)\u5be6\u9ad4\u5a92\u5408\u6703\u73fe\u5834\u9762\u8ac7","jobNameSnippet":"(16C2)\u7cfb\u7d71\u6574\u5408\u6e2c\u8a66\u5de5\u7a0b\u5e2b(SIT)\uff5c\u795e\u6e96\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8_11\/1(\u4e94)\u5be6\u9ad4\u5a92\u5408\u6703\u73fe\u5834\u9762\u8ac7","jobNo":"14278677","jobRo":1,"jobType":1,"lat":25.0418753,"lon":121.3709319,"link":{"job":"https:\/\/www.104.com.tw\/job\/8i1hx","cust":"https:\/\/www.104.com.tw\/company\/19xtf120","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8i1hx?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u7dad\u8b77\u76f8\u95dc","\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc","\u8cc7\u8a0a\u5de5\u7a0b\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[3,4],"period":0,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":[],"s9":[1],"s5":0,"d3":"08:30-17:30(\u524d\u5f8c\u5f48\u60271\u5c0f\u6642)","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241014","applyCnt":5,"coIndustry":1001006002,"coIndustryDesc":"\u534a\u5c0e\u9ad4\u88fd\u9020\u696d","custName":"\u53f0\u7063\u7f8e\u5149(\u53f0\u7063\u7f8e\u5149\u6676\u5713\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\/\u53f0\u7063\u7f8e\u5149\u8a18\u61b6\u9ad4\u80a1\u4efd\u6709\u9650\u516c\u53f8\/\u7f8e\u5546\u7f8e\u5149\u4e9e\u592a\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8)","custNo":"80353271000","description":"Apply Here: https:\/\/micron.wd1.myworkdayjobs.com\/External\/job\/Taichung---Fab-16-Taiwan\/PDE-Sr-Engineer---PCS-INTEGRATION_JR56945\n\n\nJob Description\nAs PDE PCS\/Metro\/Process Integration Engineer, we must collaborate with teams from Wafer Fab Team, Backend Process Team, Quality, PIE and Smart Manufacturing, and we will be responsible to integrate our manufacturing defense line for optimal quality control. The success of this position will be assessed by our ability to ensure defense coverage through process, measurement, inspection and test; our establishment of correlation between the defense to identify avenues to shift left, data mining for improvement opportunities, timely closure for excursion investigations and establishing advanced controls such as virtual metrology and predictive maintenance through continuous data analysis. This team handles development as well as global central role in Micron Backend environment.\n\nKey responsibilities and task\n\nWe drive the integration of our quality defense line through continuous data analysis, mining, and coverage study.\nWe work closely with different teams to understand any relationship across defense line and feasibility of shift left activities.\nWe need to analysis correlation between wafer fabrication parameters and backend manufacturing issues to identify opportunities for gap closure, and work with process integration team to reach a resolution.\nWe need to analyze and data mine test data for root cause investigation.\nWe work with Advance Process Integration Team to enable any opportunities to close gaps during our coverage study\nWe handle any global excursion investigation by leveraging on our tools available across the defense lines.\nWe identify opportunities to establish advanced controls such as virtual metrology and predictive maintenance through continuous data analysis.\nWe ensure that defense line coverage is met for any new product introduction.\nWe will be the expert in defense line strategies, platforms, systems and will handle roadmap for further enhancements to our Micron Backend Defense line.\nRequirements\n\nMasters or Bachelor's degree in an Engineering field.\nExperience in Fab Process, PWF or Backend engineering process or package development preferred\nExperience in Python, Scripting is an advantage\nExperience in Data Science is an advantage \nGood technical knowledge in component test and\/or module manufacturing process\nExcellent data analysis, statistical analysis, data interpretation skills\nAbility to make sound data-driven decisions. Prioritize and apply due-diligence in day to day task.\nProficiency in Excel, Word, Power Point, Project Management Software or any equivalent software","descSnippet":"Apply Here: https:\/\/micron.wd1.myworkdayjobs.com\/External\/job\/Taichung---Fab-16-Taiwan\/PDE-Sr-Engineer---PCS-INTEGRATION_JR56945\n\n\nJob Description\nAs PDE PCS\/Metro\/Process Integration Engineer, we must collaborate with teams from Wafer Fab Team, Backend Process Team, Quality, PIE and Smart Manufacturing, and we will be responsible to integrate our manufacturing defense line for optimal quality control. The success of this position will be assessed by our ability to ensure defense coverage through process, measurement, inspection and test; our establishment of correlation between the defense to identify avenues to shift left, data mining for improvement opportunities, timely closure for excursion investigations and establishing advanced controls such as virtual metrology and predictive maintenance through continuous data analysis. This team handles development as well as global central role in Micron Backend environment.\n\nKey responsibilities and task\n\nWe drive the integration of our quality defense line through continuous data analysis, mining, and coverage study.\nWe work closely with different teams to understand any relationship across defense line and feasibility of shift left activities.\nWe need to analysis correlation between wafer fabrication parameters and backend manufacturing issues to identify opportunities for gap closure, and work with process integration team to reach a resolution.\nWe need to analyze and data mine test data for root cause investigation.\nWe work with Advance Process Integration Team to enable any opportunities to close gaps during our coverage study\nWe handle any global excursion investigation by leveraging on our tools available across the defense lines.\nWe identify opportunities to establish advanced controls such as virtual metrology and predictive maintenance through continuous data analysis.\nWe ensure that defense line coverage is met for any new product introduction.\nWe will be the expert in defense line strategies, platforms, systems and will handle roadmap for further enhancements to our Micron Backend Defense line.\nRequirements\n\nMasters or Bachelor's degree in an Engineering field.\nExperience in Fab Process, PWF or Backend engineering process or package development preferred\nExperience in Python, Scripting is an advantage\nExperience in Data Science is an advantage \nGood technical knowledge in component test and\/or module manufacturing process\nExcellent data analysis, statistical analysis, data interpretation skills\nAbility to make sound data-driven decisions. Prioritize and apply due-diligence in day to day task.\nProficiency in Excel, Word, Power Point, Project Management Software or any equivalent software","mrtDist":0,"jobAddress":"\u53f0\u4e2d\u5e02\u540e\u91cc\u5340\u4e09\u8c50\u8def\u56db\u6bb5369\u865f","jobAddrNo":6001008014,"jobAddrNoDesc":"\u53f0\u4e2d\u5e02\u540e\u91cc\u5340","jobName":"PDE Sr Engineer - PCS INTEGRATION","jobNameSnippet":"PDE Sr Engineer - PCS INTEGRATION","jobNo":"14066325","jobRo":1,"jobType":1,"lat":24.3181102,"lon":120.7240916,"link":{"job":"https:\/\/www.104.com.tw\/job\/8dhn9","cust":"https:\/\/www.104.com.tw\/company\/10ww9gpk","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8dhn9?channel=104rpt"},"major":["\u5de5\u7a0b\u5b78\u79d1\u985e"],"mrt":"","mrtDesc":"","optionEdu":[4,5,6],"period":6,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zone":{"desc":"\u4e0a\u5e02\u4e0a\u6ac3","param":16},"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"wf16":{"desc":"","param":"wf16"},"wf27":{"desc":"","param":"wf27"},"wf20":{"desc":"","param":"wf20"},"wf19":{"desc":"","param":"wf19"},"wf1":{"desc":"","param":"wf1"},"wf10":{"desc":"","param":"wf10"},"wf34":{"desc":"","param":"wf34"},"wf7":{"desc":"","param":"wf7"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20240920","applyCnt":4,"coIndustry":1001001002,"coIndustryDesc":"\u96fb\u8166\u8edf\u9ad4\u670d\u52d9\u696d","custName":"\u99ac\u4f86\u897f\u4e9e\u5546\u98db\u78bc\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"80357001000","description":" and combination testing.\n\u2022 Carry out the tests in agreement with customer requests and test methods for EMVCo and other","descSnippet":" and combination testing.\n\u2022 Carry out the tests in agreement with customer requests and [[[test]]] methods for EMVCo and other","mrtDist":0.5,"jobAddress":"\u4fe1\u7fa9\u8def\u4e94\u6bb5150\u5df72\u865f2\u6a13","jobAddrNo":6001001007,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u4fe1\u7fa9\u5340","jobName":"Test Analyst","jobNameSnippet":"[[[Test]]] Analyst","jobNo":"13255355","jobRo":1,"jobType":2,"lat":25.0282887,"lon":121.5709968,"link":{"job":"https:\/\/www.104.com.tw\/job\/7w3wb","cust":"https:\/\/www.104.com.tw\/company\/10wyheso","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/7w3wb?channel=104rpt"},"major":["\u6578\u5b78\u53ca\u96fb\u7b97\u6a5f\u79d1\u5b78\u5b78\u79d1\u985e","\u81ea\u7136\u79d1\u5b78\u5b78\u79d1\u985e","\u5de5\u7a0b\u5b78\u79d1\u985e"],"mrt":"99001002001","mrtDesc":"\u6377\u904b\u8c61\u5c71\u7ad9","optionEdu":[4,5],"period":0,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"wf8":{"desc":"","param":"wf8"},"wf7":{"desc":"","param":"wf7"},"wf12":{"desc":"","param":"wf12"},"wf29":{"desc":"","param":"wf29"},"wf1":{"desc":"","param":"wf1"},"wf13":{"desc":"","param":"wf13"},"wf30":{"desc":"","param":"wf30"},"wf2":{"desc":"","param":"wf2"},"wf9":{"desc":"","param":"wf9"},"wf26":{"desc":"","param":"wf26"},"landmark":{"desc":"\u8ddd\u6377\u904b\u8c61\u5c71\u7ad9\u7d04500\u516c\u5c3a"}},"s9":[1],"s5":0,"d3":"09:00~18:00","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241014","applyCnt":2,"coIndustry":1001001001,"coIndustryDesc":"\u96fb\u8166\u7cfb\u7d71\u6574\u5408\u670d\u52d9\u696d","custName":"\u6d77\u76dc\u8239\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8","custNo":"27966639000","description":"maintenance. For Issues Tracking, they need to check issues with engineers\/vendors for finding root causes and solution. For Test","descSnippet":"maintenance. For Issues Tracking, they need to check issues with engineers\/vendors for finding root causes and solution. For [[[Test]]]","mrtDist":0,"jobAddress":"\u65b0\u53f0\u4e94\u8def\u4e00\u6bb593\u865f31\u6a13(\u8fd1\u6c50\u79d1\u706b\u8eca\u7ad9)","jobAddrNo":6001002004,"jobAddrNoDesc":"\u65b0\u5317\u5e02\u6c50\u6b62\u5340","jobName":"Test Engineer","jobNameSnippet":"[[[Test]]] Engineer","jobNo":"14309971","jobRo":1,"jobType":2,"lat":25.0617716,"lon":121.648006,"link":{"job":"https:\/\/www.104.com.tw\/job\/8ipn7","cust":"https:\/\/www.104.com.tw\/company\/cuim4rc","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8ipn7?channel=104rpt"},"major":[],"mrt":"","mrtDesc":"","optionEdu":[4,5],"period":4,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"wf25":{"desc":"","param":"wf25"},"wf10":{"desc":"","param":"wf10"},"wf1":{"desc":"","param":"wf1"},"wf28":{"desc":"","param":"wf28"},"wf7":{"desc":"","param":"wf7"}},"s9":[1],"s5":0,"d3":"9:00~18:00","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241017","applyCnt":5,"coIndustry":1001003001,"coIndustryDesc":"\u96fb\u8166\u53ca\u5176\u9031\u908a\u8a2d\u5099\u88fd\u9020\u696d","custName":"\u8377\u862d\u5546\u745e\u529b\u767b\u570b\u969b\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"130000000014992","description":"POSITION SUMMARY \n\nWe are now looking for a talent system engineer to join the system test team to design, maintain and","descSnippet":"POSITION SUMMARY \n\nWe are now looking for a talent system engineer to join the system [[[test]]] team to design, maintain and","mrtDist":0,"jobAddress":"\u5bf6\u6a4b\u8def235\u5df7121\u865f5\u6a13","jobAddrNo":6001002011,"jobAddrNoDesc":"\u65b0\u5317\u5e02\u65b0\u5e97\u5340","jobName":"System Test Engineer","jobNameSnippet":"System [[[Test]]] Engineer","jobNo":"14186951","jobRo":1,"jobType":2,"lat":24.9831853,"lon":121.5506196,"link":{"job":"https:\/\/www.104.com.tw\/job\/8g2pz","cust":"https:\/\/www.104.com.tw\/company\/1a2x6biavk","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8g2pz?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u7dad\u8b77\u76f8\u95dc","\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[3,4,5,6],"period":4,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"wf1":{"desc":"","param":"wf1"},"wf7":{"desc":"","param":"wf7"},"wf2":{"desc":"","param":"wf2"},"wf25":{"desc":"","param":"wf25"},"wf26":{"desc":"","param":"wf26"},"wf14":{"desc":"","param":"wf14"},"wf18":{"desc":"","param":"wf18"},"wf9":{"desc":"","param":"wf9"},"wf10":{"desc":"","param":"wf10"},"wf24":{"desc":"","param":"wf24"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241014","applyCnt":7,"coIndustry":1001005003,"coIndustryDesc":"\u5176\u4ed6\u96fb\u5b50\u96f6\u7d44\u4ef6\u76f8\u95dc\u696d","custName":"\u7f8e\u5546\u80fd\u9054\u5fae\u96fb\u5b50\u80a1\u4efd\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"130000000203943","description":"1.\tWork with RD to develop IC test program. \n2.\tCapable of developing test hardware.\n3.\tFamiliar with coding of power","descSnippet":"1.\tWork with RD to develop IC [[[test]]] program. \n2.\tCapable of developing [[[test]]] hardware.\n3.\tFamiliar with coding of power","mrtDist":0,"jobAddress":"","jobAddrNo":6001006001,"jobAddrNoDesc":"\u65b0\u7af9\u5e02","jobName":"Test Engineer","jobNameSnippet":"[[[Test]]] Engineer","jobNo":"13421214","jobRo":1,"jobType":0,"lat":24.8138287,"lon":120.9674798,"link":{"job":"https:\/\/www.104.com.tw\/job\/7znvi","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bmco7","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/7znvi?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u7dad\u8b77\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[4,5],"period":4,"remoteWorkType":0,"s10":50,"salaryHigh":9999999,"salaryLow":40000,"tags":{"wf26":{"desc":"","param":"wf26"},"wf4":{"desc":"","param":"wf4"},"wf8":{"desc":"","param":"wf8"},"wf10":{"desc":"","param":"wf10"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241018","applyCnt":4,"coIndustry":1001001003,"coIndustryDesc":"\u7db2\u969b\u7db2\u8def\u76f8\u95dc\u696d","custName":"ULTRON \u5967\u5275_\u85a9\u6469\u4e9e\u5546\u5967\u5275\u7269\u806f\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"130000000118848","description":"\u8a66\u6d41\u7a0b\u6548\u7387\u3002\u540c\u6642\u767c\u73fe\u554f\u984c\u3001\u6536\u96c6\u554f\u984c\u3001\u56de\u5831\u554f\u984c\u5916\uff0c\u9700\u9032\u4e00\u6b65\u5354\u540cRD\u6539\u5584\u7522\u54c1\u4ee5\u4fdd\u8b49\u6211\u5011\u6240\u7522\u51fa\u7684\u7522\u54c1\u8cbc\u5408\u7d42\u7aef\u4f7f\u7528\u8005\u7684\u9700\u6c42\u3002\nSr. Test Automation Developer is an important promoter of ULTRON","descSnippet":"\u8a66\u6d41\u7a0b\u6548\u7387\u3002\u540c\u6642\u767c\u73fe\u554f\u984c\u3001\u6536\u96c6\u554f\u984c\u3001\u56de\u5831\u554f\u984c\u5916\uff0c\u9700\u9032\u4e00\u6b65\u5354\u540cRD\u6539\u5584\u7522\u54c1\u4ee5\u4fdd\u8b49\u6211\u5011\u6240\u7522\u51fa\u7684\u7522\u54c1\u8cbc\u5408\u7d42\u7aef\u4f7f\u7528\u8005\u7684\u9700\u6c42\u3002\nSr. [[[Test]]] Automation Developer is an important promoter of ULTRON","mrtDist":0,"jobAddress":"\u884c\u5584\u8def48\u5df715\u865f5\u6a13\u4e4b1","jobAddrNo":6001001010,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u5167\u6e56\u5340","jobName":"Sr. Test Automation Developer \u81ea\u52d5\u5316\u6e2c\u8a66\u8edf\u9ad4\u958b\u767c\u5de5\u7a0b\u5e2b","jobNameSnippet":"Sr. [[[Test]]] Automation Developer \u81ea\u52d5\u5316\u6e2c\u8a66\u8edf\u9ad4\u958b\u767c\u5de5\u7a0b\u5e2b","jobNo":"13962894","jobRo":1,"jobType":2,"lat":25.057748,"lon":121.575335,"link":{"job":"https:\/\/www.104.com.tw\/job\/8b9u6","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bkj0g","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8b9u6?channel=104rpt"},"major":[],"mrt":"","mrtDesc":"","optionEdu":[4,5,6],"period":6,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"wf10":{"desc":"","param":"wf10"},"wf26":{"desc":"","param":"wf26"},"wf28":{"desc":"","param":"wf28"},"wf1":{"desc":"","param":"wf1"},"wf14":{"desc":"","param":"wf14"},"wf29":{"desc":"","param":"wf29"},"wf7":{"desc":"","param":"wf7"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241016","applyCnt":8,"coIndustry":1001001003,"coIndustryDesc":"\u7db2\u969b\u7db2\u8def\u76f8\u95dc\u696d","custName":"Amazon Web Services Taiwan Limited_\u53f0\u7063\u4e9e\u99ac\u905c\u7db2\u8def\u670d\u52d9\u6709\u9650\u516c\u53f8","custNo":"130000000066833","description":"\n\nAnnapurna Labs is seeking a semiconductor test engineer with a background in classic ATE hardware (testers\/probers\/handlers) to","descSnippet":"\n\nAnnapurna Labs is seeking a semiconductor [[[test]]] engineer with a background in classic ATE hardware (testers\/probers\/handlers) to","mrtDist":0,"jobAddress":"","jobAddrNo":6001001007,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u4fe1\u7fa9\u5340","jobName":"Product Test Hardware Engineer","jobNameSnippet":"Product [[[Test]]] Hardware Engineer","jobNo":"14313465","jobRo":1,"jobType":0,"lat":25.0409201,"lon":121.5720055,"link":{"job":"https:\/\/www.104.com.tw\/job\/8isc9","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bjevl","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8isc9?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc","\u5176\u4ed6\u5de5\u7a0b\u76f8\u95dc","\u6a5f\u68b0\u5de5\u7a0b\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[4,5,6],"period":4,"remoteWorkType":2,"s10":50,"salaryHigh":9999999,"salaryLow":40000,"tags":{"remote":{"desc":"\u9060\u7aef\u5de5\u4f5c"},"wf8":{"desc":"","param":"wf8"},"wf4":{"desc":"","param":"wf4"},"wf28":{"desc":"","param":"wf28"},"wf13":{"desc":"","param":"wf13"},"wf7":{"desc":"","param":"wf7"},"wf12":{"desc":"","param":"wf12"},"wf26":{"desc":"","param":"wf26"},"wf9":{"desc":"","param":"wf9"},"wf35":{"desc":"","param":"wf35"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20240801","applyCnt":3,"coIndustry":1001001006,"coIndustryDesc":"\u5176\u5b83\u8edf\u9ad4\u53ca\u7db2\u8def\u76f8\u95dc\u696d","custName":"Taiwan AI Labs_\u96c5\u5a77\u667a\u6167\u80a1\u4efd\u6709\u9650\u516c\u53f8","custNo":"130000000188403","description":"\n\n\n\u3010Responsibilities\u3011\n1.Execute test cases (manual or automated) and analyze results\n2.Create logs to document testing phases","descSnippet":"\n\n\n\u3010Responsibilities\u3011\n1.Execute [[[test]]] cases (manual or automated) and analyze results\n2.Create logs to document testing phases","mrtDist":0.23,"jobAddress":"\u627f\u5fb7\u8def1\u6bb570\u865f15\u6a13","jobAddrNo":6001001002,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u5927\u540c\u5340","jobName":"Software Test Engineer _Taipei","jobNameSnippet":"Software [[[Test]]] Engineer _Taipei","jobNo":"14141793","jobRo":1,"jobType":0,"lat":25.0627243,"lon":121.5113064,"link":{"job":"https:\/\/www.104.com.tw\/job\/8f3vl","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bm0oj","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8f3vl?channel=104rpt"},"major":[],"mrt":"99001004012","mrtDesc":"\u6377\u904b\u5927\u6a4b\u982d\u7ad9","optionEdu":[3,4,5,6],"period":0,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"wf9":{"desc":"","param":"wf9"},"wf26":{"desc":"","param":"wf26"},"landmark":{"desc":"\u8ddd\u6377\u904b\u5927\u6a4b\u982d\u7ad9\u7d04230\u516c\u5c3a"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20240916","applyCnt":1,"coIndustry":1001002004,"coIndustryDesc":"\u5176\u4ed6\u96fb\u4fe1\u53ca\u901a\u8a0a\u76f8\u95dc\u696d","custName":"\u53f0\u5317\u667a\u8c61\u4fe1\u606f\u6280\u8853\u80a1\u4efd\u6709\u9650\u516c\u53f8","custNo":"53091922000","description":"1. Requirement\n1) To survey and study test requirement\/criterion of mainstream applications.\n2) To process certification","descSnippet":"1. Requirement\n1) To survey and study [[[test]]] requirement\/criterion of mainstream applications.\n2) To process certification","mrtDist":0.5,"jobAddress":"\u6771\u8208\u8def59\u865f10\u6a13","jobAddrNo":6001001007,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u4fe1\u7fa9\u5340","jobName":"Certification Test Engineer \/ Lead","jobNameSnippet":"Certification [[[Test]]] Engineer \/ Lead","jobNo":"13855068","jobRo":1,"jobType":0,"lat":25.0474544,"lon":121.5667524,"link":{"job":"https:\/\/www.104.com.tw\/job\/88yn0","cust":"https:\/\/www.104.com.tw\/company\/oe1k574","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/88yn0?channel=104rpt"},"major":["\u82f1\u7f8e\u8a9e\u6587\u76f8\u95dc","\u8cc7\u8a0a\u5de5\u7a0b\u76f8\u95dc","\u5176\u4ed6\u6578\u5b78\u53ca\u96fb\u7b97\u6a5f\u79d1\u5b78\u76f8\u95dc"],"mrt":"99001003019","mrtDesc":"\u6377\u904b\u5357\u4eac\u4e09\u6c11\u7ad9","optionEdu":[3,4,5,6],"period":0,"remoteWorkType":0,"s10":50,"salaryHigh":55000,"salaryLow":33000,"tags":{"wf2":{"desc":"","param":"wf2"},"wf7":{"desc":"","param":"wf7"},"wf29":{"desc":"","param":"wf29"},"wf24":{"desc":"","param":"wf24"},"wf1":{"desc":"","param":"wf1"},"wf26":{"desc":"","param":"wf26"},"landmark":{"desc":"\u8ddd\u6377\u904b\u5357\u4eac\u4e09\u6c11\u7ad9\u7d04500\u516c\u5c3a"}},"s9":[1],"s5":0,"d3":"9:00~18:00","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241018","applyCnt":6,"coIndustry":1001001002,"coIndustryDesc":"\u96fb\u8166\u8edf\u9ad4\u670d\u52d9\u696d","custName":"\u7f8e\u5546\u5b89\u9081\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"96970927000","description":"-Test, validate and verify the AMI Products.\n-Embedded Linux Solution for Remote Server Management.\n-Study new and existing","descSnippet":"-[[[Test]]], validate and verify the AMI Products.\n-Embedded Linux Solution for Remote Server Management.\n-Study new and existing","mrtDist":0,"jobAddress":"\u65b0\u53f0\u4e94\u8def\u4e00\u6bb595\u865f36\u6a13","jobAddrNo":6001002004,"jobAddrNoDesc":"\u65b0\u5317\u5e02\u6c50\u6b62\u5340","jobName":"QA Test Engineer","jobNameSnippet":"QA [[[Test]]] Engineer","jobNo":"6605812","jobRo":1,"jobType":0,"lat":25.0620705,"lon":121.6485767,"link":{"job":"https:\/\/www.104.com.tw\/job\/3xl2s","cust":"https:\/\/www.104.com.tw\/company\/18jpzi54","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/3xl2s?channel=104rpt"},"major":["\u8cc7\u8a0a\u7ba1\u7406\u76f8\u95dc","\u8cc7\u8a0a\u5de5\u7a0b\u76f8\u95dc","\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[4,5],"period":3,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"wf10":{"desc":"","param":"wf10"},"wf9":{"desc":"","param":"wf9"},"wf7":{"desc":"","param":"wf7"},"wf8":{"desc":"","param":"wf8"},"wf4":{"desc":"","param":"wf4"},"wf30":{"desc":"","param":"wf30"},"wf29":{"desc":"","param":"wf29"},"wf3":{"desc":"","param":"wf3"}},"s9":[1],"s5":0,"d3":"09:00~18:00","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241018","applyCnt":0,"coIndustry":1001006002,"coIndustryDesc":"\u534a\u5c0e\u9ad4\u88fd\u9020\u696d","custName":"\u5fb7\u5dde\u5100\u5668\u5de5\u696d\u80a1\u4efd\u6709\u9650\u516c\u53f8","custNo":"33405832000","description":" Test Engineer, you will have the opportunity to work in a vibrant and dynamic team-oriented environment.\n\nWhat You Will Gain","descSnippet":" [[[Test]]] Engineer, you will have the opportunity to work in a vibrant and dynamic team-oriented environment.\n\nWhat You Will Gain","mrtDist":0.32,"jobAddress":"\u8208\u5357\u8def\u4e00\u6bb5142\u865f","jobAddrNo":6001002015,"jobAddrNoDesc":"\u65b0\u5317\u5e02\u4e2d\u548c\u5340","jobName":"[2024\u6b63\u8077]\u786c\u9ad4\u6e2c\u8a66\u5de5\u7a0b\u5e2b Test Engineer","jobNameSnippet":"[2024\u6b63\u8077]\u786c\u9ad4\u6e2c\u8a66\u5de5\u7a0b\u5e2b [[[Test]]] Engineer","jobNo":"13318438","jobRo":1,"jobType":2,"lat":24.9871227,"lon":121.5083809,"link":{"job":"https:\/\/www.104.com.tw\/job\/7xgkm","cust":"https:\/\/www.104.com.tw\/company\/fcgywxs","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/7xgkm?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc","\u5149\u96fb\u5de5\u7a0b\u76f8\u95dc"],"mrt":"99001004001","mrtDesc":"\u6377\u904b\u5357\u52e2\u89d2\u7ad9","optionEdu":[4,5],"period":0,"remoteWorkType":0,"s10":60,"salaryHigh":9999999,"salaryLow":1000000,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"wf2":{"desc":"","param":"wf2"},"wf7":{"desc":"","param":"wf7"},"wf9":{"desc":"","param":"wf9"},"wf12":{"desc":"","param":"wf12"},"wf4":{"desc":"","param":"wf4"},"wf13":{"desc":"","param":"wf13"},"wf18":{"desc":"","param":"wf18"},"wf29":{"desc":"","param":"wf29"},"wf1":{"desc":"","param":"wf1"},"wf30":{"desc":"","param":"wf30"},"wf27":{"desc":"","param":"wf27"},"wf17":{"desc":"","param":"wf17"},"wf26":{"desc":"","param":"wf26"},"wf10":{"desc":"","param":"wf10"},"wf24":{"desc":"","param":"wf24"},"wf25":{"desc":"","param":"wf25"},"wf28":{"desc":"","param":"wf28"},"wf35":{"desc":"","param":"wf35"},"landmark":{"desc":"\u8ddd\u6377\u904b\u5357\u52e2\u89d2\u7ad9\u7d04320\u516c\u5c3a"}},"s9":[1],"s5":0,"d3":"09:00~18:00","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241016","applyCnt":6,"coIndustry":1001001002,"coIndustryDesc":"\u96fb\u8166\u8edf\u9ad4\u670d\u52d9\u696d","custName":"Mphasis Taiwan_\u6fb3\u5927\u5229\u4e9e\u5546\u5b89\u5fa9\u4ed5\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"130000000137778","description":"Key Responsibilities of the IO Component Test Engineer:\n\uf09f\tBuild a test platform and install the operating system. (e.g.:","descSnippet":"Key Responsibilities of the IO Component [[[Test]]] Engineer:\n\uf09f\tBuild a [[[test]]] platform and install the operating system. (e.g.:","mrtDist":0,"jobAddress":"","jobAddrNo":6001001011,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u5357\u6e2f\u5340","jobName":"IO Component Test Engineer (BIOS OS)","jobNameSnippet":"IO Component [[[Test]]] Engineer (BIOS OS)","jobNo":"13309713","jobRo":1,"jobType":2,"lat":25.0312347,"lon":121.6111949,"link":{"job":"https:\/\/www.104.com.tw\/job\/7x9u9","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bkxma","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/7x9u9?channel=104rpt"},"major":["\u8cc7\u8a0a\u5de5\u7a0b\u76f8\u95dc","\u5176\u4ed6\u6578\u5b78\u53ca\u96fb\u7b97\u6a5f\u79d1\u5b78\u76f8\u95dc","\u8cc7\u8a0a\u7ba1\u7406\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[4,5],"period":3,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":[],"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241011","applyCnt":8,"coIndustry":1001006001,"coIndustryDesc":"IC\u8a2d\u8a08\u76f8\u95dc\u696d","custName":"Marvell_\u9081\u5a01\u723e\u79d1\u6280\u6709\u9650\u516c\u53f8","custNo":"12944742000","description":"105\u00b0C.\n\nJob Responsibilities:\n* Develop production and characterization ATE test programs and hardware.\n* Understand test","descSnippet":"105\u00b0C.\n\nJob Responsibilities:\n* Develop production and characterization ATE [[[test]]] programs and hardware.\n* Understand [[[test]]]","mrtDist":0,"jobAddress":"\u6216\u7af9\u5317","jobAddrNo":6001006002,"jobAddrNoDesc":"\u65b0\u7af9\u7e23\u7af9\u5317\u5e02","jobName":"Staff Engineer, Test Engineering","jobNameSnippet":"Staff Engineer, [[[Test]]] Engineering","jobNo":"12631000","jobRo":1,"jobType":2,"lat":24.831532,"lon":121.002672,"link":{"job":"https:\/\/www.104.com.tw\/job\/7iq54","cust":"https:\/\/www.104.com.tw\/company\/5y2yquo","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/7iq54?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[4,5],"period":6,"remoteWorkType":2,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"remote":{"desc":"\u9060\u7aef\u5de5\u4f5c"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241013","applyCnt":4,"coIndustry":1001006001,"coIndustryDesc":"IC\u8a2d\u8a08\u76f8\u95dc\u696d","custName":"Marvell_\u9081\u5a01\u723e\u79d1\u6280\u6709\u9650\u516c\u53f8","custNo":"12944742000","description":"\u2022 Test program programming\/ debugging\/ correlation\n\u2022 HVM Release to OSAT. Work with NPI Product & Test Engineering to","descSnippet":"\u2022 [[[Test]]] program programming\/ debugging\/ correlation\n\u2022 HVM Release to OSAT. Work with NPI Product & [[[Test]]] Engineering to","mrtDist":0,"jobAddress":"","jobAddrNo":6001006002,"jobAddrNoDesc":"\u65b0\u7af9\u7e23\u7af9\u5317\u5e02","jobName":"\u3010\u5be6\u7fd2\u751f_Test Engineering\u3011Intern, Test Engineering","jobNameSnippet":"\u3010\u5be6\u7fd2\u751f_[[[Test]]] Engineering\u3011Intern, [[[Test]]] Engineering","jobNo":"14308708","jobRo":1,"jobType":2,"lat":24.8346871,"lon":120.9933678,"link":{"job":"https:\/\/www.104.com.tw\/job\/8ioo4","cust":"https:\/\/www.104.com.tw\/company\/5y2yquo","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8ioo4?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[4,5],"period":0,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241014","applyCnt":9,"coIndustry":1001001002,"coIndustryDesc":"\u96fb\u8166\u8edf\u9ad4\u670d\u52d9\u696d","custName":"\u7f8e\u5546\u96f2\u9054\u570b\u969b\u79d1\u6280\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"130000000098842","description":"1. Response for Server hardware & software compatibility test, focus on activities in product development phases\n2. Own","descSnippet":"1. Response for Server hardware & software compatibility [[[test]]], focus on activities in product development phases\n2. Own","mrtDist":0.42,"jobAddress":"\u5712\u5340\u8857H\u68df3-2\u865f3\u6a13","jobAddrNo":6001001011,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u5357\u6e2f\u5340","jobName":"Server System Integration Test Engineer","jobNameSnippet":"Server System Integration [[[Test]]] Engineer","jobNo":"13639990","jobRo":1,"jobType":0,"lat":25.0567776,"lon":121.6119526,"link":{"job":"https:\/\/www.104.com.tw\/job\/84com","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bk3kq","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/84com?channel=104rpt"},"major":[],"mrt":"99001001024","mrtDesc":"\u6377\u904b\u5357\u6e2f\u5c55\u89bd\u9928\u7ad9","optionEdu":[3,4,5],"period":0,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"landmark":{"desc":"\u8ddd\u6377\u904b\u5357\u6e2f\u5c55\u89bd\u9928\u7ad9\u7d04420\u516c\u5c3a"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241017","applyCnt":10,"coIndustry":1001003001,"coIndustryDesc":"\u96fb\u8166\u53ca\u5176\u9031\u908a\u8a2d\u5099\u88fd\u9020\u696d","custName":"\u53f0\u7063\u806f\u60f3\u74b0\u7403\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8","custNo":"130000000112234","description":" system integration test engineer.\n\nPosition Requirements:\n\n\u2022 Review design documents (MRD, SPEC, etc.)\n\n\u2022 Identify and","descSnippet":" system integration [[[test]]] engineer.\n\nPosition Requirements:\n\n\u2022 Review design documents (MRD, SPEC, etc.)\n\n\u2022 Identify and","mrtDist":0.21,"jobAddress":"\u4e09\u91cd\u8def66\u865f8\u6a13","jobAddrNo":6001001011,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u5357\u6e2f\u5340","jobName":"SIT Test Engineer","jobNameSnippet":"SIT [[[Test]]] Engineer","jobNo":"14158747","jobRo":1,"jobType":2,"lat":25.0572956,"lon":121.6142977,"link":{"job":"https:\/\/www.104.com.tw\/job\/8fgyj","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bkdwq","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8fgyj?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc"],"mrt":"99001001024","mrtDesc":"\u6377\u904b\u5357\u6e2f\u5c55\u89bd\u9928\u7ad9","optionEdu":[4,5,6],"period":8,"remoteWorkType":2,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"remote":{"desc":"\u9060\u7aef\u5de5\u4f5c"},"wf2":{"desc":"","param":"wf2"},"wf34":{"desc":"","param":"wf34"},"wf12":{"desc":"","param":"wf12"},"wf9":{"desc":"","param":"wf9"},"wf11":{"desc":"","param":"wf11"},"wf13":{"desc":"","param":"wf13"},"wf8":{"desc":"","param":"wf8"},"wf24":{"desc":"","param":"wf24"},"wf35":{"desc":"","param":"wf35"},"wf7":{"desc":"","param":"wf7"},"wf10":{"desc":"","param":"wf10"},"wf26":{"desc":"","param":"wf26"},"wf4":{"desc":"","param":"wf4"},"wf28":{"desc":"","param":"wf28"},"landmark":{"desc":"\u8ddd\u6377\u904b\u5357\u6e2f\u5c55\u89bd\u9928\u7ad9\u7d04210\u516c\u5c3a"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20240808","applyCnt":4,"coIndustry":1001001003,"coIndustryDesc":"\u7db2\u969b\u7db2\u8def\u76f8\u95dc\u696d","custName":"\u65b0\u52a0\u5761\u5546\u79d1\u79d1\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"130000000201026","description":" reliable frameworks and automation tests to ensure product quality\n- Design reliable and efficient test automation processes to","descSnippet":" reliable frameworks and automation tests to ensure product quality\n- Design reliable and efficient [[[test]]] automation processes to","mrtDist":0,"jobAddress":"","jobAddrNo":6001001011,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u5357\u6e2f\u5340","jobName":"[Solutions Business] Software Development Engineer in Test","jobNameSnippet":"[Solutions Business] Software Development Engineer in [[[Test]]]","jobNo":"14141479","jobRo":1,"jobType":0,"lat":25.0312347,"lon":121.6111949,"link":{"job":"https:\/\/www.104.com.tw\/job\/8f3mv","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bmaf6","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8f3mv?channel=104rpt"},"major":[],"mrt":"","mrtDesc":"","optionEdu":[4,5,6],"period":0,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"wf7":{"desc":"","param":"wf7"},"wf26":{"desc":"","param":"wf26"},"wf24":{"desc":"","param":"wf24"},"wf9":{"desc":"","param":"wf9"},"wf14":{"desc":"","param":"wf14"},"wf8":{"desc":"","param":"wf8"},"wf4":{"desc":"","param":"wf4"},"wf30":{"desc":"","param":"wf30"},"wf2":{"desc":"","param":"wf2"},"wf29":{"desc":"","param":"wf29"},"wf34":{"desc":"","param":"wf34"},"wf1":{"desc":"","param":"wf1"},"wf10":{"desc":"","param":"wf10"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241001","applyCnt":8,"coIndustry":1011002002,"coIndustryDesc":"\u5efa\u7269\u88dd\u4fee\u53ca\u88dd\u6f62\u696d","custName":"\u7f8e\u5546\u798f\u723e\u66fc\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8\u53f0\u7063\u5206\u516c\u53f8","custNo":"130000000215095","description":" listed, we encourage you to still apply. \n\nEssential Duties and Responsibilities:\n\nThe Test Engineer is responsible for planning,","descSnippet":" listed, we encourage you to still apply. \n\nEssential Duties and Responsibilities:\n\nThe [[[Test]]] Engineer is responsible for planning,","mrtDist":0,"jobAddress":"\u5927\u540c\u8def\u4e00\u6bb5211\u865f","jobAddrNo":6001002004,"jobAddrNoDesc":"\u65b0\u5317\u5e02\u6c50\u6b62\u5340","jobName":"Test Engineer \u6e2c\u8a66\u5de5\u7a0b\u5e2b ","jobNameSnippet":"[[[Test]]] Engineer \u6e2c\u8a66\u5de5\u7a0b\u5e2b ","jobNo":"14233129","jobRo":1,"jobType":2,"lat":25.057578,"lon":121.6335463,"link":{"job":"https:\/\/www.104.com.tw\/job\/8h2cp","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bml9z","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8h2cp?channel=104rpt"},"major":[],"mrt":"","mrtDesc":"","optionEdu":[4,5,6],"period":0,"remoteWorkType":0,"s10":60,"salaryHigh":1200000,"salaryLow":1000000,"tags":{"wf12":{"desc":"","param":"wf12"},"wf29":{"desc":"","param":"wf29"},"wf26":{"desc":"","param":"wf26"},"wf4":{"desc":"","param":"wf4"},"wf7":{"desc":"","param":"wf7"},"wf10":{"desc":"","param":"wf10"},"wf1":{"desc":"","param":"wf1"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241018","applyCnt":5,"coIndustry":1001006001,"coIndustryDesc":"IC\u8a2d\u8a08\u76f8\u95dc\u696d","custName":"\u53f0\u7063\u7d22\u601d\u672a\u4f86\u79d1\u6280\u80a1\u4efd\u6709\u9650\u516c\u53f8","custNo":"130000000088279","description":"1.\tWork with head quarter team in Japan to develop Wafer\/IC test program. Verify testing program and machine for mass","descSnippet":"1.\tWork with head quarter team in Japan to develop Wafer\/IC [[[test]]] program. Verify testing program and machine for mass","mrtDist":0,"jobAddress":"","jobAddrNo":6001006003,"jobAddrNoDesc":"\u65b0\u7af9\u7e23\u6e56\u53e3\u9109","jobName":"(Branch) Test Engineer \/ Sr. Test Engineer","jobNameSnippet":"(Branch) [[[Test]]] Engineer \/ Sr. [[[Test]]] Engineer","jobNo":"11652071","jobRo":1,"jobType":0,"lat":24.8814458,"lon":121.0449768,"link":{"job":"https:\/\/www.104.com.tw\/job\/6xqsn","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bjvfb","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/6xqsn?channel=104rpt"},"major":["\u5de5\u7a0b\u5b78\u79d1\u985e"],"mrt":"","mrtDesc":"","optionEdu":[4,5,6],"period":6,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"wf8":{"desc":"","param":"wf8"},"wf10":{"desc":"","param":"wf10"},"wf13":{"desc":"","param":"wf13"},"wf25":{"desc":"","param":"wf25"},"wf29":{"desc":"","param":"wf29"},"wf33":{"desc":"","param":"wf33"},"wf1":{"desc":"","param":"wf1"},"wf31":{"desc":"","param":"wf31"},"wf3":{"desc":"","param":"wf3"},"wf12":{"desc":"","param":"wf12"},"wf24":{"desc":"","param":"wf24"},"wf7":{"desc":"","param":"wf7"}},"s9":[1],"s5":0,"d3":"","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20241018","applyCnt":5,"coIndustry":1001003001,"coIndustryDesc":"\u96fb\u8166\u53ca\u5176\u9031\u908a\u8a2d\u5099\u88fd\u9020\u696d","custName":"\u9e9f\u96f2\u6578\u64da\u79d1\u6280\u6709\u9650\u516c\u53f8","custNo":"130000000238863","description":"1. Response for Server hardware & software compatibility test, focus on activities in product development phases\n2. Own","descSnippet":"1. Response for Server hardware & software compatibility [[[test]]], focus on activities in product development phases\n2. Own","mrtDist":0.43,"jobAddress":"\u5712\u5340\u88573-1\u865f4\u6a13\u4e4b1(\u5357\u6e2f\u8edf\u9ad4\u5712\u5340\u5927\u6a13\u4e8c\u671fG\u68df)","jobAddrNo":6001001011,"jobAddrNoDesc":"\u53f0\u5317\u5e02\u5357\u6e2f\u5340","jobName":"System Integration Test","jobNameSnippet":"System Integration [[[Test]]]","jobNo":"14300933","jobRo":1,"jobType":0,"lat":25.0574271,"lon":121.6120274,"link":{"job":"https:\/\/www.104.com.tw\/job\/8iio5","cust":"https:\/\/www.104.com.tw\/company\/1a2x6bn3m7","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/8iio5?channel=104rpt"},"major":[],"mrt":"99001001024","mrtDesc":"\u6377\u904b\u5357\u6e2f\u5c55\u89bd\u9928\u7ad9","optionEdu":[1,2,3,4,5,6],"period":4,"remoteWorkType":2,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"remote":{"desc":"\u9060\u7aef\u5de5\u4f5c"},"wf1":{"desc":"","param":"wf1"},"wf3":{"desc":"","param":"wf3"},"wf8":{"desc":"","param":"wf8"},"wf31":{"desc":"","param":"wf31"},"wf7":{"desc":"","param":"wf7"},"wf26":{"desc":"","param":"wf26"},"wf2":{"desc":"","param":"wf2"},"wf10":{"desc":"","param":"wf10"},"wf34":{"desc":"","param":"wf34"},"landmark":{"desc":"\u8ddd\u6377\u904b\u5357\u6e2f\u5c55\u89bd\u9928\u7ad9\u7d04430\u516c\u5c3a"}},"s9":[1],"s5":0,"d3":"10~19\u9ede","isSave":null,"applyDate":null,"isApply":null},{"appearDate":"20240805","applyCnt":3,"coIndustry":1001006002,"coIndustryDesc":"\u534a\u5c0e\u9ad4\u88fd\u9020\u696d","custName":"OmniVision_\u53f0\u7063\u8c6a\u5a01\u79d1\u6280\u6709\u9650\u516c\u53f8","custNo":"28566098000","description":" and other related testing solutions. \n\n\u3010Responsibilities\u3011\t\u3000\n1. Create test solution validation tool\n2. HMI (Human Machine","descSnippet":" and other related testing solutions. \n\n\u3010Responsibilities\u3011\t\u3000\n1. Create [[[test]]] solution validation tool\n2. HMI (Human Machine","mrtDist":0,"jobAddress":"\u516c\u9053\u4e94\u8def\u4e8c\u6bb5101\u865f12\u6a13\u4e4b1","jobAddrNo":6001006001,"jobAddrNoDesc":"\u65b0\u7af9\u5e02","jobName":"(Staff\/Sr.) Test Integration Engineer (Software Integration)","jobNameSnippet":"(Staff\/Sr.) [[[Test]]] Integration Engineer (Software Integration)","jobNo":"13823911","jobRo":1,"jobType":0,"lat":24.798331,"lon":121.0064864,"link":{"job":"https:\/\/www.104.com.tw\/job\/88alj","cust":"https:\/\/www.104.com.tw\/company\/d4fima8","applyAnalyze":"https:\/\/www.104.com.tw\/jobs\/apply\/analysis\/88alj?channel=104rpt"},"major":["\u96fb\u6a5f\u96fb\u5b50\u5de5\u7a0b\u76f8\u95dc"],"mrt":"","mrtDesc":"","optionEdu":[5,6],"period":6,"remoteWorkType":0,"s10":10,"salaryHigh":0,"salaryLow":0,"tags":{"zoneForeign":{"desc":"\u5916\u5546\u516c\u53f8","param":5},"wf7":{"desc":"","param":"wf7"},"wf9":{"desc":"","param":"wf9"},"wf24":{"desc":"","param":"wf24"},"wf2":{"desc":"","param":"wf2"},"wf1":{"desc":"","param":"wf1"},"wf10":{"desc":"","param":"wf10"}},"s9":[1],"s5":0,"d3":"09:00~18:00","isSave":null,"applyDate":null,"isApply":null}],"metadata":{"pagination":{"count":22,"currentPage":1,"lastPage":150,"total":4486},"filterQuery":{"order":15,"asc":0,"keyword":"test","fz":8,"kwop":7,"ro":[0],"scstrict":0,"scneg":0,"page":1,"pagesize":20},"personalBoost":0,"companyKeyword":false}} -------------------------------------------------------------------------------- /general/tests/json_pchome.txt: -------------------------------------------------------------------------------- 1 | {"QTime":28,"totalRows":584,"totalPage":30,"range":{"min":"","max":""},"cateName":"","q":"test","subq":"","token":["test"],"isMust":1,"prods":[{"Id":"DDAH2K-A900APYK9","cateId":"DDAHA3","picS":"\/items\/DDAH2KA900APYK9\/000002_1592447678.jpg","picB":"\/items\/DDAH2KA900APYK9\/000001_1592447678.jpg","name":"Esprit Horizon \u5730\u5e73\u7dda\u7537\u6027\u6de1\u9999\u6c34 75ml Test \u5305\u88dd","describe":"Esprit Horizon \u5730\u5e73\u7dda\u7537\u6027\u6de1\u9999\u6c34 75ml Test \u5305\u88dd\\r\\n","price":999,"originPrice":999,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAGE8-A900APN6D","cateId":"DYAGHY","picS":"\/items\/DYAGE8A900APN6D\/000002_1591943560.jpg","picB":"\/items\/DYAGE8A900APN6D\/000001_1591943560.jpg","name":"\u3010o-one\u3011HTC D20 Pro \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u660e)","describe":"HTC D20 Pro \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u660e)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DEAC2I-A900APJYB","cateId":"DEAC2I","picS":"\/items\/DEAC2IA900APJYB\/000002_1591860666.jpg","picB":"\/items\/DEAC2IA900APJYB\/000001_1591860666.jpg","name":"KONQOR\u300c150mm\u300d\u5feb\u6e2c\u6578\u986f\u6e38\u6a19\u5361\u5c3a","describe":"KONQOR\u300c150mm\u300d\u5feb\u6e2c\u6578\u986f\u6e38\u6a19\u5361\u5c3a\uff0c\u901f\u6e2c\u901f\u986f\uff01\\r\\n\u2605\u539a\u5ea6\u6e2c\u91cf\uff0c\u5c08\u696d\u7cbe\u6e96\u3002\r\n\u2605\u5167\u5f91\u5916\u5f91\uff0c\u901f\u6e2c\u901f\u986f \u3002\r\n\u2605\u6578\u4f4d\u986f\u793a\uff0c\u6e05\u6670\u6613\u898b\u3002\r\n\u2605\u76d2\u88dd\u6536\u7d0d\uff0c\u651c\u5e36\u65b9\u4fbf\u3002","price":249,"originPrice":249,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAG68-A900APC24","cateId":"DYAG68","picS":"\/items\/DYAG68A900APC24\/000002_1591606038.jpg","picB":"\/items\/DYAG68A900APC24\/000001_1591606038.jpg","name":"\u3010o-one\u3011SUGAR T20 \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u660e)","describe":"SUGAR T20 \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u660e)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DGBJ88-A900AP4AW","cateId":"DGBJ88","picS":"\/items\/DGBJ88A900AP4AW\/000002_1591250669.jpg","picB":"\/items\/DGBJ88A900AP4AW\/000001_1591250669.jpg","name":"PS4\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149 2\u300b\u4e2d\u6587\u9650\u5b9a\u7248","describe":"\u767c\u552e\u65e5\ufe312020-7-16 \u3010\u9810\u8cfc\u4e2d\u3011PS4\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149 2\u300b\u4e2d\u6587\u9650\u5b9a\u7248\\r\\n\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u7cfb\u5217\u6700\u65b0\u4f5c!!\r\n\u2589 \u5ef6\u7e8c\u524d\u4f5c\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u73fe\u5be6\u7bc7\u540c\u4e00\u4e16\u754c\r\n\u2589 \u8207\u5973\u4e3b\u89d2\u4e00\u540c\u8abf\u67e5\u795e\u79d8\u5931\u8e64\u6848\uff0c\u4ee5\u53ca\u85cf\u5728\u80cc\u5f8c\u7684\u9670\u8b00\r\n\u2589 \u5168\u65b0\u7684\u89d2\u8272\u9663\u5bb9\u5916\uff0c\u524d\u4f5c\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u7684\u89d2\u8272\u5011\u4e5f\u5c07\u9678\u7e8c\u767b\u5834\r\n\u2589 \u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u4e2d\u5145\u6eff\u7279\u8272\u4ee5\u53ca\u885d\u64ca\u7684\u300c\u6b7b\u4ea1\u7d50\u5c40\u300d\u65bc\u672c\u4f5c\u4e5f\u6beb\u7121\u4fdd\u7559\u4e26\u4e14\u5f37\u5316\u7e7c\u627f","price":2990,"originPrice":2990,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DGBJ88-A900AP4AV","cateId":"DGBJ88","picS":"\/items\/DGBJ88A900AP4AV\/000002_1591250651.jpg","picB":"\/items\/DGBJ88A900AP4AV\/000001_1591250651.jpg","name":"PS4\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149 2\u300b\u4e2d\u6587\u4e00\u822c\u7248","describe":"\u767c\u552e\u65e5\ufe312020-7-16 \u3010\u9810\u8cfc\u4e2d\u3011PS4\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149 2\u300b\u4e2d\u6587\u4e00\u822c\u7248\\r\\n\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u7cfb\u5217\u6700\u65b0\u4f5c!!\r\n\u2589 \u5ef6\u7e8c\u524d\u4f5c\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u73fe\u5be6\u7bc7\u540c\u4e00\u4e16\u754c\r\n\u2589 \u8207\u5973\u4e3b\u89d2\u4e00\u540c\u8abf\u67e5\u795e\u79d8\u5931\u8e64\u6848\uff0c\u4ee5\u53ca\u85cf\u5728\u80cc\u5f8c\u7684\u9670\u8b00\r\n\u2589 \u5168\u65b0\u7684\u89d2\u8272\u9663\u5bb9\u5916\uff0c\u524d\u4f5c\u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u7684\u89d2\u8272\u5011\u4e5f\u5c07\u9678\u7e8c\u767b\u5834\r\n\u2589 \u300a\u6b7b\u4ea1\u7d42\u5c40 \u8f2a\u8ff4\u8a66\u7149\u300b\u4e2d\u5145\u6eff\u7279\u8272\u4ee5\u53ca\u885d\u64ca\u7684\u300c\u6b7b\u4ea1\u7d50\u5c40\u300d\u65bc\u672c\u4f5c\u4e5f\u6beb\u7121\u4fdd\u7559\u4e26\u4e14\u5f37\u5316\u7e7c\u627f","price":1790,"originPrice":1790,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DJAA2V-A900AOV8S","cateId":"DJAA1Z","picS":"\/items\/DJAA2VA900AOV8S\/000001_1590984770.jpg","picB":"\/items\/DJAA2VA900AOV8S\/000001_1590984770.jpg","name":"Android TDD\u6e2c\u8a66\u9a45\u52d5\u958b\u767c\uff1a\u5f9eUnitTest\u3001TDD\u5230DevOps\u5be6\u8e10\uff08iT\u90a6\u5e6b\u5fd9\u9435\u4eba\u8cfd\u7cfb\u5217\u66f8\uff09","describe":"Android TDD\u6e2c\u8a66\u9a45\u52d5\u958b\u767c\uff1a\u5f9eUnitTest\u3001TDD\u5230DevOps\u5be6\u8e10\uff08iT\u90a6\u5e6b\u5fd9\u9435\u4eba\u8cfd\u7cfb\u5217\u66f8\uff09\\r\\n","price":435,"originPrice":435,"author":"\u9673\u745e\u5fe0","brand":"\u535a\u78a9\u6587\u5316","publishDate":"2020\/06\/04","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAG68-A900AOS94","cateId":"DYAG68","picS":"\/items\/DYAG68A900AOS94\/000002_1590734608.jpg","picB":"\/items\/DYAG68A900AOS94\/000001_1590734608.jpg","name":"\u3010o-one\u3011SUGAR T30 \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u660e)","describe":"SUGAR T30 \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DDAH1Q-A900AOPC5","cateId":"DDAH1Q","picS":"\/items\/DDAH1QA900AOPC5\/000002_1590645860.jpg","picB":"\/items\/DDAH1QA900AOPC5\/000001_1590645860.jpg","name":"Dolce & Gabbana Light Blue \u6dfa\u85cd\u6de1\u9999\u6c34 100ml Test \u5305\u88dd","describe":"Dolce & Gabbana Light Blue \u6dfa\u85cd\u6de1\u9999\u6c34 100ml Test \u5305\u88dd\\r\\n","price":1699,"originPrice":1699,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAGHU-A900AOPAJ","cateId":"DYAGHU","picS":"\/items\/DYAGHUA900AOPAJ\/000002_1590645444.jpg","picB":"\/items\/DYAGHUA900AOPAJ\/000001_1590645444.jpg","name":"\u3010o-one\u3011SONY Xperia1 II \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u9ed1)","describe":"SONY Xperia1 II \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u9ed1)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAGHU-A900AOPAZ","cateId":"DYAGHU","picS":"\/items\/DYAGHUA900AOPAZ\/000002_1590645378.jpg","picB":"\/items\/DYAGHUA900AOPAZ\/000001_1590645378.jpg","name":"\u3010o-one\u3011SONY Xperia1 II \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u660e)","describe":"SONY Xperia1 II \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u660e)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DDAH8T-A900AOFKB","cateId":"DDAH8T","picS":"\/items\/DDAH8TA900AOFKB\/000002_1590371113.jpg","picB":"\/items\/DDAH8TA900AOFKB\/000001_1590371113.jpg","name":"Paul Smith Rose \u73ab\u7470\u5973\u6027\u6de1\u9999\u7cbe 100ml Test \u5305\u88dd","describe":"Paul Smith Rose \u73ab\u7470\u5973\u6027\u6de1\u9999\u7cbe 100ml Test \u5305\u88dd\\r\\n","price":888,"originPrice":888,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DMAAG6-A900AODFC","cateId":"DMAAG6","picS":"\/items\/DMAAG6A900AODFC\/000001_1590140018.jpg","picB":"\/items\/DMAAG6A900AODFC\/000001_1590140018.jpg","name":"\u624b\u6234\u5f0f\u76e3\u63a7\u6e2c\u8a66\u87a2\u5e55 4K VCT-8508","describe":"5\u540b 4K 800\u842c AHD TVI CVI \u985e\u6bd4 5MP 4MP 1080P \u87a2\u5e55 \u76e3\u63a7 \u5f71\u50cf \u7db2\u8def \u96fb\u6e90 \u6e2c\u8a66 \u8072\u97f3 \u986f\u793a\u5668 \u5de5\u7a0b\u5bf6 \u542b\u7a05\\r\\n\u25cf\u652f\u63f4ahd tvi cvi \u985e\u6bd4 \u8a0a\u865f\u6700\u9ad8\u53ef\u90544k\r\n\u25cf\u5f71\u50cf \u8072\u97f3 \u7db2\u8def\u7dda\u6e2c\u8a66\r\n\u25cf\u5373\u6642\u65bd\u5de5\u5373\u6642\u76e3\u770b\u8d85\u8f15\u9b06\r\n\u25cf\u5167\u5efa4000mah\u5927\u5bb9\u91cf\u92f0\u96fb\u6c60\u8d85\u5b89\u5fc3\r\n\u25cf\u53ef\u76f4\u63a5\u4f9b\u96fb\u651d\u5f71\u6a5f\u5de5\u4f5c\r\n\u25cf\u5168\u65b0\u78c1\u9435\u76d2\u5f37\u5316\uff0c\u65bd\u5de5\u66f4\u65b9\u4fbf","price":3186,"originPrice":3186,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":["C019368","C019369","C019367"],"BU":"ec"},{"Id":"DYAGH1-A900AOC31","cateId":"DYAGH1","picS":"\/items\/DYAGH1A900AOC31\/000002_1590128114.jpg","picB":"\/items\/DYAGH1A900AOC31\/000001_1590128114.jpg","name":"\u3010o-one\u3011SAMSUNG A21S \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u9ed1)","describe":"SAMSUNG A21S \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u9ed1)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAGH1-A900AOC38","cateId":"DYAGH1","picS":"\/items\/DYAGH1A900AOC38\/000002_1590128069.jpg","picB":"\/items\/DYAGH1A900AOC38\/000001_1590128069.jpg","name":"\u3010o-one\u3011SAMSUNG A21S \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u660e)","describe":"SAMSUNG A21S \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u660e)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAG5S-A900ANSXC","cateId":"DYAG5S","picS":"\/items\/DYAG5SA900ANSXC\/000002_1589532359.jpg","picB":"\/items\/DYAG5SA900ANSXC\/000001_1589532359.jpg","name":"\u3010o-one\u3011NOKIA 5.3 \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u660e)","describe":"NOKIA 5.3 \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u660e)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAGH1-A900ANQMY","cateId":"DYAGH1","picS":"\/items\/DYAGH1A900ANQMY\/000002_1589440348.jpg","picB":"\/items\/DYAGH1A900ANQMY\/000001_1589440348.jpg","name":"\u3010o-one\u3011SAMSUNG A31 \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u9ed1)","describe":"SAMSUNG A31 \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u9ed1)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DYAGH1-A900ANQM8","cateId":"DYAGH1","picS":"\/items\/DYAGH1A900ANQM8\/000002_1589440280.jpg","picB":"\/items\/DYAGH1A900ANQM8\/000001_1589440280.jpg","name":"\u3010o-one\u3011SAMSUNG A31 \u7f8e\u570b\u8ecd\u4e8b\u898f\u7bc4\u9632\u6454\u6e2c\u8a66-\u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc(\u900f\u660e)","describe":"SAMSUNG A31 \u8ecd\u529f\u9632\u6454\u624b\u6a5f\u6bbc \u4e94\u500d\u8d85\u5f37\u6297\u649e\u529b(\u900f\u660e)\\r\\n\u2605\u7f8e\u570b\u8ecd\u4e8b\u7d1a\u6a19\u6e96\u9632\u6454\u6e2c\u8a66\uff1a \r\n\u3000\u9ad8\u5ea6122cm\uff0c6\u97628\u89d212\u908a\uff0c\u517126\u4e0b\uff0c\u81ea\u7531\u843d\u9ad4\u6454\u6a5f\u6e2c\u8a66 \r\n\u2605\u6b50\u76df\u6a19\u6e96-\u74b0\u4fdd\u7121\u6bd2\u6aa2\u6e2c\u901a\u904e \r\n\u2605\u56db\u89d2\u52a0\u5f37\u6c23\u588a\u3001\u588a\u9ad8\u8a2d\u8a08 \r\n\u2605\u6b63\u6454\uff01\u5074\u6454\uff01\u7206\u6454\uff01\u901a\u901a\u4e0d\u7528\u6015\uff01 \r\n\u2605\u771f\u6b63\u7684\u786c\u6f22\u7b49\u7d1a\u9632\u649e\u9632\u6454\u624b\u6a5f\u6bbc\uff01","price":450,"originPrice":450,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":[],"BU":"ec"},{"Id":"DAAJGD-A900ANCMB","cateId":"DAAJGD","picS":"\/items\/DAAJGDA900ANCMB\/000002_1588901962.jpg","picB":"\/items\/DAAJGDA900ANCMB\/000001_1588901962.jpg","name":"\u82b1\u8a9e\u6b3e \u8a66\u7ba1\u9020\u578b\u9999\u82ac\u80a5\u7682\u7247 6\u5165(\u6bcf\u5165300\u7247)","describe":"\u82b1\u8a9e\u6b3e \u8a66\u7ba1\u9020\u578b\u9999\u82ac\u80a5\u7682\u7247 6\u5165\u4e00\u7d44 \u4e00\u5165300\u7247 \u74b0\u4fdd\u7121\u6bd2 \u4e7e\u6de8\u6e05\u6f54 \u591a\u7a2e\u9999\u82ac\u6c23\u5473\\r\\n\u2605 \u6bcf\u96bb\u8a66\u7ba1\u7d04300\u7247\u6d17\u624b\u7247\r\n\u2605 \u591a\u7a2e\u6c34\u679c\u9999\u82ac\u6c23\u5473\uff0c\u6e05\u6f54\u6d17\u6de8\r\n\u2605 \u74b0\u4fdd\u7121\u6bd2\u6750\u8cea\r\n\u2605 \u6b64\u5546\u54c1\u70ba6\u5165\u4e00\u5957","price":199,"originPrice":199,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":["C019344"],"BU":"ec"},{"Id":"DAAJGD-A900ANCMA","cateId":"DAAJGD","picS":"\/items\/DAAJGDA900ANCMA\/000002_1588901908.jpg","picB":"\/items\/DAAJGDA900ANCMA\/000001_1588901908.jpg","name":"\u4ed9\u4eba\u638c\u6b3e \u8a66\u7ba1\u9020\u578b\u9999\u82ac\u80a5\u7682\u7247 6\u5165(\u6bcf\u5165300\u7247)","describe":"\u4ed9\u4eba\u638c\u6b3e \u8a66\u7ba1\u9020\u578b\u9999\u82ac\u80a5\u7682\u7247 6\u5165\u4e00\u7d44 \u4e00\u5165300\u7247 \u74b0\u4fdd\u7121\u6bd2 \u4e7e\u6de8\u6e05\u6f54 \u591a\u7a2e\u9999\u82ac\u6c23\u5473\\r\\n\u2605 \u6bcf\u96bb\u8a66\u7ba1\u7d04300\u7247\u6d17\u624b\u7247\r\n\u2605 \u591a\u7a2e\u6c34\u679c\u9999\u82ac\u6c23\u5473\uff0c\u6e05\u6f54\u6d17\u6de8\r\n\u2605 \u74b0\u4fdd\u7121\u6bd2\u6750\u8cea\r\n\u2605 \u6b64\u5546\u54c1\u70ba6\u5165\u4e00\u5957","price":199,"originPrice":199,"author":"","brand":"","publishDate":"","sellerId":"","isPChome":1,"isNC17":0,"couponActid":["C019344"],"BU":"ec"}]} -------------------------------------------------------------------------------- /general/tests/json_pchome_lightnovel.txt: -------------------------------------------------------------------------------- 1 | try{jsonp_prodlist([{"Id":"DJAH2O-A900AQCJQ-000","Nick":"\uff08\u8f15\u5c0f\u8aaa\uff09Bon appétit\uff01\u7f8e\u5473\u60c5\u8a71\uff08\u5168\uff09\uff08\u9650\uff09\u62c6\u5c01\u4e0d\u9000","Pic":{"B":"\/items\/DJAH2OA900AQCJQ\/000001_1592904738.jpg","S":"\/items\/DJAH2OA900AQCJQ\/000001_1592904738.jpg"},"Price":{"M":200,"P":180,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u8f15\u5c0f\u8aaa\uff09Bon app?tit\uff01\u7f8e\u5473\u60c5\u8a71\uff08\u5168\uff09\uff08\u9650\uff09\u62c6\u5c01\u4e0d\u9000","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQA59-000","Nick":"\uff08\u8f15\u6587\u5b78\uff0915\u6b72\u7684\u6050\u6016\u5206\u5b50","Pic":{"B":"\/items\/DJAH2OA900AQA59\/000001_1592876539.jpg","S":"\/items\/DJAH2OA900AQA59\/000001_1592876539.jpg"},"Price":{"M":260,"P":205,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u8f15\u6587\u5b78\uff0915\u6b72\u7684\u6050\u6016\u5206\u5b50","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQA1T-000","Nick":"\uff08\u8f15\u5c0f\u8aaa\uff09\u718a\u718a\u52c7\u95d6\u7570\u4e16\u754c\uff0810\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","Pic":{"B":"\/items\/DJAH2OA900AQA1T\/000001_1592827603.jpg","S":"\/items\/DJAH2OA900AQA1T\/000001_1592827603.jpg"},"Price":{"M":250,"P":225,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u8f15\u5c0f\u8aaa\uff09\u718a\u718a\u52c7\u95d6\u7570\u4e16\u754c\uff0810\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQA25-000","Nick":"\uff08\u8f15\u5c0f\u8aaa\uff09Fate\/Apocrypha\uff085\uff09\u300c\u90aa\u9f8d\u8207\u8056\u5973\u300d\uff08\u5b8c\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","Pic":{"B":"\/items\/DJAH2OA900AQA25\/000001_1592827519.jpg","S":"\/items\/DJAH2OA900AQA25\/000001_1592827519.jpg"},"Price":{"M":320,"P":288,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u8f15\u5c0f\u8aaa\uff09Fate\/Apocrypha\uff085\uff09\u300c\u90aa\u9f8d\u8207\u8056\u5973\u300d\uff08\u5b8c\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQA07-000","Nick":"\uff08\u8f15\u5c0f\u8aaa\uff09\u98df\u93fd\u672b\u4e16\u9304\uff083\uff09\u90fd\u5e02\u751f\u547d\u9ad4\u300c\u6771\u4eac\u300d\uff08\u62c6\u5c01\u4e0d\u53ef\u9000\uff09","Pic":{"B":"\/items\/DJAH2OA900AQA07\/000001_1592876474.jpg","S":"\/items\/DJAH2OA900AQA07\/000001_1592876474.jpg"},"Price":{"M":240,"P":216,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u8f15\u5c0f\u8aaa\uff09\u98df\u93fd\u672b\u4e16\u9304\uff083\uff09\u90fd\u5e02\u751f\u547d\u9ad4\u300c\u6771\u4eac\u300d\uff08\u62c6\u5c01\u4e0d\u53ef\u9000\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQA03-000","Nick":"\uff08\u8f15\u5c0f\u8aaa\uff09\u9019\u662f\u59b3\u8207\u6211\u7684\u6700\u5f8c\u6230\u5834\uff0c\u6216\u662f\u958b\u5275\u4e16\u754c\u7684\u8056\u6230\uff084\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","Pic":{"B":"\/items\/DJAH2OA900AQA03\/000001_1592875469.jpg","S":"\/items\/DJAH2OA900AQA03\/000001_1592875469.jpg"},"Price":{"M":220,"P":198,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u8f15\u5c0f\u8aaa\uff09\u9019\u662f\u59b3\u8207\u6211\u7684\u6700\u5f8c\u6230\u5834\uff0c\u6216\u662f\u958b\u5275\u4e16\u754c\u7684\u8056\u6230\uff084\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQ9ZG-000","Nick":"\uff08\u8f15\u5c0f\u8aaa\uff09\u6200\u611b\u81f3\u4e0a\u90fd\u5e02\u7684\u96d9\u9a0e\u58eb\uff083\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","Pic":{"B":"\/items\/DJAH2OA900AQ9ZG\/000001_1592876473.jpg","S":"\/items\/DJAH2OA900AQ9ZG\/000001_1592876473.jpg"},"Price":{"M":200,"P":180,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u8f15\u5c0f\u8aaa\uff09\u6200\u611b\u81f3\u4e0a\u90fd\u5e02\u7684\u96d9\u9a0e\u58eb\uff083\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQ9WY-000","Nick":"\uff08\u7279\u88dd\u7248\uff0d\u8cb7\u65b7\uff09\uff08\u8f15\u5c0f\u8aaa\uff09\u9019\u662f\u59b3\u8207\u6211\u7684\u6700\u5f8c\u6230\u5834\uff0c\u6216\u662f\u958b\u5275\u4e16\u754c\u7684\u8056\u6230\uff084\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","Pic":{"B":"\/items\/DJAH2OA900AQ9WY\/000001_1592876328.jpg","S":"\/items\/DJAH2OA900AQ9WY\/000001_1592876328.jpg"},"Price":{"M":550,"P":550,"Prime":""},"Discount":0,"isSpec":0,"Name":"\uff08\u7279\u88dd\u7248\uff0d\u8cb7\u65b7\uff09\uff08\u8f15\u5c0f\u8aaa\uff09\u9019\u662f\u59b3\u8207\u6211\u7684\u6700\u5f8c\u6230\u5834\uff0c\u6216\u662f\u958b\u5275\u4e16\u754c\u7684\u8056\u6230\uff084\uff09\u62c6\u5c01\u4e0d\u53ef\u9000","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQ01P-000","Nick":"\u8863\u624b\u906e\u5929\uff08\u516d\uff09","Pic":{"B":"\/items\/DJAH2OA900AQ01P\/000001_1592467436.jpg","S":"\/items\/DJAH2OA900AQ01P\/000001_1592467436.jpg"},"Price":{"M":250,"P":198,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u8863\u624b\u906e\u5929\uff08\u516d\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQ01K-000","Nick":"\u8863\u624b\u906e\u5929\uff08\u4e94\uff09","Pic":{"B":"\/items\/DJAH2OA900AQ01K\/000001_1592467436.jpg","S":"\/items\/DJAH2OA900AQ01K\/000001_1592467436.jpg"},"Price":{"M":250,"P":198,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u8863\u624b\u906e\u5929\uff08\u4e94\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900APW5K-000","Nick":"\u661f\u969b\u9996\u5e2d\u6aa2\u5bdf\u5b98\uff0803\uff09","Pic":{"B":"\/items\/DJAH2OA900APW5K\/000001_1592373924.jpg","S":"\/items\/DJAH2OA900APW5K\/000001_1592373924.jpg"},"Price":{"M":220,"P":174,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u661f\u969b\u9996\u5e2d\u6aa2\u5bdf\u5b98\uff0803\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900APW5E-000","Nick":"A\u5b50\u4e0d\u6703\u9810\u8a00\u81ea\u5df1\u6b7b\u4ea1\uff0801\uff09","Pic":{"B":"\/items\/DJAH2OA900APW5E\/000001_1592373923.jpg","S":"\/items\/DJAH2OA900APW5E\/000001_1592373923.jpg"},"Price":{"M":220,"P":174,"Prime":""},"Discount":0,"isSpec":0,"Name":"A\u5b50\u4e0d\u6703\u9810\u8a00\u81ea\u5df1\u6b7b\u4ea1\uff0801\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900APLXW-000","Nick":"\u5927\u7b26\u7bc6\u5e2b\uff08\u4e09\u5341\u4e94\uff09\u798d\u8d77\u856d\u7246","Pic":{"B":"\/items\/DJAH2OA900APLXW\/000001_1591929625.jpg","S":"\/items\/DJAH2OA900APLXW\/000001_1591929625.jpg"},"Price":{"M":180,"P":142,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u5927\u7b26\u7bc6\u5e2b\uff08\u4e09\u5341\u4e94\uff09\u798d\u8d77\u856d\u7246","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900APLY1-000","Nick":"\u9f4a\u6b61\uff087\uff09","Pic":{"B":"\/items\/DJAH2OA900APLY1\/000001_1591929625.jpg","S":"\/items\/DJAH2OA900APLY1\/000001_1591929625.jpg"},"Price":{"M":250,"P":198,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u9f4a\u6b61\uff087\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900APLY3-000","Nick":"\u9f4a\u6b61\uff088\uff09","Pic":{"B":"\/items\/DJAH2OA900APLY3\/000001_1591929625.jpg","S":"\/items\/DJAH2OA900APLY3\/000001_1591929625.jpg"},"Price":{"M":250,"P":198,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u9f4a\u6b61\uff088\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900APLXY-000","Nick":"\u9f8d\u57ce\uff08\u5341\uff09\u5168\u9762\u53cd\u653b","Pic":{"B":"\/items\/DJAH2OA900APLXY\/000001_1591929625.jpg","S":"\/items\/DJAH2OA900APLXY\/000001_1591929625.jpg"},"Price":{"M":180,"P":142,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u9f8d\u57ce\uff08\u5341\uff09\u5168\u9762\u53cd\u653b","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900APLXU-000","Nick":"\u6ec4\u5143\u5716\uff08\u5341\u4e09\uff09\u5996\u65cf\u5165\u4fb5","Pic":{"B":"\/items\/DJAH2OA900APLXU\/000001_1591929625.jpg","S":"\/items\/DJAH2OA900APLXU\/000001_1591929625.jpg"},"Price":{"M":180,"P":142,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u6ec4\u5143\u5716\uff08\u5341\u4e09\uff09\u5996\u65cf\u5165\u4fb5","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQ1VW-000","Nick":"\u5f90\u79d8\u66f8\u628a\u7e3d\u88c1\u96e2\u4e86\uff08\u9650\uff09","Pic":{"B":"\/items\/DJAH2OA900AQ1VW\/000001_1592537717.jpg","S":"\/items\/DJAH2OA900AQ1VW\/000001_1592537717.jpg"},"Price":{"M":190,"P":150,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u5f90\u79d8\u66f8\u628a\u7e3d\u88c1\u96e2\u4e86\uff08\u9650\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQ1VN-000","Nick":"\u9738\u7e3d\u7684\u5e8a\u4f34\u5951\u7d04\uff08\u9650\uff09","Pic":{"B":"\/items\/DJAH2OA900AQ1VN\/000001_1592537837.jpg","S":"\/items\/DJAH2OA900AQ1VN\/000001_1592537837.jpg"},"Price":{"M":190,"P":150,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u9738\u7e3d\u7684\u5e8a\u4f34\u5951\u7d04\uff08\u9650\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1},{"Id":"DJAH2O-A900AQ1UW-000","Nick":"\u62d0\u7e3d\u88c1\u5077\u751f\u4e00\u500b\u5bf6\uff08\u9650\uff09","Pic":{"B":"\/items\/DJAH2OA900AQ1UW\/000001_1592537837.jpg","S":"\/items\/DJAH2OA900AQ1UW\/000001_1592537837.jpg"},"Price":{"M":190,"P":150,"Prime":""},"Discount":0,"isSpec":0,"Name":"\u62d0\u7e3d\u88c1\u5077\u751f\u4e00\u500b\u5bf6\uff08\u9650\uff09","isCarrier":0,"isSnapUp":0,"isBigCart":1}]);}catch(e){if(window.console){console.log(e);}} -------------------------------------------------------------------------------- /general/tests/json_yourator.txt: -------------------------------------------------------------------------------- 1 | {"total":150,"jobs":[{"id":25520,"name":"後端工程師","path":"/companies/Playalab/jobs/25520","category":{"id":23,"name":"後端工程","jobs_count":1145,"job_type":"technical_job","isco_code":"15-1252.00","priority":1,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"23"},"tags":[{"id":174,"name":"blockchain","jobs_count":250,"created_at":"2020-10-07T14:48:45.000+08:00","updated_at":"2020-10-07T14:48:45.000+08:00"},{"id":27,"name":"後端開發","jobs_count":98,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 40,000 - 60,000 (月薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/Playalab","brand":"普拉亞科技 Playa Lab","banner":"https://s3cdn.yourator.co/banners/banners/000/002/044/medium/e8d642f7848ec063074ba4e36b5a4c317927c98f.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"目前公司無實體辦公室,皆為遠端辦公。","remote_interview":"remote_interview_partial","remote_interview_description":"","is_active":false},{"id":6233,"name":"Sr. Software Development Engineer in Test (Sr. SDET)","path":"/companies/jkopay/jobs/6233","category":{"id":27,"name":"測試工程","jobs_count":364,"job_type":"technical_job","isco_code":"15-1253.00","priority":5,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"12"},"tags":[{"id":46,"name":"Python","jobs_count":1236,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":67,"name":"SQL","jobs_count":954,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":317,"name":"Linux","jobs_count":819,"created_at":"2020-10-07T14:48:46.000+08:00","updated_at":"2020-10-07T14:48:46.000+08:00"},{"id":501,"name":"Selenium","jobs_count":12,"created_at":"2020-10-21T16:23:44.000+08:00","updated_at":"2020-10-21T16:23:44.000+08:00"},{"id":999,"name":"appium","jobs_count":4,"created_at":"2021-01-05T10:51:37.000+08:00","updated_at":"2021-01-05T10:51:37.000+08:00"},{"id":1066,"name":"pytest","jobs_count":1,"created_at":"2021-01-14T17:01:45.000+08:00","updated_at":"2021-01-14T17:01:45.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":false,"follow":false,"salary":"面議(經常性薪資達4萬元)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/jkopay","brand":"街口支付","banner":"https://s3cdn.yourator.co/banners/banners/000/000/949/medium/b49d0e2dd1cdcc1963e239c6e12f88bf5bb3671a.png","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":false},{"id":23006,"name":"APP QA engineer (Manual) ","path":"/companies/omlet/jobs/23006","category":{"id":27,"name":"測試工程","jobs_count":364,"job_type":"technical_job","isco_code":"15-1253.00","priority":5,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"12"},"tags":[{"id":615,"name":"QA Engineer","jobs_count":73,"created_at":"2020-11-04T12:46:05.000+08:00","updated_at":"2020-11-04T12:46:05.000+08:00"},{"id":959,"name":"QA testing","jobs_count":65,"created_at":"2020-12-28T11:03:44.000+08:00","updated_at":"2020-12-28T11:03:44.000+08:00"},{"id":1463,"name":"手動測試","jobs_count":8,"created_at":"2021-04-30T20:46:07.000+08:00","updated_at":"2021-04-30T20:46:07.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 800,000 - 1,200,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/omlet","brand":"Omlet Arcade","banner":"https://s3cdn.yourator.co/banners/banners/000/000/073/medium/9b0e3fa25b6ecf797558f4937e7930ec621f7702.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"","remote_interview":"remote_interview_partial","remote_interview_description":"","is_active":false},{"id":1124,"name":"[VR BU] Software Quality Assurance Engineer","path":"/companies/iStaging/jobs/1124","category":{"id":27,"name":"測試工程","jobs_count":364,"job_type":"technical_job","isco_code":"15-1253.00","priority":5,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"12"},"tags":[{"id":14,"name":"跨國團隊","jobs_count":1956,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":77,"name":"商業應用","jobs_count":473,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":117,"name":"VR/AR","jobs_count":413,"created_at":"2020-10-07T14:48:45.000+08:00","updated_at":"2020-10-07T14:48:45.000+08:00"},{"id":30,"name":"Git","jobs_count":310,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":342,"name":"QA","jobs_count":58,"created_at":"2020-10-07T19:14:56.000+08:00","updated_at":"2020-10-07T19:14:56.000+08:00"},{"id":829,"name":"RESTful API","jobs_count":39,"created_at":"2020-12-16T14:29:53.000+08:00","updated_at":"2020-12-16T14:29:53.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":false,"follow":false,"salary":"面議(經常性薪資達4萬元)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/iStaging","brand":"iStaging 愛實境","banner":"https://s3cdn.yourator.co/banners/banners/000/000/137/medium/929b22ce80eec9b06e18f648c9384098e05303d8.png","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":false},{"id":16705,"name":"Software Quality Assurance Engineer (App / Web)","path":"/companies/omlet/jobs/16705","category":{"id":27,"name":"測試工程","jobs_count":364,"job_type":"technical_job","isco_code":"15-1253.00","priority":5,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"12"},"tags":[{"id":14,"name":"跨國團隊","jobs_count":1956,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":59,"name":"APP","jobs_count":1443,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":959,"name":"QA testing","jobs_count":65,"created_at":"2020-12-28T11:03:44.000+08:00","updated_at":"2020-12-28T11:03:44.000+08:00"},{"id":1920,"name":"QA automation testing","jobs_count":28,"created_at":"2021-09-28T11:56:36.000+08:00","updated_at":"2021-09-28T11:56:36.000+08:00"},{"id":981,"name":"App測試","jobs_count":3,"created_at":"2020-12-30T10:28:29.000+08:00","updated_at":"2020-12-30T10:28:29.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 1,000,000 - 1,600,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/omlet","brand":"Omlet Arcade","banner":"https://s3cdn.yourator.co/banners/banners/000/000/073/medium/9b0e3fa25b6ecf797558f4937e7930ec621f7702.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"","remote_interview":"remote_interview_partial","remote_interview_description":"","is_active":false},{"id":25150,"name":"[3D BU] 資深前端工程師 Senior Frontend Engineer","path":"/companies/iStaging/jobs/25150","category":{"id":22,"name":"前端工程","jobs_count":1505,"job_type":"technical_job","isco_code":"15-1252.00","priority":0,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"22"},"tags":[],"intern":false,"job_type":"full_time","has_salary_info":false,"follow":false,"salary":"面議(經常性薪資達4萬元)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/iStaging","brand":"iStaging 愛實境","banner":"https://s3cdn.yourator.co/banners/banners/000/000/137/medium/929b22ce80eec9b06e18f648c9384098e05303d8.png","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_partial","remote_interview_description":"","is_active":true},{"id":24895,"name":"Senior QA Specialist - Manual","path":"/companies/Dcard/jobs/24895","category":{"id":27,"name":"測試工程","jobs_count":364,"job_type":"technical_job","isco_code":"15-1253.00","priority":5,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"12"},"tags":[{"id":959,"name":"QA testing","jobs_count":65,"created_at":"2020-12-28T11:03:44.000+08:00","updated_at":"2020-12-28T11:03:44.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":false,"follow":false,"salary":"面議(經常性薪資達4萬元)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/Dcard","brand":"Dcard","banner":"https://s3cdn.yourator.co/banners/banners/000/000/052/medium/07272d45c662097dc47bdc379414b715c4bbb304.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"疫情緩和後須進辦公室工作","remote_interview":"remote_interview_partial","remote_interview_description":"疫情緩和後須進辦公室面談","is_active":false},{"id":17560,"name":"Backend Developer","path":"/companies/Dcard/jobs/17560","category":{"id":23,"name":"後端工程","jobs_count":1145,"job_type":"technical_job","isco_code":"15-1252.00","priority":1,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"23"},"tags":[],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 800,000 - 1,150,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/Dcard","brand":"Dcard","banner":"https://s3cdn.yourator.co/banners/banners/000/000/052/medium/07272d45c662097dc47bdc379414b715c4bbb304.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"疫情緩和後須進辦公室工作","remote_interview":"remote_interview_partial","remote_interview_description":"疫情緩和後須進辦公室面談","is_active":false},{"id":519,"name":"Senior Frontend Engineer","path":"/companies/Dcard/jobs/519","category":{"id":22,"name":"前端工程","jobs_count":1505,"job_type":"technical_job","isco_code":"15-1252.00","priority":0,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"22"},"tags":[{"id":14,"name":"跨國團隊","jobs_count":1956,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":59,"name":"APP","jobs_count":1443,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":61,"name":"Node.js","jobs_count":753,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":293,"name":"ReactJS","jobs_count":650,"created_at":"2020-10-07T14:48:46.000+08:00","updated_at":"2020-10-07T14:48:46.000+08:00"},{"id":65,"name":"社群軟體","jobs_count":244,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":107,"name":"Redux","jobs_count":179,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 1,000,000 - 1,600,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/Dcard","brand":"Dcard","banner":"https://s3cdn.yourator.co/banners/banners/000/000/052/medium/07272d45c662097dc47bdc379414b715c4bbb304.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"疫情緩和後須進辦公室工作","remote_interview":"remote_interview_partial","remote_interview_description":"疫情緩和後須進辦公室面談","is_active":false},{"id":17015,"name":"前端工程師","path":"/companies/lawsnote/jobs/17015","category":{"id":22,"name":"前端工程","jobs_count":1505,"job_type":"technical_job","isco_code":"15-1252.00","priority":0,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"22"},"tags":[],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 630,000 - 910,000 (年薪)","country":"TW","country_name":"台灣","city":"新北市","company":{"path":"/companies/lawsnote","brand":"Lawsnote","banner":"https://s3cdn.yourator.co/banners/banners/000/001/141/medium/6507aa190e3748f12fecdcdeb6a7549ca1ae4af5.png","area":"新北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":true},{"id":17010,"name":"後端工程師","path":"/companies/lawsnote/jobs/17010","category":{"id":23,"name":"後端工程","jobs_count":1145,"job_type":"technical_job","isco_code":"15-1252.00","priority":1,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"23"},"tags":[{"id":12,"name":"新創","jobs_count":1301,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":124,"name":"資訊平台","jobs_count":970,"created_at":"2020-10-07T14:48:45.000+08:00","updated_at":"2020-10-07T14:48:45.000+08:00"},{"id":61,"name":"Node.js","jobs_count":753,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":30,"name":"Git","jobs_count":310,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 900,000 - 1,800,000 (年薪)","country":"TW","country_name":"台灣","city":"新北市","company":{"path":"/companies/lawsnote","brand":"Lawsnote","banner":"https://s3cdn.yourator.co/banners/banners/000/001/141/medium/6507aa190e3748f12fecdcdeb6a7549ca1ae4af5.png","area":"新北市"},"remote_work":"remote_work_none","remote_work_description":"","remote_interview":"remote_interview_none","remote_interview_description":"","is_active":true},{"id":26062,"name":"Frontend Developer 前端工程師","path":"/companies/CrescendoLab/jobs/26062","category":{"id":22,"name":"前端工程","jobs_count":1505,"job_type":"technical_job","isco_code":"15-1252.00","priority":0,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"22"},"tags":[],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 800,000 - 1,300,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/CrescendoLab","brand":"漸強實驗室 Crescendo Lab Ltd.","banner":"https://s3cdn.yourator.co/banners/banners/000/000/643/medium/ca65cc0368d3e47181450d65252a97d1fa309ab1.png","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":true},{"id":26063,"name":"Sr. Frontend Developer 資深前端工程師","path":"/companies/CrescendoLab/jobs/26063","category":{"id":22,"name":"前端工程","jobs_count":1505,"job_type":"technical_job","isco_code":"15-1252.00","priority":0,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"22"},"tags":[],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 1,300,000 - 2,000,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/CrescendoLab","brand":"漸強實驗室 Crescendo Lab Ltd.","banner":"https://s3cdn.yourator.co/banners/banners/000/000/643/medium/ca65cc0368d3e47181450d65252a97d1fa309ab1.png","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":true},{"id":2079,"name":"QA測試工程師 ","path":"/companies/BoniO/jobs/2079","category":{"id":27,"name":"測試工程","jobs_count":364,"job_type":"technical_job","isco_code":"15-1253.00","priority":5,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"12"},"tags":[{"id":17,"name":"教育","jobs_count":979,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":99,"name":"線上課程","jobs_count":430,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":84,"name":"遊戲","jobs_count":126,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 650,000 - 900,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/BoniO","brand":"PaGamO","banner":"https://s3cdn.yourator.co/banners/banners/000/000/478/medium/18fd0819c502b75eb5d100be0b8b61b5083d35b8.jpg","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_partial","remote_interview_description":"最後一關需要 Onsite","is_active":true},{"id":24198,"name":"全端工程師_FullStack Engineer_Yory","path":"/companies/BoniO/jobs/24198","category":{"id":24,"name":"全端工程","jobs_count":-1287,"job_type":"technical_job","isco_code":"15-1252.00","priority":2,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"24"},"tags":[{"id":89,"name":"Go","jobs_count":202,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":321,"name":"Django","jobs_count":76,"created_at":"2020-10-07T14:48:46.000+08:00","updated_at":"2020-10-07T14:48:46.000+08:00"},{"id":378,"name":"Ruby on rails","jobs_count":25,"created_at":"2020-10-10T14:53:04.000+08:00","updated_at":"2020-10-10T14:53:04.000+08:00"},{"id":172,"name":"NLP","jobs_count":17,"created_at":"2020-10-07T14:48:45.000+08:00","updated_at":"2020-10-07T14:48:45.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 1,200,000 - 2,000,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/BoniO","brand":"PaGamO","banner":"https://s3cdn.yourator.co/banners/banners/000/000/478/medium/18fd0819c502b75eb5d100be0b8b61b5083d35b8.jpg","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"彈性居家工作","remote_interview":"remote_interview_full","remote_interview_description":"","is_active":false},{"id":24199,"name":"前端工程師_FrontEnd Engineer_Yory","path":"/companies/BoniO/jobs/24199","category":{"id":22,"name":"前端工程","jobs_count":1505,"job_type":"technical_job","isco_code":"15-1252.00","priority":0,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"22"},"tags":[{"id":748,"name":"React","jobs_count":44,"created_at":"2020-12-01T18:02:55.000+08:00","updated_at":"2020-12-01T18:02:55.000+08:00"},{"id":869,"name":"Angular","jobs_count":28,"created_at":"2020-12-18T15:59:29.000+08:00","updated_at":"2020-12-18T15:59:29.000+08:00"},{"id":1760,"name":"Next.js","jobs_count":8,"created_at":"2021-08-13T16:53:11.000+08:00","updated_at":"2021-08-13T16:53:11.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 900,000 - 1,200,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/BoniO","brand":"PaGamO","banner":"https://s3cdn.yourator.co/banners/banners/000/000/478/medium/18fd0819c502b75eb5d100be0b8b61b5083d35b8.jpg","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"彈性居家辦公","remote_interview":"remote_interview_full","remote_interview_description":"","is_active":false},{"id":27935,"name":"System Analyst_Taipei","path":"/companies/Carrefour/jobs/27935","category":{"id":29,"name":"資料工程 / 機器學習","jobs_count":541,"job_type":"technical_job","isco_code":"15-2051.00","priority":0,"job_category_group_id":8,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"28"},"tags":[],"intern":false,"job_type":"full_time","has_salary_info":false,"follow":false,"salary":"面議(經常性薪資達4萬元)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/Carrefour","brand":"Carrefour Taiwan","banner":"https://s3cdn.yourator.co/banners/banners/000/002/139/medium/970cd4427c0f8c2d28c29d3c53afe7e119dd4e5f.png","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":true},{"id":24460,"name":"[AI] MIS 工程師","path":"/companies/dynasafe/jobs/24460","category":{"id":12,"name":"MIS / 網路管理","jobs_count":346,"job_type":"technical_job","isco_code":"15-1253.00","priority":0,"job_category_group_id":3,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"13"},"tags":[{"id":935,"name":"系統分析師","jobs_count":89,"created_at":"2020-12-23T14:58:59.000+08:00","updated_at":"2020-12-23T14:58:59.000+08:00"},{"id":778,"name":"系統維護/操作人員","jobs_count":58,"created_at":"2020-12-07T17:01:52.000+08:00","updated_at":"2020-12-07T17:01:52.000+08:00"},{"id":703,"name":"MIS程式設計師","jobs_count":29,"created_at":"2020-11-19T14:57:08.000+08:00","updated_at":"2020-11-19T14:57:08.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 30,000 - (月薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/dynasafe","brand":"動力安全資訊股份有限公司 Dynasafe","banner":"https://s3cdn.yourator.co/banners/banners/000/001/997/medium/af26187ec9ed272aa6dc86ae67464ab5b069f627.png","area":"臺北市"},"remote_work":"remote_work_none","remote_work_description":null,"remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":true},{"id":24413,"name":"[AST] 系統 助理工程師","path":"/companies/dynasafe/jobs/24413","category":{"id":12,"name":"MIS / 網路管理","jobs_count":346,"job_type":"technical_job","isco_code":"15-1253.00","priority":0,"job_category_group_id":3,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"13"},"tags":[{"id":935,"name":"系統分析師","jobs_count":89,"created_at":"2020-12-23T14:58:59.000+08:00","updated_at":"2020-12-23T14:58:59.000+08:00"},{"id":778,"name":"系統維護/操作人員","jobs_count":58,"created_at":"2020-12-07T17:01:52.000+08:00","updated_at":"2020-12-07T17:01:52.000+08:00"},{"id":779,"name":"網路管理工程師","jobs_count":58,"created_at":"2020-12-07T17:04:35.000+08:00","updated_at":"2020-12-07T17:04:35.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 30,000 - (月薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/dynasafe","brand":"動力安全資訊股份有限公司 Dynasafe","banner":"https://s3cdn.yourator.co/banners/banners/000/001/997/medium/af26187ec9ed272aa6dc86ae67464ab5b069f627.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"目前公司採防疫分組居家辦公,疫情緩和後仍須進辦公室工作","remote_interview":"remote_interview_none","remote_interview_description":null,"is_active":true},{"id":24286,"name":"前端工程師 Jr./Sr. Frontend Engineer (React)[E05]","path":"/companies/Partipost/jobs/24286","category":{"id":22,"name":"前端工程","jobs_count":1505,"job_type":"technical_job","isco_code":"15-1252.00","priority":0,"job_category_group_id":7,"created_at":"2020-06-09T14:52:17.000+08:00","updated_at":"2021-02-22T17:04:05.000+08:00","job_category_code":"22"},"tags":[{"id":38,"name":"JavaScript","jobs_count":1604,"created_at":"2020-10-07T14:48:44.000+08:00","updated_at":"2020-10-07T14:48:44.000+08:00"},{"id":293,"name":"ReactJS","jobs_count":650,"created_at":"2020-10-07T14:48:46.000+08:00","updated_at":"2020-10-07T14:48:46.000+08:00"},{"id":315,"name":"ReactNative","jobs_count":143,"created_at":"2020-10-07T14:48:46.000+08:00","updated_at":"2020-10-07T14:48:46.000+08:00"},{"id":748,"name":"React","jobs_count":44,"created_at":"2020-12-01T18:02:55.000+08:00","updated_at":"2020-12-01T18:02:55.000+08:00"},{"id":747,"name":"React.js","jobs_count":22,"created_at":"2020-12-01T17:55:52.000+08:00","updated_at":"2020-12-01T17:55:52.000+08:00"}],"intern":false,"job_type":"full_time","has_salary_info":true,"follow":false,"salary":"NT$ 900,000 - 1,400,000 (年薪)","country":"TW","country_name":"台灣","city":"臺北市","company":{"path":"/companies/Partipost","brand":"Partipost 台北派兒","banner":"https://s3cdn.yourator.co/banners/banners/000/000/465/medium/441e7f5119dfeb665169cc04698cb45588b9c282.png","area":"臺北市"},"remote_work":"remote_work_partial","remote_work_description":"","remote_interview":"remote_interview_full","remote_interview_description":"疫情期間全程 eMeet(4 rounds interview )","is_active":true}]} -------------------------------------------------------------------------------- /general/tests/test_index.py: -------------------------------------------------------------------------------- 1 | from django.test import Client, TestCase 2 | 3 | class IndexTestCase(TestCase): 4 | def test_index(self): 5 | c = Client() 6 | res = c.get('/') 7 | self.assertRedirects(res, 'https://github.com/hasname/feedgen', fetch_redirect_response=False) 8 | -------------------------------------------------------------------------------- /general/tests/test_robotstxt.py: -------------------------------------------------------------------------------- 1 | from django.test import Client, TestCase 2 | 3 | class RobotstxtTestCase(TestCase): 4 | def test_robotstxt(self): 5 | c = Client() 6 | res = c.get('/robots.txt') 7 | self.assertEqual(res.status_code, 200) 8 | -------------------------------------------------------------------------------- /general/tests/test_smoke.py: -------------------------------------------------------------------------------- 1 | from django.test import Client, TestCase 2 | import os 3 | import re 4 | import requests_mock 5 | 6 | class SmokeTestCase(TestCase): 7 | @requests_mock.mock() 8 | def test_bookwalker_lightnovel(self, m): 9 | text = open(os.path.dirname(__file__) + '/html_bookwalker_manga.txt').read() 10 | m.get('https://www.bookwalker.com.tw/block/3?order=sell_desc', text=text) 11 | 12 | c = Client() 13 | res = c.get('/bookwalker-manga') 14 | self.assertEqual(res.status_code, 200) 15 | 16 | @requests_mock.mock() 17 | def test_bookwalker_lightnovel(self, m): 18 | text = open(os.path.dirname(__file__) + '/html_bookwalker_lightnovel.txt').read() 19 | m.get('https://www.bookwalker.com.tw/block/5?order=sell_desc', text=text) 20 | 21 | c = Client() 22 | res = c.get('/bookwalker-lightnovel') 23 | self.assertEqual(res.status_code, 200) 24 | 25 | @requests_mock.mock() 26 | def test_cakeresume(self, m): 27 | text = open(os.path.dirname(__file__) + '/html_cakeresume.txt').read() 28 | m.get('https://www.cakeresume.com/jobs/test?location_list%5B0%5D=Taiwan&order=latest', text=text) 29 | 30 | c = Client() 31 | res = c.get('/cakeresume/test') 32 | self.assertEqual(res.status_code, 200) 33 | 34 | @requests_mock.mock() 35 | def test_dcard_board(self, m): 36 | text = open(os.path.dirname(__file__) + '/html_dcard_board.txt').read() 37 | m.get('https://www.dcard.tw/f/moon', text=text) 38 | 39 | c = Client() 40 | res = c.get('/dcard/board/moon') 41 | self.assertEqual(res.status_code, 200) 42 | 43 | @requests_mock.mock() 44 | def test_dcard_main(self, m): 45 | m.get('https://www.dcard.tw/service/api/v2/popularForums/GetHead?listKey=popularForums', text='{"listKey":"popularForums","head":"00000000-0000-0000-0000-000000000000"}') 46 | 47 | text = open(os.path.dirname(__file__) + '/json_dcard_popular.txt').read() 48 | m.get('https://www.dcard.tw/service/api/v2/popularForums/GetPage?pageKey=00000000-0000-0000-0000-000000000000', text=text) 49 | 50 | c = Client() 51 | res = c.get('/dcard/main') 52 | self.assertEqual(res.status_code, 200) 53 | 54 | @requests_mock.mock() 55 | def test_job104(self, m): 56 | text = open(os.path.dirname(__file__) + '/json_job104.txt').read() 57 | m.get(re.compile(r'^https://www\.104\.com\.tw/jobs/search/api/jobs'), text=text) 58 | 59 | c = Client() 60 | res = c.get('/104/test') 61 | self.assertEqual(res.status_code, 200) 62 | 63 | res = c.get('/104company/test') 64 | self.assertEqual(res.status_code, 200) 65 | 66 | @requests_mock.mock() 67 | def test_job1111(self, m): 68 | text = open(os.path.dirname(__file__) + '/html_job1111.txt').read() 69 | m.get('https://www.1111.com.tw/search/job?col=da&ks=test&page=1&sort=desc', text=text) 70 | 71 | c = Client() 72 | res = c.get('/1111/test') 73 | self.assertEqual(res.status_code, 200) 74 | 75 | @requests_mock.mock() 76 | def test_job518(self, m): 77 | text = open(os.path.dirname(__file__) + '/html_job518.txt').read() 78 | m.get('https://www.518.com.tw/job-index-P-1.html?i=1&am=1&ad=test&orderType=1&orderField=8', text=text) 79 | 80 | c = Client() 81 | res = c.get('/518/test') 82 | self.assertEqual(res.status_code, 200) 83 | 84 | @requests_mock.mock() 85 | def test_meetjobs(self, m): 86 | text = open(os.path.dirname(__file__) + '/json_meetjobs.txt').read() 87 | m.get('https://api.meet.jobs/api/v1/jobs?page=1&order=update&q=test&include=required_skills&external_job=true', text=text) 88 | 89 | c = Client() 90 | res = c.get('/meetjobs/test') 91 | self.assertEqual(res.status_code, 200) 92 | 93 | @requests_mock.mock() 94 | def test_momoshop(self, m): 95 | m.get('https://www.momoshop.com.tw/', text='') 96 | 97 | text = open(os.path.dirname(__file__) + '/json_momoshop.txt').read() 98 | m.post('https://www.momoshop.com.tw/ajax/ajaxTool.jsp?n=2018', text=text) 99 | 100 | c = Client() 101 | res = c.get('/momoshop/test') 102 | self.assertEqual(res.status_code, 200) 103 | 104 | @requests_mock.mock() 105 | def test_pchome(self, m): 106 | text = open(os.path.dirname(__file__) + '/json_pchome.txt').read() 107 | m.get('https://ecshweb.pchome.com.tw/search/v3.3/all/results?q=test&page=1&sort=new/dc', text=text) 108 | 109 | c = Client() 110 | res = c.get('/pchome/test') 111 | self.assertEqual(res.status_code, 200) 112 | 113 | @requests_mock.mock() 114 | def test_pchome_lightnovel(self, m): 115 | text = open(os.path.dirname(__file__) + '/json_pchome_lightnovel.txt').read() 116 | m.get('https://ecapi.pchome.com.tw/cdn/ecshop/prodapi/v2/newarrival/DJAZ/prod&offset=1&limit=20&fields=Id,Nick,Pic,Price,Discount,isSpec,Name,isCarrier,isSnapUp,isBigCart&_callback=jsonp_prodlist?_callback=jsonp_prodlist', text=text) 117 | 118 | c = Client() 119 | res = c.get('/pchome-lightnovel') 120 | self.assertEqual(res.status_code, 200) 121 | 122 | @requests_mock.mock() 123 | def test_plurk_search(self, m): 124 | text = open(os.path.dirname(__file__) + '/json_plurk_search.txt').read() 125 | m.post('https://www.plurk.com/Search/search2', text=text) 126 | 127 | c = Client() 128 | res = c.get('/plurk/search/test') 129 | self.assertEqual(res.status_code, 200) 130 | 131 | @requests_mock.mock() 132 | def test_plurk_top(self, m): 133 | text = open(os.path.dirname(__file__) + '/json_plurk_top_zh.txt').read() 134 | m.get('https://www.plurk.com/Stats/topReplurks?period=day&lang=zh&limit=10', text=text) 135 | 136 | c = Client() 137 | res = c.get('/plurk/top/zh') 138 | self.assertEqual(res.status_code, 200) 139 | 140 | @requests_mock.mock() 141 | def test_rent591(self, m): 142 | text = open(os.path.dirname(__file__) + '/html_rent591.txt').read() 143 | m.get('https://rent.591.com.tw/?kind=0&order=posttime&orderType=desc®ion=1&keywords=abc', text=text) 144 | 145 | c = Client() 146 | res = c.get('/rent591/1/abc') 147 | self.assertEqual(res.status_code, 200) 148 | 149 | @requests_mock.mock() 150 | def test_shopee(self, m): 151 | text = open(os.path.dirname(__file__) + '/json_shopee.txt').read() 152 | m.get('https://shopee.tw/api/v4/search/search_items/?by=ctime&keyword=test&limit=60&newest=0&order=desc&page_type=search&scenario=PAGE_GLOBAL_SEARCH&version=2', text=text) 153 | 154 | c = Client() 155 | res = c.get('/shopee/test') 156 | self.assertEqual(res.status_code, 200) 157 | 158 | @requests_mock.mock() 159 | def test_taipeimetrotimetable(self, m): 160 | text = open(os.path.dirname(__file__) + '/html_taipeimetrotimetable.txt').read() 161 | m.get('https://web.metro.taipei/img/ALL/timetables/079a.PDF', headers={'last-modified': 'Fri, 11 Nov 2022 16:20:50 GMT'}, text=text) 162 | 163 | c = Client() 164 | res = c.get('/taipeimetrotimetable/079a') 165 | self.assertEqual(res.status_code, 200) 166 | 167 | @requests_mock.mock() 168 | def test_yourator(self, m): 169 | text = open(os.path.dirname(__file__) + '/json_yourator.txt').read() 170 | m.get('https://www.yourator.co/api/v2/jobs?term[]=test', text=text) 171 | 172 | c = Client() 173 | res = c.get('/yourator/test') 174 | self.assertEqual(res.status_code, 200) 175 | 176 | @requests_mock.mock() 177 | def test_youtube(self, m): 178 | text = open(os.path.dirname(__file__) + '/html_youtube.txt').read() 179 | m.get('https://www.youtube.com/results?search_query=test&sp=CAI%253D', text=text) 180 | 181 | c = Client() 182 | res = c.get('/youtube/test') 183 | self.assertEqual(res.status_code, 200) 184 | -------------------------------------------------------------------------------- /general/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from .views import bookwalker, cakeresume, dcard, index, job104, job1111, job518, meetjobs, momoshop, pchome, plurk, rent591, robotstxt, shopee, taipeimetrotimetable, yourator, youtube 4 | 5 | urlpatterns = [ 6 | path('', index.IndexView.as_view(), name='index'), 7 | path('robots.txt', robotstxt.RobotsTxtView.as_view(), name='robotstxt'), 8 | 9 | path('104/', job104.Job104View.as_view(), name='job104'), 10 | path('104company/', job104.Job104CompanyView.as_view(), name='job104company'), 11 | path('1111/', job1111.Job1111View.as_view(), name='job1111'), 12 | path('518/', job518.Job518View.as_view(), name='job518'), 13 | path('bookwalker-lightnovel', bookwalker.BookwalkerLightNovelView.as_view(), name='bookwalker_lightnovel'), 14 | path('bookwalker-manga', bookwalker.BookwalkerMangaView.as_view(), name='bookwalker_manga'), 15 | path('cakeresume/', cakeresume.CakeResumeView.as_view(), name='cakeresume'), 16 | path('dcard/board/', dcard.DcardBoardView.as_view(), name='dcard_board'), 17 | path('dcard/main', dcard.DcardMainView.as_view(), name='dcard_main'), 18 | path('meetjobs/', meetjobs.MeetJobsView.as_view(), name='meetjobs'), 19 | path('momoshop/', momoshop.MomoshopView.as_view(), name='momoshop'), 20 | path('pchome/', pchome.PChomeView.as_view(), name='pchome'), 21 | path('pchome-lightnovel', pchome.PChomeLightNovelView.as_view(), name='pchome_lightnovel'), 22 | path('plurk/search/', plurk.PlurkSearchView.as_view(), name='plurk_search'), 23 | path('plurk/top/', plurk.PlurkTopView.as_view(), name='plurk_top'), 24 | path('rent591//', rent591.Rent591View.as_view(), name='rent591'), 25 | path('shopee/', shopee.ShopeeView.as_view(), name='shopee'), 26 | path('taipeimetrotimetable/', taipeimetrotimetable.TaipeiMetroTimetableView.as_view(), name='taipeimetrotimetable'), 27 | path('yourator/', yourator.YouratorView.as_view(), name='yourator'), 28 | path('youtube/', youtube.YouTubeView.as_view(), name='youtube'), 29 | ] 30 | -------------------------------------------------------------------------------- /general/views/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasname/feedgen/6365ea93df41dbd20188fa2b6831ec71a99ff1b5/general/views/__init__.py -------------------------------------------------------------------------------- /general/views/bookwalker.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import lxml.html 5 | import re 6 | 7 | from .. import services 8 | 9 | class BookwalkerMangaView(View): 10 | def get(self, *args, **kwargs): 11 | url = 'https://www.bookwalker.com.tw/block/3?order=sell_desc' 12 | 13 | title = 'BOOKWALKER 漫畫' 14 | 15 | feed = feedgen.feed.FeedGenerator() 16 | feed.author({'name': 'Feed Generator'}) 17 | feed.id(url) 18 | feed.link(href=url, rel='alternate') 19 | feed.title(title) 20 | 21 | s = services.RequestsService().process() 22 | 23 | r = s.get(url) 24 | body = lxml.html.fromstring(r.text) 25 | 26 | for item in body.cssselect('.bookitem a'): 27 | img = item.cssselect('img')[0] 28 | img_src = img.get('data-src') 29 | img_src = re.sub(r'_4(_mask)?\.jpg$', '.jpg', img_src) 30 | img.set('src', img_src) 31 | del img.attrib['data-src'] 32 | 33 | content = lxml.etree.tostring(item, encoding='unicode') 34 | book_title = item.get('title') 35 | book_url = item.get('href') 36 | 37 | entry = feed.add_entry() 38 | entry.content(content, type='xhtml') 39 | entry.id(book_url) 40 | entry.title(book_title) 41 | entry.link(href=book_url) 42 | 43 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 44 | res['Cache-Control'] = 'max-age=300,public' 45 | 46 | return res 47 | 48 | class BookwalkerLightNovelView(View): 49 | def get(self, *args, **kwargs): 50 | url = 'https://www.bookwalker.com.tw/block/5?order=sell_desc' 51 | 52 | title = 'BOOKWALKER 輕小說' 53 | 54 | feed = feedgen.feed.FeedGenerator() 55 | feed.author({'name': 'Feed Generator'}) 56 | feed.id(url) 57 | feed.link(href=url, rel='alternate') 58 | feed.title(title) 59 | 60 | s = services.RequestsService().process() 61 | 62 | r = s.get(url) 63 | body = lxml.html.fromstring(r.text) 64 | 65 | for item in body.cssselect('.bookitem a'): 66 | img = item.cssselect('img')[0] 67 | img_src = img.get('data-src') 68 | img_src = re.sub(r'_4(_mask)?\.jpg$', '.jpg', img_src) 69 | img.set('src', img_src) 70 | del img.attrib['data-src'] 71 | 72 | content = lxml.etree.tostring(item, encoding='unicode') 73 | book_title = item.get('title') 74 | book_url = item.get('href') 75 | 76 | entry = feed.add_entry() 77 | entry.content(content, type='xhtml') 78 | entry.id(book_url) 79 | entry.title(book_title) 80 | entry.link(href=book_url) 81 | 82 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 83 | res['Cache-Control'] = 'max-age=300,public' 84 | 85 | return res 86 | -------------------------------------------------------------------------------- /general/views/cakeresume.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import lxml 6 | import re 7 | import urllib 8 | 9 | from .. import services 10 | 11 | class CakeResumeView(View): 12 | def get(self, *args, **kwargs): 13 | keyword = kwargs['keyword'] 14 | 15 | url = 'https://www.cakeresume.com/jobs/{}?location_list%5B0%5D=Taiwan&order=latest'.format(urllib.parse.quote_plus(keyword)) 16 | 17 | title = 'CakeResume 搜尋 - {}'.format(keyword) 18 | 19 | feed = feedgen.feed.FeedGenerator() 20 | feed.author({'name': 'Feed Generator'}) 21 | feed.id(url) 22 | feed.link(href=url, rel='alternate') 23 | feed.title(title) 24 | 25 | try: 26 | s = services.RequestsService().process() 27 | 28 | r = s.get(url) 29 | body = lxml.html.fromstring(r.text) 30 | items = body.cssselect('div[class^="JobSearchItem_wrapper__"]') 31 | except: 32 | items = [] 33 | 34 | for item in items: 35 | job_company = item.cssselect('a[class^="JobSearchItem_companyName__"]')[0].text_content() 36 | job_desc = item.cssselect('div[class^="JobSearchItem_description__"]')[0].text_content() 37 | job_features = item.cssselect('div[class^="JobSearchItem_features__"]')[0].text_content() 38 | job_link = item.cssselect('a[class^="JobSearchItem_jobTitle__"]')[0].get('href') 39 | job_title = item.cssselect('a[class^="JobSearchItem_jobTitle__"]')[0].text_content() 40 | 41 | # "/"-prefix but not "//"-prefix: 42 | if re.match(r'^/($|[^/])', job_link): 43 | job_link = 'https://www.cakeresume.com' + job_link 44 | 45 | item_author = job_company 46 | item_content = '

{}

{}

'.format(html.escape(job_features), html.escape(job_desc)) 47 | item_title = job_title 48 | item_url = job_link 49 | 50 | entry = feed.add_entry() 51 | entry.author({'name': item_author}) 52 | entry.content(item_content, type='xhtml') 53 | entry.id(item_url) 54 | entry.link(href=item_url) 55 | entry.title(item_title) 56 | 57 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 58 | res['Cache-Control'] = 'max-age=300,public' 59 | 60 | return res 61 | -------------------------------------------------------------------------------- /general/views/dcard.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import lxml.html 6 | import re 7 | import urllib 8 | 9 | from .. import services 10 | 11 | class DcardBoardView(View): 12 | def get(self, *args, **kwargs): 13 | board = kwargs['board'] 14 | url = 'https://www.dcard.tw/f/{}'.format(urllib.parse.quote_plus(board)) 15 | 16 | title = 'Dcard 看板 - {}'.format(board) 17 | 18 | feed = feedgen.feed.FeedGenerator() 19 | feed.author({'name': 'Feed Generator'}) 20 | feed.id(url) 21 | feed.link(href=url, rel='alternate') 22 | feed.title(title) 23 | 24 | try: 25 | proxy = services.ProxySocks5Service().process() 26 | s = services.RequestsService().process() 27 | 28 | if proxy is not None: 29 | s.proxies = {'http': proxy, 'https': proxy} 30 | 31 | r = s.get(url) 32 | body = lxml.html.fromstring(r.text) 33 | except: 34 | return HttpResponse('Service Unavailable', status=503) 35 | 36 | items = body.cssselect('div[role="main"] article') 37 | for item in items: 38 | item_title = item.cssselect('h2')[0].text_content() 39 | item_url = item.cssselect('h2 > a')[0].get('href') 40 | item_desc = item.cssselect('h2 + div')[0].text_content() 41 | try: 42 | item_img = item.cssselect('img')[0] 43 | except IndexError: 44 | item_img_src = None 45 | else: 46 | item_img_src = item_img.get('src') 47 | g = re.match(r'^(https://imgur\.dcard\.tw/\w+)b(\.jpg)$', item_img_src) 48 | if g: 49 | item_img_src = g.group(1) + g.group(2) 50 | 51 | if item_url.startswith('/f/'): 52 | item_url = 'https://www.dcard.tw' + item_url 53 | 54 | if item_img_src is None: 55 | item_content = '{}'.format( 56 | html.escape(item_desc) 57 | ) 58 | else: 59 | item_content = '{}
{}'.format( 60 | html.escape(item_title), 61 | html.escape(item_img_src), 62 | html.escape(item_desc) 63 | ) 64 | 65 | entry = feed.add_entry() 66 | entry.content(item_content, type='xhtml') 67 | entry.id(item_url) 68 | entry.title(item_title) 69 | entry.link(href=item_url) 70 | 71 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 72 | res['Cache-Control'] = 'max-age=300,public' 73 | 74 | return res 75 | 76 | class DcardMainView(View): 77 | def get(self, *args, **kwargs): 78 | url = 'https://www.dcard.tw/f' 79 | 80 | title = 'Dcard 首頁' 81 | 82 | feed = feedgen.feed.FeedGenerator() 83 | feed.author({'name': 'Feed Generator'}) 84 | feed.id(url) 85 | feed.link(href=url, rel='alternate') 86 | feed.title(title) 87 | 88 | proxy = services.ProxySocks5Service().process() 89 | s = services.RequestsService().process() 90 | 91 | if proxy is not None: 92 | s.proxies = {'http': proxy, 'https': proxy} 93 | 94 | r = s.get('https://www.dcard.tw/service/api/v2/popularForums/GetHead?listKey=popularForums') 95 | if r.status_code == 200: 96 | head = r.json()['head'] 97 | r = s.get('https://www.dcard.tw/service/api/v2/popularForums/GetPage?pageKey={}'.format(head)) 98 | items = r.json()['items'] 99 | else: 100 | items = [] 101 | 102 | for item in items: 103 | item_title = '[{}] {}'.format(item['name'], item['posts'][0]['title']) 104 | item_url = 'https://www.dcard.tw/f/{}/p/{}'.format(item['alias'], item['posts'][0]['id']) 105 | item_desc = item['posts'][0]['excerpt'] 106 | 107 | item_content = '

{}

'.format( 108 | html.escape(item_desc) 109 | ) 110 | 111 | entry = feed.add_entry() 112 | entry.content(item_content, type='xhtml') 113 | entry.id(item_url) 114 | entry.title(item_title) 115 | entry.link(href=item_url) 116 | 117 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 118 | res['Cache-Control'] = 'max-age=300,public' 119 | 120 | return res 121 | -------------------------------------------------------------------------------- /general/views/index.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import redirect 2 | from django.views.generic import View 3 | 4 | class IndexView(View): 5 | def get(self, *args, **kwargs): 6 | return redirect('https://github.com/hasname/feedgen') 7 | -------------------------------------------------------------------------------- /general/views/job104.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import json 6 | import time 7 | 8 | from .. import services 9 | 10 | class Job104CompanyView(View): 11 | def get(self, *args, **kwargs): 12 | keyword = kwargs['keyword'] 13 | 14 | url = 'https://www.104.com.tw/jobs/search/api/jobs?jobsource=index_s&keyword={}&mode=s&order=16&page=1&pagesize=20&searchJobs=1'.format(keyword) 15 | 16 | title = '104 公司搜尋 - {}'.format(keyword) 17 | 18 | feed = feedgen.feed.FeedGenerator() 19 | feed.author({'name': 'Feed Generator'}) 20 | feed.id(url) 21 | feed.link(href=url, rel='alternate') 22 | feed.title(title) 23 | 24 | try: 25 | s = services.RequestsService().process() 26 | 27 | r = s.get(url, headers={'Referer': 'https://www.104.com.tw/'}) 28 | items = json.loads(r.text)['data'] 29 | except: 30 | items = [] 31 | 32 | for item in items: 33 | try: 34 | job_desc = item['description'] 35 | job_title = item['jobName'] 36 | 37 | if keyword.lower() not in job_title.lower() and keyword.lower() not in job_desc.lower(): 38 | continue 39 | 40 | job_company = item['custName'] 41 | job_company_url = item['link']['cust'] 42 | 43 | content = '

{}

'.format( 44 | html.escape(job_company), 45 | ) 46 | 47 | entry = feed.add_entry() 48 | entry.author({'name': job_company}) 49 | entry.content(content, type='xhtml') 50 | entry.id(job_company_url) 51 | entry.link(href=job_company_url) 52 | entry.title(job_company) 53 | except: 54 | pass 55 | 56 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 57 | res['Cache-Control'] = 'max-age=300,public' 58 | 59 | return res 60 | 61 | class Job104View(View): 62 | def get(self, *args, **kwargs): 63 | keyword = kwargs['keyword'] 64 | 65 | url = 'https://www.104.com.tw/jobs/search/api/jobs?jobsource=index_s&keyword={}&mode=s&order=16&page=1&pagesize=20&searchJobs=1'.format(keyword) 66 | 67 | title = '104 搜尋 - {}'.format(keyword) 68 | 69 | feed = feedgen.feed.FeedGenerator() 70 | feed.author({'name': 'Feed Generator'}) 71 | feed.id(url) 72 | feed.link(href=url, rel='alternate') 73 | feed.title(title) 74 | 75 | try: 76 | s = services.RequestsService().process() 77 | 78 | r = s.get(url, headers={'Referer': 'https://www.104.com.tw/'}) 79 | items = json.loads(r.text)['data'] 80 | except: 81 | items = [] 82 | 83 | for item in items: 84 | try: 85 | job_desc = item['description'] 86 | job_title = item['jobName'] 87 | 88 | if keyword.lower() not in job_title.lower() and keyword.lower() not in job_desc.lower(): 89 | continue 90 | 91 | job_company = item['custName'] 92 | job_url = item['link']['job'] 93 | 94 | content = '

{}

{}
'.format( 95 | html.escape(job_company), 96 | html.escape(job_desc) 97 | ) 98 | 99 | entry = feed.add_entry() 100 | entry.author({'name': job_company}) 101 | entry.content(content, type='xhtml') 102 | entry.id(job_url) 103 | entry.link(href=job_url) 104 | entry.title(job_title) 105 | except: 106 | pass 107 | 108 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 109 | res['Cache-Control'] = 'max-age=300,public' 110 | 111 | return res 112 | -------------------------------------------------------------------------------- /general/views/job1111.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import lxml.html 6 | import urllib 7 | 8 | from .. import services 9 | 10 | class Job1111View(View): 11 | def get(self, *args, **kwargs): 12 | keyword = kwargs['keyword'] 13 | 14 | url = 'https://www.1111.com.tw/search/job?col=da&ks={}&page=1&sort=desc'.format(urllib.parse.quote_plus(keyword)) 15 | 16 | title = '1111 搜尋 - {}'.format(keyword) 17 | 18 | feed = feedgen.feed.FeedGenerator() 19 | feed.author({'name': 'Feed Generator'}) 20 | feed.id(url) 21 | feed.link(href=url, rel='alternate') 22 | feed.title(title) 23 | 24 | s = services.RequestsService().process() 25 | 26 | r = s.get(url) 27 | r.encoding = 'utf-8' 28 | body = lxml.html.fromstring(r.text) 29 | 30 | for item in body.cssselect('div.job_item'): 31 | a = item.cssselect('.job_item_info a')[0] 32 | job_title = a.text_content() 33 | job_url = a.get('href') 34 | if job_url.startswith('/job/'): 35 | job_url = 'https://www.1111.com.tw' + job_url 36 | 37 | job_company = item.cssselect('div.card-subtitle a')[0].get('title') 38 | 39 | job_desc = item.cssselect('p.job_item_description')[0].text_content() 40 | content = '

{}

{}

'.format( 41 | html.escape(job_company), html.escape(job_desc) 42 | ) 43 | 44 | entry = feed.add_entry() 45 | entry.content(content, type='xhtml') 46 | entry.id(job_url) 47 | entry.link(href=job_url) 48 | entry.title(job_title) 49 | 50 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 51 | res['Cache-Control'] = 'max-age=300,public' 52 | 53 | return res 54 | -------------------------------------------------------------------------------- /general/views/job518.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import lxml.html 6 | import re 7 | import urllib 8 | 9 | from .. import services 10 | 11 | class Job518View(View): 12 | def get(self, *args, **kwargs): 13 | keyword = kwargs['keyword'] 14 | 15 | url = 'https://www.518.com.tw/job-index-P-1.html?i=1&am=1&ad={}&orderType=1&orderField=8'.format(urllib.parse.quote_plus(keyword)) 16 | 17 | title = '518 搜尋 - {}'.format(keyword) 18 | 19 | feed = feedgen.feed.FeedGenerator() 20 | feed.author({'name': 'Feed Generator'}) 21 | feed.id(url) 22 | feed.link(href=url, rel='alternate') 23 | feed.title(title) 24 | 25 | try: 26 | s = services.RequestsService().process() 27 | 28 | r = s.get(url) 29 | body = lxml.html.fromstring(r.text) 30 | except: 31 | body = lxml.html.fromstring('') 32 | 33 | for item in body.cssselect('#listContent > ul'): 34 | try: 35 | a = item.cssselect('li.title a')[0] 36 | job_title = a.getchildren()[0].text_content() 37 | 38 | job_url = a.get('href') 39 | job_url = re.sub('\\?.*', '', job_url) 40 | 41 | job_company = item.cssselect('li.company')[0].text_content() 42 | 43 | job_desc = item.cssselect('li.sumbox')[0].text_content() 44 | content = '

{}

{}

'.format( 45 | html.escape(job_company), html.escape(job_desc) 46 | ) 47 | 48 | entry = feed.add_entry() 49 | entry.content(content, type='xhtml') 50 | entry.id(job_url) 51 | entry.link(href=job_url) 52 | entry.title(job_title) 53 | 54 | except IndexError: 55 | pass 56 | 57 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 58 | res['Cache-Control'] = 'max-age=300,public' 59 | 60 | return res 61 | -------------------------------------------------------------------------------- /general/views/meetjobs.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import datetime 5 | import html 6 | import lxml.html 7 | import lxml.html.clean 8 | import urllib 9 | 10 | from .. import services 11 | 12 | class MeetJobsView(View): 13 | def get(self, *args, **kwargs): 14 | keyword = kwargs['keyword'] 15 | 16 | url = 'https://meet.jobs/zh-TW/jobs?page=1&order=update&q={}'.format(urllib.parse.quote_plus(keyword)) 17 | api_url = 'https://api.meet.jobs/api/v1/jobs?page=1&order=update&q={}&include=required_skills&external_job=true'.format(urllib.parse.quote_plus(keyword)) 18 | 19 | title = 'meet.jobs 搜尋 - {}'.format(keyword) 20 | 21 | feed = feedgen.feed.FeedGenerator() 22 | feed.author({'name': 'Feed Generator'}) 23 | feed.id(url) 24 | feed.link(href=url, rel='alternate') 25 | feed.title(title) 26 | 27 | try: 28 | s = services.RequestsService().process() 29 | 30 | r = s.get(api_url) 31 | items = r.json()['collection'] 32 | except: 33 | items = [] 34 | 35 | for item in items: 36 | try: 37 | job_company = item['employer']['name'] 38 | job_desc = lxml.etree.tostring(lxml.html.fromstring(lxml.html.clean.clean_html(item['description']))).decode('utf8') 39 | job_features = item['work_type'] 40 | job_link = 'https://meet.jobs/zh-TW/jobs/{}-{}'.format(item['id'], item['slug']) 41 | job_published_at = item['published_at'] 42 | job_title = item['title'] 43 | job_updated_at = item['updated_at'] 44 | 45 | item_author = job_company 46 | item_content = '

{}

{}

'.format(html.escape(job_features), job_desc) 47 | item_title = job_title 48 | item_url = job_link 49 | 50 | entry = feed.add_entry() 51 | entry.author({'name': item_author}) 52 | entry.content(item_content, type='xhtml') 53 | entry.id(item_url) 54 | entry.link(href=item_url) 55 | entry.published(datetime.datetime.strptime(item['published_at'], '%Y-%m-%dT%H:%M:%S.%f%z')) 56 | entry.title(item_title) 57 | entry.updated(datetime.datetime.strptime(item['updated_at'], '%Y-%m-%dT%H:%M:%S.%f%z')) 58 | 59 | except TypeError: 60 | pass 61 | 62 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 63 | res['Cache-Control'] = 'max-age=300,public' 64 | 65 | return res 66 | -------------------------------------------------------------------------------- /general/views/momoshop.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import json 6 | import time 7 | import urllib 8 | 9 | from .. import services 10 | 11 | class MomoshopView(View): 12 | def get(self, *args, **kwargs): 13 | keyword = kwargs['keyword'] 14 | 15 | url = 'https://www.momoshop.com.tw/search/searchShop.jsp?keyword={}&searchType=4&cateLevel=0&cateCode=&curPage=1&_isFuzzy=0&showType=chessboardType'.format(urllib.parse.quote_plus(keyword)) 16 | 17 | title = 'Momoshop 搜尋 - {}'.format(keyword) 18 | 19 | feed = feedgen.feed.FeedGenerator() 20 | feed.author({'name': 'Feed Generator'}) 21 | feed.id(url) 22 | feed.link(href=url, rel='alternate') 23 | feed.title(title) 24 | 25 | try: 26 | s = services.RequestsService().process() 27 | 28 | # Environment cookie. 29 | r = s.get('https://www.momoshop.com.tw/') 30 | 31 | # Get the actual content. 32 | now = int(time.time()) 33 | data = { 34 | 'flag': 2018, 35 | 'data': { 36 | 'specialGoodsType': '', 37 | 'searchValue': keyword, 38 | 'cateCode': '', 39 | 'cateLevel': '-1', 40 | 'cp': 'N', 41 | 'NAM': 'N', 42 | 'first': 'N', 43 | 'freeze': 'N', 44 | 'superstore': 'N', 45 | 'tvshop': 'N', 46 | 'china': 'N', 47 | 'tomorrow': 'N', 48 | 'stockYN': 'N', 49 | 'prefere': 'N', 50 | 'threeHours': 'N', 51 | 'showType': 'chessboardType', 52 | 'curPage': '1', 53 | 'priceS': '0', 54 | 'priceE': '9999999', 55 | 'searchType': '4', 56 | 'reduceKeyword': '', 57 | 'isFuzzy': '0', 58 | 'rtnCateDatainfo': { 59 | 'cateCode': '', 60 | 'cateLv': '-1', 61 | 'keyword': keyword, 62 | 'curPage': '1', 63 | 'historyDoPush': False, 64 | 'timestamp': now, 65 | }, 66 | } 67 | } 68 | 69 | url = 'https://www.momoshop.com.tw/ajax/ajaxTool.jsp?n=2018' 70 | r = s.post(url, data={'data': json.dumps(data)}, headers={'Referer': 'https://www.momoshop.com.tw/'}) 71 | body = json.loads(r.text) 72 | except: 73 | return HttpResponse('Service Unavailable', status=503) 74 | 75 | # If it's not 200 then return an empty feed. 76 | if body['rtnData']['searchResult']['resultCode'] != '200': 77 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 78 | res['Cache-Control'] = 'max-age=300,public' 79 | return res 80 | 81 | for item in body['rtnData']['searchResult']['rtnSearchData']['goodsInfoList']: 82 | # Product name & description 83 | item_img = item['imgUrl'] 84 | item_name = item['goodsName'] 85 | item_title = '({}) {}'.format(item['goodsPrice'], item_name) 86 | item_url = 'https://www.momoshop.com.tw/goods/GoodsDetail.jsp?i_code={}'.format(item['goodsCode']) 87 | 88 | # Use larger size. 89 | item_img = item_img.replace('_L.', '_B.') 90 | 91 | content = '{}'.format(html.escape(item_name), html.escape(item_img)) 92 | 93 | entry = feed.add_entry() 94 | entry.content(content, type='xhtml') 95 | entry.id(item_url) 96 | entry.link(href=item_url) 97 | entry.title(item_title) 98 | 99 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 100 | res['Cache-Control'] = 'max-age=300,public' 101 | 102 | return res 103 | -------------------------------------------------------------------------------- /general/views/pchome.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import json 6 | import re 7 | import urllib 8 | 9 | from .. import services 10 | 11 | class PChomeLightNovelView(View): 12 | def get(self, *args, **kwargs): 13 | url = 'https://ecapi.pchome.com.tw/cdn/ecshop/prodapi/v2/newarrival/DJAZ/prod&offset=1&limit=20&fields=Id,Nick,Pic,Price,Discount,isSpec,Name,isCarrier,isSnapUp,isBigCart&_callback=jsonp_prodlist?_callback=jsonp_prodlist' 14 | 15 | title = 'PChome 輕小說' 16 | 17 | feed = feedgen.feed.FeedGenerator() 18 | feed.author({'name': 'Feed Generator'}) 19 | feed.id(url) 20 | feed.link(href=url, rel='alternate') 21 | feed.title(title) 22 | 23 | try: 24 | s = services.RequestsService().process() 25 | 26 | r = s.get(url) 27 | body = re.match(r'^[^\[]*(\[.*\])[^\[]*$', r.text).group(1) 28 | items = json.loads(body) 29 | except: 30 | items = [] 31 | 32 | for item in items: 33 | content = '{}
{}'.format( 34 | html.escape(item['Nick']), 35 | html.escape(item['Nick']), 36 | html.escape(item['Pic']['B']), 37 | ) 38 | book_title = item['Nick'] 39 | book_url = 'https://24h.pchome.com.tw/books/prod/{}'.format( 40 | urllib.parse.quote_plus(item['Id']) 41 | ) 42 | 43 | entry = feed.add_entry() 44 | entry.content(content, type='xhtml') 45 | entry.id(book_url) 46 | entry.title(book_title) 47 | entry.link(href=book_url) 48 | 49 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 50 | res['Cache-Control'] = 'max-age=300,public' 51 | 52 | return res 53 | 54 | class PChomeView(View): 55 | def get(self, *args, **kwargs): 56 | keyword = kwargs['keyword'] 57 | 58 | url = 'https://ecshweb.pchome.com.tw/search/v3.3/all/results?q={}&page=1&sort=new/dc'.format(urllib.parse.quote_plus(keyword)) 59 | 60 | title = 'PChome 搜尋 - {}'.format(keyword) 61 | 62 | feed = feedgen.feed.FeedGenerator() 63 | feed.author({'name': 'Feed Generator'}) 64 | feed.id(url) 65 | feed.link(href=url, rel='alternate') 66 | feed.title(title) 67 | 68 | try: 69 | s = services.RequestsService().process() 70 | 71 | r = s.get(url) 72 | body = json.loads(r.text) 73 | except: 74 | body = {'prods': []} 75 | 76 | for item in body['prods']: 77 | # Product name & description 78 | item_author = self.str_clean(item['author']) 79 | item_desc = self.str_clean(item['describe']) 80 | item_name = self.str_clean(item['name']) 81 | item_origin_price = item['originPrice'] 82 | item_price = item['price'] 83 | item_title = '(${}/${}) {}'.format(item_origin_price, item_price, item_name) 84 | 85 | # URL 86 | if item['cateId'][0] == 'D': 87 | item_url = 'https://24h.pchome.com.tw/prod/' + item['Id'] 88 | else: 89 | item_url = 'https://mall.pchome.com.tw/prod/' + item['Id'] 90 | img_url = 'https://cs-a.ecimg.tw%s' % (item['picB']) 91 | 92 | content = '{}
{}'.format( 93 | html.escape(item_desc), html.escape(item_name), html.escape(img_url) 94 | ) 95 | 96 | entry = feed.add_entry() 97 | entry.author({'name': item_author}) 98 | entry.content(content, type='xhtml') 99 | entry.id(item_url) 100 | entry.link(href=item_url) 101 | entry.title(item_title) 102 | 103 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 104 | res['Cache-Control'] = 'max-age=300,public' 105 | 106 | return res 107 | 108 | def str_clean(self, s): 109 | return re.sub(r'[\x00-\x09]', ' ', s) 110 | -------------------------------------------------------------------------------- /general/views/plurk.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import base36 4 | import dateutil.parser 5 | import feedgen.feed 6 | import json 7 | import re 8 | import urllib 9 | 10 | from .. import services 11 | 12 | class PlurkSearchView(View): 13 | def get(self, *args, **kwargs): 14 | keyword = kwargs['keyword'] 15 | 16 | url = 'https://www.plurk.com/Search/search2' 17 | 18 | title = 'Plurk Search - {}'.format(keyword) 19 | 20 | feed = feedgen.feed.FeedGenerator() 21 | feed.author({'name': 'Feed Generator'}) 22 | feed.id(url) 23 | feed.link(href=url, rel='alternate') 24 | feed.title(title) 25 | 26 | s = services.RequestsService().process() 27 | 28 | r = s.post(url, data={'query': keyword}) 29 | body = json.loads(r.text) 30 | 31 | users = body['users'] 32 | 33 | for p in body['plurks']: 34 | url = 'https://www.plurk.com/p/' + base36.dumps(p['id']) 35 | 36 | author = users[str(p['owner_id'])]['nick_name'] 37 | content = self.str_clean(p['content']) 38 | 39 | entry = feed.add_entry() 40 | entry.author(name=author) 41 | entry.content(content, type='CDATA') 42 | entry.id(url) 43 | entry.link(href=url) 44 | entry.published(dateutil.parser.parse(p['posted'])) 45 | entry.title(self.str_clean(p['content_raw']) or 'None') 46 | 47 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 48 | res['Cache-Control'] = 'max-age=300,public' 49 | 50 | return res 51 | 52 | def str_clean(self, s): 53 | return re.sub(r'[\x00-\x09]', ' ', s) 54 | 55 | class PlurkTopView(View): 56 | def get(self, *args, **kwargs): 57 | lang = kwargs['lang'] 58 | 59 | url = 'https://www.plurk.com/Stats/topReplurks?period=day&lang={}&limit=10'.format(urllib.parse.quote_plus(lang)) 60 | 61 | title = 'Plurk Top ({})'.format(lang) 62 | 63 | feed = feedgen.feed.FeedGenerator() 64 | feed.author({'name': 'Feed Generator'}) 65 | feed.id(url) 66 | feed.link(href=url, rel='alternate') 67 | feed.title(title) 68 | 69 | s = services.RequestsService().process() 70 | 71 | r = s.get(url) 72 | body = json.loads(r.text) 73 | 74 | for (x, stat) in body['stats']: 75 | url = 'https://www.plurk.com/p/' + base36.dumps(stat['id']) 76 | 77 | content = self.str_clean(stat['content']) 78 | content = re.sub(r' height="\d+(px)?"', ' ', content) 79 | content = re.sub(r' width="\d+(px)?"', ' ', content) 80 | 81 | entry = feed.add_entry() 82 | entry.author({'name': self.str_clean(stat['owner']['full_name'])}) 83 | entry.content(content, type='CDATA') 84 | entry.id(url) 85 | entry.link(href=url) 86 | entry.published(stat['posted']) 87 | entry.title(self.str_clean(stat['content_raw'])) 88 | 89 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 90 | res['Cache-Control'] = 'max-age=300,public' 91 | 92 | return res 93 | 94 | def str_clean(self, s): 95 | return re.sub(r'[\x00-\x09]', ' ', s) 96 | -------------------------------------------------------------------------------- /general/views/rent591.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import lxml.html 6 | import re 7 | 8 | from .. import services 9 | 10 | class Rent591View(View): 11 | def get(self, *args, **kwargs): 12 | region = kwargs['region'] 13 | keyword = kwargs['keyword'] 14 | 15 | # Support query string to filter results. 16 | qs = self.request.META.get('QUERY_STRING', '') 17 | if qs != '': 18 | qs = '&' + qs 19 | 20 | url = 'https://rent.591.com.tw/?kind=0&order=posttime&orderType=desc®ion={}&keywords={}{}'.format(region, keyword, qs) 21 | 22 | if qs == '': 23 | title = '591 出租搜尋 - {}'.format(keyword) 24 | else: 25 | title = '591 出租搜尋 - {} ({})'.format(keyword, qs) 26 | 27 | feed = feedgen.feed.FeedGenerator() 28 | feed.author({'name': 'Feed Generator'}) 29 | feed.id(url) 30 | feed.link(href=url, rel='alternate') 31 | feed.title(title) 32 | 33 | try: 34 | s = services.RequestsService().process() 35 | 36 | r = s.get(url) 37 | text = r.text 38 | except: 39 | text = '' 40 | 41 | body = lxml.html.fromstring(text) 42 | 43 | items = body.cssselect('#content > ul') 44 | 45 | for item in items: 46 | item_metainfo = item.cssselect('.infoContent .lightBox')[0].text_content() 47 | item_area = re.search(r'([\.0-9]+坪)', item_metainfo).group(1) 48 | item_desc = item.text_content() 49 | item_img = item.cssselect('.imageBox img')[0].get('data-original') 50 | item_price = item.cssselect('.price')[0].text_content() 51 | item_title = item.cssselect('.infoContent')[0].text_content() 52 | item_url = item.cssselect('a')[0].get('href') 53 | item_url = re.sub(r'^//', 'https://', item_url) 54 | 55 | item_price_num = item_price.replace(',', '') 56 | item_price_num = float(re.sub(r' .*', '', item_price_num)) 57 | item_area_num = float(re.sub(r'坪.*', '', item_area)) 58 | item_unitprice = int(item_price_num / item_area_num) 59 | 60 | content = '{}
{}
{}'.format( 61 | html.escape(item_title), 62 | html.escape(item_img), 63 | html.escape(item_title), 64 | html.escape(item_desc) 65 | ) 66 | 67 | entry = feed.add_entry() 68 | entry.content(content, type='xhtml') 69 | entry.id(item_url) 70 | entry.link(href=item_url) 71 | entry.title('${}/坪 - {} - {}'.format(item_unitprice, item_area, item_title)) 72 | 73 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 74 | res['Cache-Control'] = 'max-age=300,public' 75 | 76 | return res 77 | -------------------------------------------------------------------------------- /general/views/robotstxt.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | 4 | class RobotsTxtView(View): 5 | def get(self, *args, **kwargs): 6 | return HttpResponse("#\nUser-agent: *\nDisallow: *\n", content_type='text/plain') 7 | -------------------------------------------------------------------------------- /general/views/shopee.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import json 6 | import urllib 7 | 8 | from .. import services 9 | 10 | class ShopeeView(View): 11 | def get(self, *args, **kwargs): 12 | keyword = kwargs['keyword'] 13 | 14 | url = 'https://shopee.tw/api/v4/search/search_items/?by=ctime&keyword={}&limit=60&newest=0&order=desc&page_type=search&scenario=PAGE_GLOBAL_SEARCH&version=2'.format(urllib.parse.quote_plus(keyword)) 15 | referer = 'https://shopee.tw/search?keyword={}'.format(urllib.parse.quote_plus(keyword)) 16 | 17 | title = '蝦皮搜尋 - {}'.format(keyword) 18 | 19 | feed = feedgen.feed.FeedGenerator() 20 | feed.author({'name': 'Feed Generator'}) 21 | feed.id(url) 22 | feed.link(href=url, rel='alternate') 23 | feed.title(title) 24 | 25 | proxy = services.ProxySocks5Service().process() 26 | s = services.RequestsService().process() 27 | 28 | if proxy is not None: 29 | s.proxies = {'http': proxy, 'https': proxy} 30 | 31 | r = s.get(url, headers={'Referer': referer}) 32 | body = json.loads(r.text) 33 | items = body['items'] 34 | 35 | if not isinstance(items, list): 36 | items = [] 37 | 38 | for item in items: 39 | itemid = item['itemid'] 40 | item_basic = item['item_basic'] 41 | 42 | name = item_basic['name'] 43 | shopid = item_basic['shopid'] 44 | 45 | prod_url = 'https://shopee.tw/product/%d/%d' % (shopid, itemid) 46 | img_url = 'https://cf.shopee.tw/file/%s' % (item_basic['image']) 47 | 48 | content = '{}
{}'.format( 49 | html.escape(name), html.escape(name), html.escape(img_url) 50 | ) 51 | 52 | entry = feed.add_entry() 53 | entry.content(content, type='xhtml') 54 | entry.id(prod_url) 55 | entry.link(href=prod_url) 56 | entry.title(name) 57 | 58 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 59 | res['Cache-Control'] = 'max-age=300,public' 60 | 61 | return res 62 | -------------------------------------------------------------------------------- /general/views/taipeimetrotimetable.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import datetime 4 | import feedgen.feed 5 | import html 6 | 7 | from .. import services 8 | 9 | class TaipeiMetroTimetableView(View): 10 | def get(self, *args, **kwargs): 11 | keyword = kwargs['keyword'] 12 | 13 | url = 'https://web.metro.taipei/img/ALL/timetables/{}.PDF'.format(keyword) 14 | title = '台北捷運時刻表 - {}'.format(keyword) 15 | 16 | feed = feedgen.feed.FeedGenerator() 17 | feed.author({'name': 'Feed Generator'}) 18 | feed.id(url) 19 | feed.link(href=url, rel='alternate') 20 | feed.title(title) 21 | 22 | try: 23 | s = services.RequestsService().process() 24 | 25 | r = s.get(url) 26 | lastmodified = r.headers['last-modified'] 27 | t = datetime.datetime.strptime(lastmodified, '%a, %d %b %Y %H:%M:%S %Z') 28 | 29 | content = '

{}

'.format(html.escape(lastmodified)) 30 | id = '{}?v={}'.format(url, t.strftime('%s')) 31 | title = '台北捷運時刻表 ({}) - {}'.format(keyword, lastmodified) 32 | 33 | entry = feed.add_entry() 34 | entry.content(content, type='xhtml') 35 | entry.id(id) 36 | entry.link(href=url) 37 | entry.title(title) 38 | entry.updated(lastmodified) 39 | except: 40 | pass 41 | 42 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 43 | res['Cache-Control'] = 'max-age=300,public' 44 | 45 | return res 46 | -------------------------------------------------------------------------------- /general/views/yourator.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import urllib 6 | 7 | from .. import services 8 | 9 | class YouratorView(View): 10 | def get(self, *args, **kwargs): 11 | keyword = kwargs['keyword'] 12 | 13 | url = 'https://www.yourator.co/api/v2/jobs?term[]={}'.format(urllib.parse.quote_plus(keyword)) 14 | 15 | title = 'Yourator 搜尋 - {}'.format(keyword) 16 | 17 | feed = feedgen.feed.FeedGenerator() 18 | feed.author({'name': 'Feed Generator'}) 19 | feed.id(url) 20 | feed.link(href=url, rel='alternate') 21 | feed.title(title) 22 | 23 | try: 24 | s = services.RequestsService().process() 25 | 26 | r = s.get(url) 27 | items = r.json()['jobs'] 28 | except: 29 | items = [] 30 | 31 | for item in items: 32 | job_city = item['city'] 33 | job_company = item['company']['brand'] 34 | job_link = 'https://www.yourator.co' + item['path'] 35 | job_salary = item['salary'] 36 | job_title = item['name'] 37 | 38 | item_author = job_company 39 | item_content = '

{}

{} {}

'.format(html.escape(job_company), html.escape(job_city), html.escape(job_salary)) 40 | item_title = job_title 41 | item_url = job_link 42 | 43 | entry = feed.add_entry() 44 | entry.author({'name': item_author}) 45 | entry.content(item_content, type='xhtml') 46 | entry.id(item_url) 47 | entry.link(href=item_url) 48 | entry.title(item_title) 49 | 50 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 51 | res['Cache-Control'] = 'max-age=300,public' 52 | 53 | return res 54 | -------------------------------------------------------------------------------- /general/views/youtube.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic import View 3 | import feedgen.feed 4 | import html 5 | import json 6 | import re 7 | import urllib 8 | 9 | from .. import services 10 | 11 | class YouTubeView(View): 12 | def get(self, *args, **kwargs): 13 | keyword = kwargs['keyword'] 14 | 15 | url = 'https://www.youtube.com/results?search_query={}&sp=CAI%253D'.format(urllib.parse.quote_plus(keyword)) 16 | 17 | title = 'YouTube Search - {}'.format(keyword) 18 | 19 | feed = feedgen.feed.FeedGenerator() 20 | feed.author({'name': 'Feed Generator'}) 21 | feed.id(url) 22 | feed.link(href=url, rel='alternate') 23 | feed.title(title) 24 | 25 | s = services.RequestsService().process() 26 | 27 | r = s.get(url) 28 | 29 | m = re.search(r"var ytInitialData = (.*?);?", r.text, re.MULTILINE) 30 | ytInitialData = m.group(1) 31 | j = json.loads(ytInitialData) 32 | 33 | items = [] 34 | for loop in j['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents']: 35 | try: 36 | items += loop['itemSectionRenderer']['contents'] 37 | except KeyError: 38 | continue 39 | 40 | for item in items: 41 | try: 42 | # author 43 | author = item['videoRenderer']['longBylineText']['runs'][0]['text'] 44 | 45 | # link 46 | link = 'https://www.youtube.com/watch?v=' + urllib.parse.quote(item['videoRenderer']['videoId']) 47 | 48 | # img 49 | img = 'https://i.ytimg.com/vi/' + item['videoRenderer']['videoId'] + '/hqdefault.jpg' 50 | 51 | # title 52 | title = item['videoRenderer']['title']['runs'][0]['text'] 53 | 54 | # content 55 | content = '{}'.format( 56 | html.escape(title), html.escape(img) 57 | ) 58 | 59 | entry = feed.add_entry() 60 | entry.author({'name': author}) 61 | entry.content(content, type='xhtml') 62 | entry.id(link) 63 | entry.title(title) 64 | entry.link(href=link) 65 | 66 | except IndexError: 67 | pass 68 | except KeyError: 69 | pass 70 | 71 | res = HttpResponse(feed.atom_str(), content_type='application/atom+xml; charset=utf-8') 72 | res['Cache-Control'] = 'max-age=300,public' 73 | 74 | return res 75 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'feedgen_hasname.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "feedgen_hasname" 3 | version = "0.2024.0311.0" 4 | description = "feedgen.hasname.com" 5 | authors = [{ name = "Gea-Suan Lin", email = "gslin@gslin.com" }] 6 | requires-python = "~=3.13" 7 | readme = "README.md" 8 | license = "MIT" 9 | keywords = ["feed"] 10 | dependencies = [ 11 | "base36", 12 | "cssselect", 13 | "django", 14 | "django-service-objects", 15 | "feedgen", 16 | "lxml", 17 | "lxml_html_clean", 18 | "pip", 19 | "pysocks", 20 | "python-dateutil", 21 | "python-dotenv", 22 | "requests", 23 | "requests_futures", 24 | "sentry-sdk", 25 | "uwsgi", 26 | ] 27 | 28 | [project.urls] 29 | Homepage = "https://github.com/hasname/feedgen" 30 | Repository = "https://github.com/hasname/feedgen.git" 31 | 32 | [dependency-groups] 33 | dev = [ 34 | "coverage", 35 | "requests-mock", 36 | "ruff", 37 | ] 38 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 1 3 | requires-python = ">=3.13, <4" 4 | 5 | [[package]] 6 | name = "asgiref" 7 | version = "3.8.1" 8 | source = { registry = "https://pypi.org/simple" } 9 | sdist = { url = "https://files.pythonhosted.org/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186 } 10 | wheels = [ 11 | { url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828 }, 12 | ] 13 | 14 | [[package]] 15 | name = "base36" 16 | version = "0.1.1" 17 | source = { registry = "https://pypi.org/simple" } 18 | sdist = { url = "https://files.pythonhosted.org/packages/7e/63/e75b652d027bb394b67a61d232fd2f10d032ec3b8658dd81c593a9dfc25e/base36-0.1.1.tar.gz", hash = "sha256:6f221783c5499bd5fd4a1102054df9638d6232ff5ca850c21fd1efe5070c1a96", size = 2782 } 19 | wheels = [ 20 | { url = "https://files.pythonhosted.org/packages/d5/25/5ed7384b92e7c35909b8e939096cc24a13d64fc4e3a16c0d4b9438c3f88c/base36-0.1.1-py2.py3-none-any.whl", hash = "sha256:15eec75cf938a2186349e6b6dfc7320c73c065921493be83808c68d909b15763", size = 3530 }, 21 | ] 22 | 23 | [[package]] 24 | name = "certifi" 25 | version = "2025.1.31" 26 | source = { registry = "https://pypi.org/simple" } 27 | sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } 28 | wheels = [ 29 | { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, 30 | ] 31 | 32 | [[package]] 33 | name = "charset-normalizer" 34 | version = "3.4.1" 35 | source = { registry = "https://pypi.org/simple" } 36 | sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } 37 | wheels = [ 38 | { url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 }, 39 | { url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 }, 40 | { url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 }, 41 | { url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 }, 42 | { url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 }, 43 | { url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 }, 44 | { url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 }, 45 | { url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 }, 46 | { url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 }, 47 | { url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 }, 48 | { url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 }, 49 | { url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 }, 50 | { url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 }, 51 | { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 }, 52 | ] 53 | 54 | [[package]] 55 | name = "coverage" 56 | version = "7.7.1" 57 | source = { registry = "https://pypi.org/simple" } 58 | sdist = { url = "https://files.pythonhosted.org/packages/6b/bf/3effb7453498de9c14a81ca21e1f92e6723ce7ebdc5402ae30e4dcc490ac/coverage-7.7.1.tar.gz", hash = "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", size = 810332 } 59 | wheels = [ 60 | { url = "https://files.pythonhosted.org/packages/ec/2a/1a254eaadb01c163b29d6ce742aa380fc5cfe74a82138ce6eb944c42effa/coverage-7.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", size = 211277 }, 61 | { url = "https://files.pythonhosted.org/packages/cf/00/9636028365efd4eb6db71cdd01d99e59f25cf0d47a59943dbee32dd1573b/coverage-7.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", size = 211551 }, 62 | { url = "https://files.pythonhosted.org/packages/6f/c8/14aed97f80363f055b6cd91e62986492d9fe3b55e06b4b5c82627ae18744/coverage-7.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", size = 245068 }, 63 | { url = "https://files.pythonhosted.org/packages/d6/76/9c5fe3f900e01d7995b0cda08fc8bf9773b4b1be58bdd626f319c7d4ec11/coverage-7.7.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:392cc8fd2b1b010ca36840735e2a526fcbd76795a5d44006065e79868cc76ccf", size = 242109 }, 64 | { url = "https://files.pythonhosted.org/packages/c0/81/760993bb536fb674d3a059f718145dcd409ed6d00ae4e3cbf380019fdfd0/coverage-7.7.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bb47cc9f07a59a451361a850cb06d20633e77a9118d05fd0f77b1864439461b", size = 244129 }, 65 | { url = "https://files.pythonhosted.org/packages/00/be/1114a19f93eae0b6cd955dabb5bee80397bd420d846e63cd0ebffc134e3d/coverage-7.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b4c144c129343416a49378e05c9451c34aae5ccf00221e4fa4f487db0816ee2f", size = 244201 }, 66 | { url = "https://files.pythonhosted.org/packages/06/8d/9128fd283c660474c7dc2b1ea5c66761bc776b970c1724989ed70e9d6eee/coverage-7.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bc96441c9d9ca12a790b5ae17d2fa6654da4b3962ea15e0eabb1b1caed094777", size = 242282 }, 67 | { url = "https://files.pythonhosted.org/packages/d4/2a/6d7dbfe9c1f82e2cdc28d48f4a0c93190cf58f057fa91ba2391b92437fe6/coverage-7.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d03287eb03186256999539d98818c425c33546ab4901028c8fa933b62c35c3a", size = 243570 }, 68 | { url = "https://files.pythonhosted.org/packages/cf/3e/29f1e4ce3bb951bcf74b2037a82d94c5064b3334304a3809a95805628838/coverage-7.7.1-cp313-cp313-win32.whl", hash = "sha256:8fed429c26b99641dc1f3a79179860122b22745dd9af36f29b141e178925070a", size = 213772 }, 69 | { url = "https://files.pythonhosted.org/packages/bc/3a/cf029bf34aefd22ad34f0e808eba8d5830f297a1acb483a2124f097ff769/coverage-7.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:092b134129a8bb940c08b2d9ceb4459af5fb3faea77888af63182e17d89e1cf1", size = 214575 }, 70 | { url = "https://files.pythonhosted.org/packages/92/4c/fb8b35f186a2519126209dce91ab8644c9a901cf04f8dfa65576ca2dd9e8/coverage-7.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3154b369141c3169b8133973ac00f63fcf8d6dbcc297d788d36afbb7811e511", size = 212113 }, 71 | { url = "https://files.pythonhosted.org/packages/59/90/e834ffc86fd811c5b570a64ee1895b20404a247ec18a896b9ba543b12097/coverage-7.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:264ff2bcce27a7f455b64ac0dfe097680b65d9a1a293ef902675fa8158d20b24", size = 212333 }, 72 | { url = "https://files.pythonhosted.org/packages/a5/a1/27f0ad39569b3b02410b881c42e58ab403df13fcd465b475db514b83d3d3/coverage-7.7.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba8480ebe401c2f094d10a8c4209b800a9b77215b6c796d16b6ecdf665048950", size = 256566 }, 73 | { url = "https://files.pythonhosted.org/packages/9f/3b/21fa66a1db1b90a0633e771a32754f7c02d60236a251afb1b86d7e15d83a/coverage-7.7.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:520af84febb6bb54453e7fbb730afa58c7178fd018c398a8fcd8e269a79bf96d", size = 252276 }, 74 | { url = "https://files.pythonhosted.org/packages/d6/e5/4ab83a59b0f8ac4f0029018559fc4c7d042e1b4552a722e2bfb04f652296/coverage-7.7.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88d96127ae01ff571d465d4b0be25c123789cef88ba0879194d673fdea52f54e", size = 254616 }, 75 | { url = "https://files.pythonhosted.org/packages/db/7a/4224417c0ccdb16a5ba4d8d1fcfaa18439be1624c29435bb9bc88ccabdfb/coverage-7.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0ce92c5a9d7007d838456f4b77ea159cb628187a137e1895331e530973dcf862", size = 255707 }, 76 | { url = "https://files.pythonhosted.org/packages/51/20/ff18a329ccaa3d035e2134ecf3a2e92a52d3be6704c76e74ca5589ece260/coverage-7.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0dab4ef76d7b14f432057fdb7a0477e8bffca0ad39ace308be6e74864e632271", size = 253876 }, 77 | { url = "https://files.pythonhosted.org/packages/e4/e8/1d6f1a6651672c64f45ffad05306dad9c4c189bec694270822508049b2cb/coverage-7.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7e688010581dbac9cab72800e9076e16f7cccd0d89af5785b70daa11174e94de", size = 254687 }, 78 | { url = "https://files.pythonhosted.org/packages/6b/ea/1b9a14cf3e2bc3fd9de23a336a8082091711c5f480b500782d59e84a8fe5/coverage-7.7.1-cp313-cp313t-win32.whl", hash = "sha256:e52eb31ae3afacdacfe50705a15b75ded67935770c460d88c215a9c0c40d0e9c", size = 214486 }, 79 | { url = "https://files.pythonhosted.org/packages/cc/bb/faa6bcf769cb7b3b660532a30d77c440289b40636c7f80e498b961295d07/coverage-7.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a6b6b3bd121ee2ec4bd35039319f3423d0be282b9752a5ae9f18724bc93ebe7c", size = 215647 }, 80 | { url = "https://files.pythonhosted.org/packages/52/26/9f53293ff4cc1d47d98367ce045ca2e62746d6be74a5c6851a474eabf59b/coverage-7.7.1-py3-none-any.whl", hash = "sha256:822fa99dd1ac686061e1219b67868e25d9757989cf2259f735a4802497d6da31", size = 203006 }, 81 | ] 82 | 83 | [[package]] 84 | name = "cssselect" 85 | version = "1.3.0" 86 | source = { registry = "https://pypi.org/simple" } 87 | sdist = { url = "https://files.pythonhosted.org/packages/72/0a/c3ea9573b1dc2e151abfe88c7fe0c26d1892fe6ed02d0cdb30f0d57029d5/cssselect-1.3.0.tar.gz", hash = "sha256:57f8a99424cfab289a1b6a816a43075a4b00948c86b4dcf3ef4ee7e15f7ab0c7", size = 42870 } 88 | wheels = [ 89 | { url = "https://files.pythonhosted.org/packages/ee/58/257350f7db99b4ae12b614a36256d9cc870d71d9e451e79c2dc3b23d7c3c/cssselect-1.3.0-py3-none-any.whl", hash = "sha256:56d1bf3e198080cc1667e137bc51de9cadfca259f03c2d4e09037b3e01e30f0d", size = 18786 }, 90 | ] 91 | 92 | [[package]] 93 | name = "django" 94 | version = "5.1.7" 95 | source = { registry = "https://pypi.org/simple" } 96 | dependencies = [ 97 | { name = "asgiref" }, 98 | { name = "sqlparse" }, 99 | { name = "tzdata", marker = "sys_platform == 'win32'" }, 100 | ] 101 | sdist = { url = "https://files.pythonhosted.org/packages/5f/57/11186e493ddc5a5e92cc7924a6363f7d4c2b645f7d7cb04a26a63f9bfb8b/Django-5.1.7.tar.gz", hash = "sha256:30de4ee43a98e5d3da36a9002f287ff400b43ca51791920bfb35f6917bfe041c", size = 10716510 } 102 | wheels = [ 103 | { url = "https://files.pythonhosted.org/packages/ba/0f/7e042df3d462d39ae01b27a09ee76653692442bc3701fbfa6cb38e12889d/Django-5.1.7-py3-none-any.whl", hash = "sha256:1323617cb624add820cb9611cdcc788312d250824f92ca6048fda8625514af2b", size = 8276912 }, 104 | ] 105 | 106 | [[package]] 107 | name = "django-service-objects" 108 | version = "0.7.1" 109 | source = { registry = "https://pypi.org/simple" } 110 | dependencies = [ 111 | { name = "django" }, 112 | { name = "six" }, 113 | ] 114 | sdist = { url = "https://files.pythonhosted.org/packages/5d/41/86414421c90af067a9ca232bfb86c486ed1dcc7a9da4f5925ee85189252d/django-service-objects-0.7.1.tar.gz", hash = "sha256:9c14c383149f7369c2306439a8b1fec3d6c85c129e8e22479c131efab1530eb1", size = 9759 } 115 | wheels = [ 116 | { url = "https://files.pythonhosted.org/packages/56/8d/290d9cdf0954da637f723717b2f2debd354d3d3cf7b251c6357f172a1f80/django_service_objects-0.7.1-py3-none-any.whl", hash = "sha256:c13961062f35c68d8f59a98f75e970636aa8d4fc7e9dad85d222a39c13151449", size = 11075 }, 117 | ] 118 | 119 | [[package]] 120 | name = "feedgen" 121 | version = "1.0.0" 122 | source = { registry = "https://pypi.org/simple" } 123 | dependencies = [ 124 | { name = "lxml" }, 125 | { name = "python-dateutil" }, 126 | ] 127 | sdist = { url = "https://files.pythonhosted.org/packages/6b/59/be0a6f852b5dfbf19e6c8e962c8f41407697f9f52a7902250ed98683ae89/feedgen-1.0.0.tar.gz", hash = "sha256:d9bd51c3b5e956a2a52998c3708c4d2c729f2fcc311188e1e5d3b9726393546a", size = 258496 } 128 | 129 | [[package]] 130 | name = "feedgen-hasname" 131 | version = "0.2024.311.0" 132 | source = { virtual = "." } 133 | dependencies = [ 134 | { name = "base36" }, 135 | { name = "cssselect" }, 136 | { name = "django" }, 137 | { name = "django-service-objects" }, 138 | { name = "feedgen" }, 139 | { name = "lxml" }, 140 | { name = "lxml-html-clean" }, 141 | { name = "pip" }, 142 | { name = "pysocks" }, 143 | { name = "python-dateutil" }, 144 | { name = "python-dotenv" }, 145 | { name = "requests" }, 146 | { name = "requests-futures" }, 147 | { name = "sentry-sdk" }, 148 | { name = "uwsgi" }, 149 | ] 150 | 151 | [package.dev-dependencies] 152 | dev = [ 153 | { name = "coverage" }, 154 | { name = "requests-mock" }, 155 | { name = "ruff" }, 156 | ] 157 | 158 | [package.metadata] 159 | requires-dist = [ 160 | { name = "base36" }, 161 | { name = "cssselect" }, 162 | { name = "django" }, 163 | { name = "django-service-objects" }, 164 | { name = "feedgen" }, 165 | { name = "lxml" }, 166 | { name = "lxml-html-clean" }, 167 | { name = "pip" }, 168 | { name = "pysocks" }, 169 | { name = "python-dateutil" }, 170 | { name = "python-dotenv" }, 171 | { name = "requests" }, 172 | { name = "requests-futures" }, 173 | { name = "sentry-sdk" }, 174 | { name = "uwsgi" }, 175 | ] 176 | 177 | [package.metadata.requires-dev] 178 | dev = [ 179 | { name = "coverage" }, 180 | { name = "requests-mock" }, 181 | { name = "ruff" }, 182 | ] 183 | 184 | [[package]] 185 | name = "idna" 186 | version = "3.10" 187 | source = { registry = "https://pypi.org/simple" } 188 | sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } 189 | wheels = [ 190 | { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, 191 | ] 192 | 193 | [[package]] 194 | name = "lxml" 195 | version = "5.3.1" 196 | source = { registry = "https://pypi.org/simple" } 197 | sdist = { url = "https://files.pythonhosted.org/packages/ef/f6/c15ca8e5646e937c148e147244817672cf920b56ac0bf2cc1512ae674be8/lxml-5.3.1.tar.gz", hash = "sha256:106b7b5d2977b339f1e97efe2778e2ab20e99994cbb0ec5e55771ed0795920c8", size = 3678591 } 198 | wheels = [ 199 | { url = "https://files.pythonhosted.org/packages/94/1c/724931daa1ace168e0237b929e44062545bf1551974102a5762c349c668d/lxml-5.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c093c7088b40d8266f57ed71d93112bd64c6724d31f0794c1e52cc4857c28e0e", size = 8171881 }, 200 | { url = "https://files.pythonhosted.org/packages/67/0c/857b8fb6010c4246e66abeebb8639eaabba60a6d9b7c606554ecc5cbf1ee/lxml-5.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0884e3f22d87c30694e625b1e62e6f30d39782c806287450d9dc2fdf07692fd", size = 4440394 }, 201 | { url = "https://files.pythonhosted.org/packages/61/72/c9e81de6a000f9682ccdd13503db26e973b24c68ac45a7029173237e3eed/lxml-5.3.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1637fa31ec682cd5760092adfabe86d9b718a75d43e65e211d5931809bc111e7", size = 5037860 }, 202 | { url = "https://files.pythonhosted.org/packages/24/26/942048c4b14835711b583b48cd7209bd2b5f0b6939ceed2381a494138b14/lxml-5.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a364e8e944d92dcbf33b6b494d4e0fb3499dcc3bd9485beb701aa4b4201fa414", size = 4782513 }, 203 | { url = "https://files.pythonhosted.org/packages/e2/65/27792339caf00f610cc5be32b940ba1e3009b7054feb0c4527cebac228d4/lxml-5.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:779e851fd0e19795ccc8a9bb4d705d6baa0ef475329fe44a13cf1e962f18ff1e", size = 5305227 }, 204 | { url = "https://files.pythonhosted.org/packages/18/e1/25f7aa434a4d0d8e8420580af05ea49c3e12db6d297cf5435ac0a054df56/lxml-5.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c4393600915c308e546dc7003d74371744234e8444a28622d76fe19b98fa59d1", size = 4829846 }, 205 | { url = "https://files.pythonhosted.org/packages/fe/ed/faf235e0792547d24f61ee1448159325448a7e4f2ab706503049d8e5df19/lxml-5.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:673b9d8e780f455091200bba8534d5f4f465944cbdd61f31dc832d70e29064a5", size = 4949495 }, 206 | { url = "https://files.pythonhosted.org/packages/e5/e1/8f572ad9ed6039ba30f26dd4c2c58fb90f79362d2ee35ca3820284767672/lxml-5.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2e4a570f6a99e96c457f7bec5ad459c9c420ee80b99eb04cbfcfe3fc18ec6423", size = 4773415 }, 207 | { url = "https://files.pythonhosted.org/packages/a3/75/6b57166b9d1983dac8f28f354e38bff8d6bcab013a241989c4d54c72701b/lxml-5.3.1-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:71f31eda4e370f46af42fc9f264fafa1b09f46ba07bdbee98f25689a04b81c20", size = 5337710 }, 208 | { url = "https://files.pythonhosted.org/packages/cc/71/4aa56e2daa83bbcc66ca27b5155be2f900d996f5d0c51078eaaac8df9547/lxml-5.3.1-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:42978a68d3825eaac55399eb37a4d52012a205c0c6262199b8b44fcc6fd686e8", size = 4897362 }, 209 | { url = "https://files.pythonhosted.org/packages/65/10/3fa2da152cd9b49332fd23356ed7643c9b74cad636ddd5b2400a9730d12b/lxml-5.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:8b1942b3e4ed9ed551ed3083a2e6e0772de1e5e3aca872d955e2e86385fb7ff9", size = 4977795 }, 210 | { url = "https://files.pythonhosted.org/packages/de/d2/e1da0f7b20827e7b0ce934963cb6334c1b02cf1bb4aecd218c4496880cb3/lxml-5.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:85c4f11be9cf08917ac2a5a8b6e1ef63b2f8e3799cec194417e76826e5f1de9c", size = 4858104 }, 211 | { url = "https://files.pythonhosted.org/packages/a5/35/063420e1b33d3308f5aa7fcbdd19ef6c036f741c9a7a4bd5dc8032486b27/lxml-5.3.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:231cf4d140b22a923b1d0a0a4e0b4f972e5893efcdec188934cc65888fd0227b", size = 5416531 }, 212 | { url = "https://files.pythonhosted.org/packages/c3/83/93a6457d291d1e37adfb54df23498101a4701834258c840381dd2f6a030e/lxml-5.3.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5865b270b420eda7b68928d70bb517ccbe045e53b1a428129bb44372bf3d7dd5", size = 5273040 }, 213 | { url = "https://files.pythonhosted.org/packages/39/25/ad4ac8fac488505a2702656550e63c2a8db3a4fd63db82a20dad5689cecb/lxml-5.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7bebc2275016cddf3c997bf8a0f7044160714c64a9b83975670a04e6d2252", size = 5050951 }, 214 | { url = "https://files.pythonhosted.org/packages/82/74/f7d223c704c87e44b3d27b5e0dde173a2fcf2e89c0524c8015c2b3554876/lxml-5.3.1-cp313-cp313-win32.whl", hash = "sha256:d0751528b97d2b19a388b302be2a0ee05817097bab46ff0ed76feeec24951f78", size = 3485357 }, 215 | { url = "https://files.pythonhosted.org/packages/80/83/8c54533b3576f4391eebea88454738978669a6cad0d8e23266224007939d/lxml-5.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:91fb6a43d72b4f8863d21f347a9163eecbf36e76e2f51068d59cd004c506f332", size = 3814484 }, 216 | ] 217 | 218 | [[package]] 219 | name = "lxml-html-clean" 220 | version = "0.4.1" 221 | source = { registry = "https://pypi.org/simple" } 222 | dependencies = [ 223 | { name = "lxml" }, 224 | ] 225 | sdist = { url = "https://files.pythonhosted.org/packages/81/f2/fe319e3c5cb505a361b95d1e0d0d793fe28d4dcc2fc39d3cae9324dc4233/lxml_html_clean-0.4.1.tar.gz", hash = "sha256:40c838bbcf1fc72ba4ce811fbb3135913017b27820d7c16e8bc412ae1d8bc00b", size = 21378 } 226 | wheels = [ 227 | { url = "https://files.pythonhosted.org/packages/f7/ba/2af7a60b45bf21375e111c1e2d5d721108d06c80e3d9a3cc1d767afe1731/lxml_html_clean-0.4.1-py3-none-any.whl", hash = "sha256:b704f2757e61d793b1c08bf5ad69e4c0b68d6696f4c3c1429982caf90050bcaf", size = 14114 }, 228 | ] 229 | 230 | [[package]] 231 | name = "pip" 232 | version = "25.0.1" 233 | source = { registry = "https://pypi.org/simple" } 234 | sdist = { url = "https://files.pythonhosted.org/packages/70/53/b309b4a497b09655cb7e07088966881a57d082f48ac3cb54ea729fd2c6cf/pip-25.0.1.tar.gz", hash = "sha256:88f96547ea48b940a3a385494e181e29fb8637898f88d88737c5049780f196ea", size = 1950850 } 235 | wheels = [ 236 | { url = "https://files.pythonhosted.org/packages/c9/bc/b7db44f5f39f9d0494071bddae6880eb645970366d0a200022a1a93d57f5/pip-25.0.1-py3-none-any.whl", hash = "sha256:c46efd13b6aa8279f33f2864459c8ce587ea6a1a59ee20de055868d8f7688f7f", size = 1841526 }, 237 | ] 238 | 239 | [[package]] 240 | name = "pysocks" 241 | version = "1.7.1" 242 | source = { registry = "https://pypi.org/simple" } 243 | sdist = { url = "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0", size = 284429 } 244 | wheels = [ 245 | { url = "https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", size = 16725 }, 246 | ] 247 | 248 | [[package]] 249 | name = "python-dateutil" 250 | version = "2.9.0.post0" 251 | source = { registry = "https://pypi.org/simple" } 252 | dependencies = [ 253 | { name = "six" }, 254 | ] 255 | sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } 256 | wheels = [ 257 | { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, 258 | ] 259 | 260 | [[package]] 261 | name = "python-dotenv" 262 | version = "1.1.0" 263 | source = { registry = "https://pypi.org/simple" } 264 | sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920 } 265 | wheels = [ 266 | { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 }, 267 | ] 268 | 269 | [[package]] 270 | name = "requests" 271 | version = "2.32.3" 272 | source = { registry = "https://pypi.org/simple" } 273 | dependencies = [ 274 | { name = "certifi" }, 275 | { name = "charset-normalizer" }, 276 | { name = "idna" }, 277 | { name = "urllib3" }, 278 | ] 279 | sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } 280 | wheels = [ 281 | { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, 282 | ] 283 | 284 | [[package]] 285 | name = "requests-futures" 286 | version = "1.0.2" 287 | source = { registry = "https://pypi.org/simple" } 288 | dependencies = [ 289 | { name = "requests" }, 290 | ] 291 | sdist = { url = "https://files.pythonhosted.org/packages/88/f8/175b823241536ba09da033850d66194c372c65c38804847ac9cef0239542/requests_futures-1.0.2.tar.gz", hash = "sha256:6b7eb57940336e800faebc3dab506360edec9478f7b22dc570858ad3aa7458da", size = 10356 } 292 | wheels = [ 293 | { url = "https://files.pythonhosted.org/packages/91/23/7c1096731c15c83826cb0dd42078b561a838aed44c36f370aeb815168106/requests_futures-1.0.2-py2.py3-none-any.whl", hash = "sha256:a3534af7c2bf670cd7aa730716e9e7d4386497554f87792be7514063b8912897", size = 7671 }, 294 | ] 295 | 296 | [[package]] 297 | name = "requests-mock" 298 | version = "1.12.1" 299 | source = { registry = "https://pypi.org/simple" } 300 | dependencies = [ 301 | { name = "requests" }, 302 | ] 303 | sdist = { url = "https://files.pythonhosted.org/packages/92/32/587625f91f9a0a3d84688bf9cfc4b2480a7e8ec327cefd0ff2ac891fd2cf/requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401", size = 60901 } 304 | wheels = [ 305 | { url = "https://files.pythonhosted.org/packages/97/ec/889fbc557727da0c34a33850950310240f2040f3b1955175fdb2b36a8910/requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563", size = 27695 }, 306 | ] 307 | 308 | [[package]] 309 | name = "ruff" 310 | version = "0.11.2" 311 | source = { registry = "https://pypi.org/simple" } 312 | sdist = { url = "https://files.pythonhosted.org/packages/90/61/fb87430f040e4e577e784e325351186976516faef17d6fcd921fe28edfd7/ruff-0.11.2.tar.gz", hash = "sha256:ec47591497d5a1050175bdf4e1a4e6272cddff7da88a2ad595e1e326041d8d94", size = 3857511 } 313 | wheels = [ 314 | { url = "https://files.pythonhosted.org/packages/62/99/102578506f0f5fa29fd7e0df0a273864f79af044757aef73d1cae0afe6ad/ruff-0.11.2-py3-none-linux_armv6l.whl", hash = "sha256:c69e20ea49e973f3afec2c06376eb56045709f0212615c1adb0eda35e8a4e477", size = 10113146 }, 315 | { url = "https://files.pythonhosted.org/packages/74/ad/5cd4ba58ab602a579997a8494b96f10f316e874d7c435bcc1a92e6da1b12/ruff-0.11.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2c5424cc1c4eb1d8ecabe6d4f1b70470b4f24a0c0171356290b1953ad8f0e272", size = 10867092 }, 316 | { url = "https://files.pythonhosted.org/packages/fc/3e/d3f13619e1d152c7b600a38c1a035e833e794c6625c9a6cea6f63dbf3af4/ruff-0.11.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ecf20854cc73f42171eedb66f006a43d0a21bfb98a2523a809931cda569552d9", size = 10224082 }, 317 | { url = "https://files.pythonhosted.org/packages/90/06/f77b3d790d24a93f38e3806216f263974909888fd1e826717c3ec956bbcd/ruff-0.11.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c543bf65d5d27240321604cee0633a70c6c25c9a2f2492efa9f6d4b8e4199bb", size = 10394818 }, 318 | { url = "https://files.pythonhosted.org/packages/99/7f/78aa431d3ddebfc2418cd95b786642557ba8b3cb578c075239da9ce97ff9/ruff-0.11.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20967168cc21195db5830b9224be0e964cc9c8ecf3b5a9e3ce19876e8d3a96e3", size = 9952251 }, 319 | { url = "https://files.pythonhosted.org/packages/30/3e/f11186d1ddfaca438c3bbff73c6a2fdb5b60e6450cc466129c694b0ab7a2/ruff-0.11.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:955a9ce63483999d9f0b8f0b4a3ad669e53484232853054cc8b9d51ab4c5de74", size = 11563566 }, 320 | { url = "https://files.pythonhosted.org/packages/22/6c/6ca91befbc0a6539ee133d9a9ce60b1a354db12c3c5d11cfdbf77140f851/ruff-0.11.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:86b3a27c38b8fce73bcd262b0de32e9a6801b76d52cdb3ae4c914515f0cef608", size = 12208721 }, 321 | { url = "https://files.pythonhosted.org/packages/19/b0/24516a3b850d55b17c03fc399b681c6a549d06ce665915721dc5d6458a5c/ruff-0.11.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3b66a03b248c9fcd9d64d445bafdf1589326bee6fc5c8e92d7562e58883e30f", size = 11662274 }, 322 | { url = "https://files.pythonhosted.org/packages/d7/65/76be06d28ecb7c6070280cef2bcb20c98fbf99ff60b1c57d2fb9b8771348/ruff-0.11.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0397c2672db015be5aa3d4dac54c69aa012429097ff219392c018e21f5085147", size = 13792284 }, 323 | { url = "https://files.pythonhosted.org/packages/ce/d2/4ceed7147e05852876f3b5f3fdc23f878ce2b7e0b90dd6e698bda3d20787/ruff-0.11.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:869bcf3f9abf6457fbe39b5a37333aa4eecc52a3b99c98827ccc371a8e5b6f1b", size = 11327861 }, 324 | { url = "https://files.pythonhosted.org/packages/c4/78/4935ecba13706fd60ebe0e3dc50371f2bdc3d9bc80e68adc32ff93914534/ruff-0.11.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2a2b50ca35457ba785cd8c93ebbe529467594087b527a08d487cf0ee7b3087e9", size = 10276560 }, 325 | { url = "https://files.pythonhosted.org/packages/81/7f/1b2435c3f5245d410bb5dc80f13ec796454c21fbda12b77d7588d5cf4e29/ruff-0.11.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7c69c74bf53ddcfbc22e6eb2f31211df7f65054bfc1f72288fc71e5f82db3eab", size = 9945091 }, 326 | { url = "https://files.pythonhosted.org/packages/39/c4/692284c07e6bf2b31d82bb8c32f8840f9d0627d92983edaac991a2b66c0a/ruff-0.11.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6e8fb75e14560f7cf53b15bbc55baf5ecbe373dd5f3aab96ff7aa7777edd7630", size = 10977133 }, 327 | { url = "https://files.pythonhosted.org/packages/94/cf/8ab81cb7dd7a3b0a3960c2769825038f3adcd75faf46dd6376086df8b128/ruff-0.11.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:842a472d7b4d6f5924e9297aa38149e5dcb1e628773b70e6387ae2c97a63c58f", size = 11378514 }, 328 | { url = "https://files.pythonhosted.org/packages/d9/3a/a647fa4f316482dacf2fd68e8a386327a33d6eabd8eb2f9a0c3d291ec549/ruff-0.11.2-py3-none-win32.whl", hash = "sha256:aca01ccd0eb5eb7156b324cfaa088586f06a86d9e5314b0eb330cb48415097cc", size = 10319835 }, 329 | { url = "https://files.pythonhosted.org/packages/86/54/3c12d3af58012a5e2cd7ebdbe9983f4834af3f8cbea0e8a8c74fa1e23b2b/ruff-0.11.2-py3-none-win_amd64.whl", hash = "sha256:3170150172a8f994136c0c66f494edf199a0bbea7a409f649e4bc8f4d7084080", size = 11373713 }, 330 | { url = "https://files.pythonhosted.org/packages/d6/d4/dd813703af8a1e2ac33bf3feb27e8a5ad514c9f219df80c64d69807e7f71/ruff-0.11.2-py3-none-win_arm64.whl", hash = "sha256:52933095158ff328f4c77af3d74f0379e34fd52f175144cefc1b192e7ccd32b4", size = 10441990 }, 331 | ] 332 | 333 | [[package]] 334 | name = "sentry-sdk" 335 | version = "2.24.1" 336 | source = { registry = "https://pypi.org/simple" } 337 | dependencies = [ 338 | { name = "certifi" }, 339 | { name = "urllib3" }, 340 | ] 341 | sdist = { url = "https://files.pythonhosted.org/packages/f1/ef/4847dcd63e3f3c451cf701a825d21200f1322d46ac97586d5c90a13dfea1/sentry_sdk-2.24.1.tar.gz", hash = "sha256:8ba3c29990fa48865b908b3b9dc5ae7fa7e72407c7c9e91303e5206b32d7b8b1", size = 318124 } 342 | wheels = [ 343 | { url = "https://files.pythonhosted.org/packages/65/95/91137ffe7a5956496155af5ffbe45ee4ddfa795a569136147e766abd14b1/sentry_sdk-2.24.1-py2.py3-none-any.whl", hash = "sha256:36baa6a1128b9d98d2adc5e9b2f887eff0a6af558fc2b96ed51919042413556d", size = 336945 }, 344 | ] 345 | 346 | [[package]] 347 | name = "six" 348 | version = "1.17.0" 349 | source = { registry = "https://pypi.org/simple" } 350 | sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } 351 | wheels = [ 352 | { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, 353 | ] 354 | 355 | [[package]] 356 | name = "sqlparse" 357 | version = "0.5.3" 358 | source = { registry = "https://pypi.org/simple" } 359 | sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999 } 360 | wheels = [ 361 | { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415 }, 362 | ] 363 | 364 | [[package]] 365 | name = "tzdata" 366 | version = "2025.2" 367 | source = { registry = "https://pypi.org/simple" } 368 | sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380 } 369 | wheels = [ 370 | { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 }, 371 | ] 372 | 373 | [[package]] 374 | name = "urllib3" 375 | version = "2.3.0" 376 | source = { registry = "https://pypi.org/simple" } 377 | sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } 378 | wheels = [ 379 | { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, 380 | ] 381 | 382 | [[package]] 383 | name = "uwsgi" 384 | version = "2.0.28" 385 | source = { registry = "https://pypi.org/simple" } 386 | sdist = { url = "https://files.pythonhosted.org/packages/24/c2/d58480aadc9a1f420dd96fc43cf0dcd8cb5ededb95cab53743529c23b6cd/uwsgi-2.0.28.tar.gz", hash = "sha256:79ca1891ef2df14508ab0471ee8c0eb94bd2d51d03f32f90c4bbe557ab1e99d0", size = 816212 } 387 | -------------------------------------------------------------------------------- /uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | chdir = /home/service-feedgen/feedgen 3 | enable-threads = true 4 | http-socket = :8000 5 | master = true 6 | threads = 4 7 | wsgi-file = /home/service-feedgen/feedgen/feedgen_hasname/wsgi.py 8 | --------------------------------------------------------------------------------