<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: doogee “doogeetop” top</title>
    <description>The latest articles on DEV Community by doogee “doogeetop” top (@doogee_doogeetoptop_1e).</description>
    <link>https://dev.to/doogee_doogeetoptop_1e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4201403%2Fa88bda62-a33d-46d4-ae2d-35c79ebdb602.jpg</url>
      <title>DEV Community: doogee “doogeetop” top</title>
      <link>https://dev.to/doogee_doogeetoptop_1e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/doogee_doogeetoptop_1e"/>
    <language>en</language>
    <item>
      <title>996 Isn't a Schedule. It's a Bargain Nobody Signed</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Thu, 12 Nov 2026 00:21:37 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/996-isnt-a-schedule-its-a-bargain-nobody-signed-3a3c</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/996-isnt-a-schedule-its-a-bargain-nobody-signed-3a3c</guid>
      <description>&lt;p&gt;In January 2021, a 22-year-old employee of the Chinese e-commerce company Pinduoduo died after leaving work at around 1:30 a.m. She collapsed on her way home. Her exact cause of death was never publicly confirmed, and that uncertainty matters: it is precisely what turned a private tragedy into a public argument about how Chinese tech companies treat working time.&lt;/p&gt;

&lt;p&gt;The case did not become famous because of the death alone. It became famous because of what happened next. An account bearing Pinduoduo's name responded to questions about the death on Zhihu, a Chinese Q&amp;amp;A platform, with a message that essentially told readers that ordinary people survive by trading their health for money, and that this is simply the age we live in. The reply was deleted within half an hour, but screenshots had already spread across Weibo, where the topic drew hundreds of millions of views. Pinduoduo later said the reply did not represent the company, attributing it to an employee of a supplier who had forgotten to log out of the company's account. Shanghai's labour authorities opened an investigation into the company's employment practices.&lt;/p&gt;

&lt;p&gt;Strip away the corporate damage control and you are left with the real subject: 996. The term describes a schedule of 9 a.m. to 9 p.m., six days a week, which adds up to roughly 72 hours. China's Labour Law sets a standard of no more than 8 hours a day and 44 hours a week. The gap between the law and the lived schedule is the whole story, and everyone involved knows it.&lt;/p&gt;

&lt;p&gt;996 was not new in 2021. In 2019, tens of thousands of programmers staged a rare online protest over working hours, and the debate reached the founders of China's biggest tech companies. Alibaba's Jack Ma publicly defended the schedule as a kind of blessing; the heads of JD.com and Xiaomi voiced support for intense work cultures as well. The protest changed very little. A 2019 survey by the recruitment platform Zhaopin, cited by the BBC, found that more than 80 percent of over 10,000 respondents regularly worked overtime, and 70 percent said that overtime was unpaid. Product and engineering roles reported the worst of it.&lt;/p&gt;

&lt;p&gt;Why does the schedule survive when the law, on paper, forbids it? Legal scholars quoted in the BBC's coverage pointed to the escape hatches companies use: unfinished tasks, and the fiction of voluntary overtime. When promotion, bonuses, and even keeping your job depend on staying late, overtime is voluntary in the same way that breathing underwater is optional. The choice is formally yours and practically absent.&lt;/p&gt;

&lt;p&gt;Pinduoduo itself is a useful lens because its rise was so fast. Founded in 2015, it reached a market value above 200 billion dollars by the end of 2020 on the back of low prices and discount-driven growth in smaller cities. Former employees told the BBC that a typical day started at 11 a.m. and ran more than twelve hours, six days a week, with lunch breaks cut from two hours to one and even bathroom habits policed by signs. Pay was reportedly higher than at peers like Alibaba and Tencent, and far above average Chinese wages. That is the bargain in its bluntest form: more money, in exchange for more of your life, with the exchange rate set entirely by the employer.&lt;/p&gt;

&lt;p&gt;The 2021 case is worth revisiting not because it resolved anything, but because it exposed the three layers of the problem at once. First, the human layer: a young worker dead after a midnight finish, with no confirmed medical explanation made public. Second, the corporate layer: a company whose first instinct was to minimise, then to disown its own account's words, then to blame a supplier's employee. Third, the structural layer: a labour market where the legal ceiling on hours is widely ignored, where enforcement arrives only after a death makes headlines, and where public anger burns hot for a week and then moves on.&lt;/p&gt;

&lt;p&gt;There is a temptation to treat 996 as a Chinese curiosity. It is not. Every industry that pays by output while measuring commitment by presence eventually invents its own version of it. The pattern is always the same: a schedule that nobody formally mandates, a promotion system that quietly rewards it, and a vocabulary that reframes exhaustion as ambition. When a founder calls overwork a blessing, he is not describing a schedule. He is giving employees a story that makes it harder for them to object.&lt;/p&gt;

&lt;p&gt;So what actually changes a 996 culture? Not slogans, and not one investigation opened under media pressure. Three things have to move together. Overtime has to be paid and recorded, so that the real cost of the schedule shows up on a company's books instead of in its employees' bodies. Promotion criteria have to be written down and audited, so that staying late stops being an unspoken requirement. And workers need a channel to refuse without fear, which is the one thing no internal handbook has ever provided on its own.&lt;/p&gt;

&lt;p&gt;The Pinduoduo case ended the way most of these cases end: an investigation, a round of apologies, and a debate that flared and faded. The schedule it was about did not fade. That is why the story still deserves a retelling, not as a scandal, but as a question that has never been answered: if a company can only win by working its people 72 hours a week, what exactly is it winning, and who is paying for it?&lt;/p&gt;

&lt;p&gt;I write about work, building, and the human cost of moving fast over at Airgrix (&lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;https://airgrix.com&lt;/a&gt;), where I also run a small independent store.&lt;/p&gt;

</description>
      <category>career</category>
      <category>workplace</category>
      <category>tech</category>
    </item>
    <item>
      <title>GMKtec: How a Shenzhen Mini-PC Maker Sells $170 Boxes and a $6,799 AI Flagship From One Shopify Store</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Tue, 10 Nov 2026 12:22:11 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/gmktec-how-a-shenzhen-mini-pc-maker-sells-170-boxes-and-a-6799-ai-flagship-from-one-shopify-2pbn</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/gmktec-how-a-shenzhen-mini-pc-maker-sells-170-boxes-and-a-6799-ai-flagship-from-one-shopify-2pbn</guid>
      <description>&lt;h1&gt;
  
  
  GMKtec: One Store, a $170 Box and a $6,799 AI Flagship
&lt;/h1&gt;

&lt;p&gt;GMKtec is a Shenzhen mini-PC brand selling direct to the world from a single Shopify store (gmktec.com), and it's a clean little case study in how Chinese hardware makers now run global DTC. I counted 63 products on the store. The cheapest, a NucBox G11 Plus, is $169.99. The most expensive, the EVO-X5 Pro built on AMD's Ryzen AI Max+ PRO 495, is $6,799. Same store, same cart, a 40× price spread — and the architecture of the catalogue is what makes that work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The catalogue is organised the way buyers actually think.&lt;/strong&gt; Collections are split first by product line — G series (budget boxes), M series (mainstream), K series (performance), EVO series (AI flagships), NEO series — and then cross-cut by chip platform, with separate AMD Ryzen and Intel collections. A hobbyist shopping "a Ryzen box under $300" and an AI tinkerer shopping "the Strix Halo one" both land in a collection that speaks their language in one click. Around the PCs sits a thin accessories layer (keyboard/mouse combos, USB-C docks) and a clearance collection — the classic move for keeping ageing SKUs revenue-positive instead of deleting them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The product names are the SEO.&lt;/strong&gt; Handles read like spec sheets: &lt;em&gt;amd-ryzen-7-7840hs-mini-pc-nucbox-k6&lt;/em&gt;. Nobody brands-searches "NucBox K6" who doesn't already know it; everybody searches the chip. By stuffing the exact processor model into every title and URL, each product page is pre-targeted at the long-tail query a buyer types when comparing boxes on Reddit and YouTube comments. It's the same lesson as every good programmatic catalogue: name the page after the search, not after your internal SKU poetry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The timing is the third thing.&lt;/strong&gt; GMKtec's flagship line is not "fast mini PC" — it's "AI mini PC," rebuilt around Ryzen AI and AI Max+ silicon, with local-LLM-friendly memory configurations at price points far below a comparable workstation. Whether or not local AI demand stays hot, the brand has positioned its highest-margin products on the newest query wave instead of fighting over the old "office mini PC" term. New term, thin competition, hardware that actually fits the query: the same pattern as every good keyword land-grab, executed in physical products.&lt;/p&gt;

&lt;p&gt;What would I copy? The series × platform collection matrix, the spec-sheet naming, and the refusal to split the flagship into a separate "pro" store. What are the risks? A 63-SKU catalogue riding one component cycle — when the chip platform turns, the whole naming and collection structure turns with it — and DTC hardware support costs that a spec sheet can't show you. But as a storefront teardown, gmktec.com is worth an hour of any hardware seller's time: proof that a factory brand with clear taxonomy and search-shaped naming can look, from the customer's side of the glass, like a global brand.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Store checked October 2026: gmktec.com (Shopify), 63 products, $169.99–$6,799.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>indiehacking</category>
      <category>ecommerce</category>
      <category>shopify</category>
      <category>hardware</category>
    </item>
    <item>
      <title>The TCM Graduate at Majuqiao: A Day-Labor Story Followed by Feng Ge</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Mon, 09 Nov 2026 09:22:36 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/the-tcm-graduate-at-majuqiao-a-day-labor-story-followed-by-feng-ge-4op6</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/the-tcm-graduate-at-majuqiao-a-day-labor-story-followed-by-feng-ge-4op6</guid>
      <description>&lt;p&gt;This is not the other Majuqiao story. In the video, the creator Feng Ge spends a day trying day labour in Majuqiao, on the edge of Beijing, and follows a different young man: a graduate from Shanxi who studied traditional Chinese medicine at a vocational college. He did not arrive as a career labourer. He arrived, in the video's account, as a stopgap, hoping to earn some quick money and move on. More than a month later, he was still there, and the video is useful because it shows how a short stopgap can turn into a trap.&lt;/p&gt;

&lt;h2&gt;
  
  
  A 6-yuan bowl outside the sixth ring road
&lt;/h2&gt;

&lt;p&gt;In the video, Feng Ge starts with food. At a roadside stall in Majuqiao, he eats a large bowl of banmian, a hand-pulled noodle dish, for 6 yuan. The portion is generous, and he remarks on the contrast: this is the capital, yet just outside the sixth ring road, a filling meal can cost that little. The price is the first clue to the local economy. Everything in Majuqiao is priced for people who are paid by the day.&lt;/p&gt;

&lt;p&gt;Housing follows the same logic. In the video, shared rental rooms are cut up to the smallest sellable unit: a bunk bed charged by the day, at 15 yuan for an upper bunk and 20 yuan for a lower bunk. In one flat, even the kitchen has been turned into a sleeping room, with beds fitted in and charged at about 30 yuan a day. The rooms shown are cramped and dirty, with poor hygiene. Cheapness here has a floor, and that floor is a bed in a room that was never meant to be a bedroom.&lt;/p&gt;

&lt;h2&gt;
  
  
  The courier maths
&lt;/h2&gt;

&lt;p&gt;Day labour in Majuqiao is not only construction work. In the video, Feng Ge also meets a courier who works on a full-time or part-time basis. The courier's day starts at 6 in the morning at a sorting station. He then delivers 50 to more than 100 parcels a day, earning 3 to 4 yuan per parcel, for a daily income of more than 200 yuan. Days off are very few.&lt;/p&gt;

&lt;p&gt;The video then spells out what it takes to push that income higher. To reach 10,000 yuan a month, the courier would need to deliver more than 130 parcels a day and keep working until 8 or 9 in the evening, pushing daily pay to nearly 400 yuan. That is the top end of the grind, not the normal day. When income falls short, the video records a quieter cost: the courier says a person in that position can barely maintain basic dignity and daily life, let alone think about dating, marriage, or facing family and friends back home.&lt;/p&gt;

&lt;h2&gt;
  
  
  The graduate who came for quick money
&lt;/h2&gt;

&lt;p&gt;The young man at the centre of the video is from Shanxi. In the video, he says he studied traditional Chinese medicine at a vocational college, known in China as a dazhuan. After graduation, his path was blocked in a specific way. To sit the pharmacist examination, he needed three years after graduation, and he could not stay on for an internship at a school hospital. He then tried sales work, but in the video's account he lacked the eloquence the job required and could not meet its performance targets.&lt;/p&gt;

&lt;p&gt;On a friend's suggestion, he came to Majuqiao to earn some quick money as a temporary step. He arrived with just over 3,000 yuan, a small sum that had to last until the next payday, and then the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  One night of work, five days of rest
&lt;/h2&gt;

&lt;p&gt;His first heavy job, in the video, was night-shift parcel sorting at 260 yuan a day. The work meant spending the whole night bent over: unloading vehicles, scanning parcels, and holding bags open for loading. He had never done heavy manual work before. After one night, he was so exhausted that he rested in his dormitory for five full days.&lt;/p&gt;

&lt;p&gt;After food costs, he had saved almost nothing from that shift. Worse, his starting money had gone down, not up: from just over 3,000 yuan to 2,800 yuan. The stopgap was already costing him money.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gown he cannot take off
&lt;/h2&gt;

&lt;p&gt;In the video, the young man puts his dilemma in plain terms. He says a vocational college diploma is in an extremely awkward position in today's society. Decent office work, in his account, is closed to him. Heavy manual work, on the other hand, is work his body cannot easily bear, and the strain is mental as well as physical. He says people without a diploma can at least sell their labour without that extra weight, while he is caught in between.&lt;/p&gt;

&lt;p&gt;This is the "long gown" dilemma in his own framing: a credential that is not enough to open one door, but heavy enough to make the other door harder to walk through. He is not refusing work. He tried the work, paid for it with five days of rest, and came back with less money than he started with.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rules at the bridgehead
&lt;/h2&gt;

&lt;p&gt;Majuqiao's day-labour market has its own unwritten rules, and the video does not soften them. On construction sites, rough scolding and harsh insults from foremen and intermediaries are described as routine, and workers describe their dignity as being trampled. Overtime is not reliably paid: working past the normal end of the day, to 5:30 in the afternoon, does not necessarily bring any extra pay, and wages can be docked on various pretexts.&lt;/p&gt;

&lt;p&gt;Transport is another part of the same pattern. In the video, intermediaries trying to cut costs use vans, including app-based freight vans and mixed cargo-and-passenger vans, to move workers to sites informally. The practice is described in the video as irregular.&lt;/p&gt;

&lt;p&gt;After more than a month in Majuqiao, the young man says in the video that day labour feels meaningless to him, and that he does not belong there. That is not a conclusion drawn by the camera. It is his own stated feeling after weeks of trying to make the stopgap work.&lt;/p&gt;

&lt;h2&gt;
  
  
  A stated hope, not an outcome
&lt;/h2&gt;

&lt;p&gt;What he wants next is also stated clearly in the video, and it should be reported as a hope, not as a result. He has already prepared a passport, and he has passed an intermediate chef certificate examination. His hope is to save enough travel money to work abroad, where he believes pay could be somewhat higher, so that he can support his family and leave Majuqiao behind sooner.&lt;/p&gt;

&lt;p&gt;Nothing in the video, as summarised, says that plan has happened. It is a plan held by a man with 2,800 yuan left, a cooking certificate, a passport, and more than a month of day labour behind him. A 6-yuan bowl and a 15-yuan bunk make Majuqiao survivable for a day. They do not make it a place where a short stopgap easily becomes a way out.&lt;/p&gt;

&lt;p&gt;More from Terry at &lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;Airgrix&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>china</category>
      <category>work</category>
      <category>society</category>
      <category>career</category>
    </item>
    <item>
      <title>A Million in Debt, Three Daughters, and a 25-Kilogram Bumblebee Suit</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Mon, 09 Nov 2026 05:26:00 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/a-million-in-debt-three-daughters-and-a-25-kilogram-bumblebee-suit-4hih</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/a-million-in-debt-three-daughters-and-a-25-kilogram-bumblebee-suit-4hih</guid>
      <description>&lt;p&gt;In the video, a 37-year-old veteran starts his working week in an office and ends it inside a costume. From Monday to Friday, he works at a state-owned company for about 400 dollars a month, a modest and steady wage. On Saturday and Sunday, he puts on a Bumblebee costume, 2.5 metres tall and weighing 25 kilograms, and works events across town. In the video, he says he has kept up this weekend work for eight years, with almost no rest.&lt;/p&gt;

&lt;p&gt;The costume is not a hobby. It is the second half of a plan to pay off a very large debt while supporting three daughters. The youngest is two, and in the video is being looked after by her grandparents back home.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the debt began
&lt;/h2&gt;

&lt;p&gt;In the video, the debt story starts about ten years ago, when he left the military. He received 80,000 yuan as a resettlement payment and put all of it into opening a milk-tea shop. The business grew for a time and expanded to several shops. Then, in his account, a choice about ingredients became a business problem. He says he refused to use inferior ingredients and insisted on buying pure milk and fresh fruit at higher cost. The shops lost money and closed.&lt;/p&gt;

&lt;p&gt;After that, he tried again, and again. In the video, he describes two or three failed ventures in total, and says that within two or three years he had accumulated more than a million yuan in debt. Those numbers are his account in the video, not an audited balance sheet. What is clear is the sequence: a single lump sum, an early expansion, a cost decision he would not reverse, and repeated attempts that left him deeper in debt.&lt;/p&gt;

&lt;p&gt;That sequence explains the double life: a steady weekday job gives the family a floor, even if the pay is low, while weekend costume work offers a chance to move faster than that floor would allow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning to wear 25 kilograms
&lt;/h2&gt;

&lt;p&gt;The costume has its own history in the video. He learned the work in Beijing, introduced by a former squad leader. He paid 10,000 yuan for tuition and 18,000 yuan for his first set of equipment. In the video, he notes that a set can now be bought for only a few thousand yuan. The costume is not powered assistance: it is carried and balanced by the person inside it, and the metal edges rub against his joints over long shifts.&lt;/p&gt;

&lt;p&gt;Eight years of that work has left a record of falls. In the video, he says he has fallen six or seven times because of the weight and balance, and that each time he got up, treated the injury as best he could, and kept working. The suit is also sealed and hot. In winter, his clothes are soaked through. In summer, he says, sweat runs down his legs and fills his shoes. In the video, these are presented as the ordinary cost of the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two gigs in one day
&lt;/h2&gt;

&lt;p&gt;The video follows him through two bookings on a single day. At midday, he works a baby banquet at a high-end restaurant, marking a full-month or first-birthday celebration. His work there is greeting guests, posing for photos, performing and interacting with children and families, and seeing guests off. In the video, that shift lasts four hours of continuous standing work in the costume.&lt;/p&gt;

&lt;p&gt;After that, there is no hot meal and no real break. He moves straight to a shopping mall, where the work changes shape. Instead of one long celebration, he does repeated parade appearances to draw foot traffic, about 20 minutes of costumed walking per hour. The costume is the same, but the rhythm is different: short bursts, repeated, in heat, with the same weight on his shoulders. Together, the two gigs show why the weekend work is tiring in a way that a single hourly rate cannot capture: the weight, the heat, the standing, and the lack of recovery time between bookings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Home, in his own words
&lt;/h2&gt;

&lt;p&gt;The hardest part of the video, for many viewers, will not be the costume. It will be what he says about home. This section must be read carefully, because the video gives his account, not a verified account of both sides. In his words in the video, his wife restricts his social life: bringing people home or going out socially, he says, requires her approval in advance. He says she opposed new projects and wanted him to stay in steady employment, and that she opposed his attempt to appear on camera and make social media videos. He also says that when the film crew visited, she threatened divorce proceedings.&lt;/p&gt;

&lt;p&gt;In the video, he puts the point in his own terms: physical tiredness outside the home, he says, he can accept, but feeling misunderstood, unrecognised, and unsupported at home hurts more. This draft reports that as his feeling and his account, and does not treat it as an established fact about his wife, and does not take sides in a marriage the viewer only sees through one person's words on camera. The video does not settle who is right about money, risk, or family decisions. Its value here is narrower: it shows how financial pressure can turn ordinary disagreements about work and risk into something that feels, to the person carrying the debt, like a second kind of weight.&lt;/p&gt;

&lt;h2&gt;
  
  
  A song written at night
&lt;/h2&gt;

&lt;p&gt;Late at night, after the day's work, he writes. In the video, he turns his frustration, his longing for somewhere farther away, and his refusal to settle for an ordinary life into lyrics, and uses AI to set them to music. The idea of the song, paraphrased briefly, is that he feels trapped where he stands while his body stays silent, and that even if no one understands his ambition, he wants to fly toward a wider horizon and find freedom in singing.&lt;/p&gt;

&lt;p&gt;That song does not solve the debt or change the schedule. In the video, it gives him a place to say, in his own words, what the working day does not allow him to say. The costume makes him visible at events; the song is private work, done at night, for himself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stays with you
&lt;/h2&gt;

&lt;p&gt;Strip away the costume, and the story is a common trade-off made visible: a steady job offers predictability but not enough income, while extra work offers income but takes the weekends, the rest, and, over years, a physical toll. A business built on refusing to cut corners can still fail, leaving a debt that outlasts the business itself.&lt;/p&gt;

&lt;p&gt;That unfinished quality is why the video is worth watching rather than summarising as inspiration. It does not pretend that hard work alone clears a million yuan of debt. It shows a father of three daughters doing a physically demanding weekend job, year after year, while holding a weekday job, and using a song at night to name the part of that life that neither job can express.&lt;/p&gt;

&lt;p&gt;More from Terry at &lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;Airgrix&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>china</category>
      <category>work</category>
      <category>family</category>
      <category>business</category>
    </item>
    <item>
      <title>When Negotiation Fails After a Death at Work: The Order of Things That Actually Helps</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Mon, 09 Nov 2026 00:26:02 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/when-negotiation-fails-after-a-death-at-work-the-order-of-things-that-actually-helps-1lof</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/when-negotiation-fails-after-a-death-at-work-the-order-of-things-that-actually-helps-1lof</guid>
      <description>&lt;p&gt;A question posted on Zhihu in 2021 still reads like a cry for help: a younger brother died suddenly while working at a tech company, and the family's negotiation with the company went nowhere. What do you do then?&lt;/p&gt;

&lt;p&gt;The answers the question received leaned on publicity: find influencers, get the story out, complain to regulators, call television. Publicity is not useless, but it is the wrong first step, and in the worst cases it is a trap. Attention fades. Deadlines do not. When someone dies at work and the employer will not negotiate, the family's real problem is not that nobody is listening. It is that two clocks have already started, and the company knows it.&lt;/p&gt;

&lt;p&gt;This is general information about how the Chinese system works, not legal advice for any specific case. Every case turns on its own facts, and a labour lawyer should be involved early. But the shape of the process is the same in most cases, and knowing the order of it is what keeps a grieving family from being outmanoeuvred.&lt;/p&gt;

&lt;p&gt;The first job is evidence, and it is urgent for a reason nobody wants to hear: the employer controls most of it. Attendance records, overtime logs, internal chat messages, shift schedules, pay slips, the employment contract, medical records, and the death certificate should be copied, photographed, and stored outside the company's systems as soon as possible. Colleagues who witnessed the working hours should be asked, promptly and politely, whether they are willing to put what they saw in writing. Memories harden into silence quickly when a company starts managing the story.&lt;/p&gt;

&lt;p&gt;The second job is understanding the two clocks. Under China's Regulations on Work-Related Injury Insurance, the employer is supposed to apply for a work-injury determination within 30 days of the incident. If the employer does not, the worker's close relatives or the trade union may apply directly within one year. Separately, labour arbitration claims generally carry a one-year limitation period, counted from when the party knew or should have known their rights were infringed. These are different clocks, run by different bodies, and missing either one can close a door that negotiation will never reopen. Note also that when a worker has died, close relatives are the ones who participate in arbitration on the worker's behalf. The system anticipates exactly this situation. It does not require the family to win an argument with the company first.&lt;/p&gt;

&lt;p&gt;The third job is knocking on the right doors, in the right order. A labour dispute goes to the labour inspection authority and the social insurance department for the work-injury determination, and then to the labour dispute arbitration committee if it cannot be settled. Arbitration comes before any court case in this system: it is not an optional extra, it is the mandatory first forum. The business regulator that handles company registrations is not the body that decides labour disputes, and a complaint filed in the wrong place costs weeks. Media attention belongs at the end of this sequence, not the beginning: it is leverage, not a remedy, and it works best when the evidence is already preserved and the formal applications are already filed. A story told before the paperwork exists can be denied, reframed, or simply outlasted.&lt;/p&gt;

&lt;p&gt;The fourth job is the hardest one emotionally: do not sign anything under grief. Companies in these situations often offer a lump sum in exchange for a full waiver of claims, presented as kindness and urgency in the same breath. A waiver signed before the work-injury determination is made can be worth far more to the company than to the family, because the family does not yet know what the formal determination would entitle them to. No legitimate offer evaporates because a family took a week to get independent advice. Any offer that claims otherwise is telling you something about itself.&lt;/p&gt;

&lt;p&gt;Finally, it helps to reframe what "negotiation failed" actually means. It rarely means the company has a strong legal position. More often it means the company has calculated that a grieving family will run out of energy, money, or time before the formal process forces an answer. That calculation is the reason the formal process exists: arbitration committees, work-injury determinations, and labour inspections do not require the employer's goodwill. They require applications, evidence, and persistence, in that order.&lt;/p&gt;

&lt;p&gt;None of this brings anyone back, and no essay should pretend otherwise. But there is a difference between a family that is ignored and a family that is ignored while its paperwork is already moving through the system. The first depends on the company's conscience. The second does not. When negotiation fails after a death at work, the answer is not to shout louder. It is to stop negotiating on the company's timetable, and start moving on the law's.&lt;/p&gt;

&lt;p&gt;I write about work, building, and the systems ordinary people run into at Airgrix (&lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;https://airgrix.com&lt;/a&gt;), where I also run a small independent store.&lt;/p&gt;

</description>
      <category>career</category>
      <category>workplace</category>
      <category>labor</category>
      <category>advice</category>
    </item>
    <item>
      <title>The Laptop That Lied About Its Own Brain: Chuwi's CPU Spoofing Scandal</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Sun, 08 Nov 2026 01:02:48 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/the-laptop-that-lied-about-its-own-brain-chuwis-cpu-spoofing-scandal-366d</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/the-laptop-that-lied-about-its-own-brain-chuwis-cpu-spoofing-scandal-366d</guid>
      <description>&lt;p&gt;A laptop can lie to you in a spec sheet. That's marketing, and we've all learned to discount it. What Chinese budget-laptop brand Chuwi is accused of is something else entirely: a laptop that lies to you &lt;em&gt;inside its own firmware&lt;/em&gt; — a machine that tells Windows, CPU-Z, and HWiNFO it has a newer processor than the silicon actually soldered to its board.&lt;/p&gt;

&lt;p&gt;Here's how the story unfolded, as reported by Notebookcheck after a wave of complaints from CoreBook X owners on Reddit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The chip that wasn't
&lt;/h2&gt;

&lt;p&gt;The CoreBook X was advertised with an AMD Ryzen 5 7430U — a Zen 3 part. Owners who benchmarked their machines found performance that didn't add up, roughly 7% below where a 7430U should land, and closer to 10% once the laptop's single-channel memory held it back further.&lt;/p&gt;

&lt;p&gt;The 7430U and the older Ryzen 5 5500U are, on paper, easy to confuse: both are 6-core, 12-thread parts. But the 5500U is a Zen 2 chip with half the L3 cache. Similar enough that even a knowledgeable buyer could miss the swap — which is presumably the point.&lt;/p&gt;

&lt;p&gt;Every software check came back clean. BIOS said 7430U. Windows said 7430U. CPU-Z and HWiNFO64 — the tools enthusiasts actually trust — said 7430U.&lt;/p&gt;

&lt;p&gt;The silicon itself couldn't lie. Notebookcheck's team pulled the cooler off a unit and read the OPN printed on the chip: &lt;strong&gt;100-000000375&lt;/strong&gt;. AMD's own documentation maps that code to the Ryzen 5 5500U. The 7430U's OPN is a different number entirely. Chuwi hadn't just shipped the wrong chip — the evidence points to firmware modified to report the wrong identity, so that no software tool a customer could run would ever reveal it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The response made it worse
&lt;/h2&gt;

&lt;p&gt;Chuwi neither admitted nor denied the allegation. Its statement leaned on "different production batches" and noted that remaining stock already in circulation is outside its direct control, while saying an internal investigation is underway.&lt;/p&gt;

&lt;p&gt;Consider what that defense concedes. Swapping a component because of a supply shortage is an industry sin, but a survivable one — &lt;em&gt;if you disclose it&lt;/em&gt;. Firmware-level identity spoofing is not a production accident. Somebody had to write that code, flash it, and ship it. A batch mix-up explains the wrong chip. It does not explain the wrong chip that introduces itself under a false name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond one laptop brand
&lt;/h2&gt;

&lt;p&gt;I run a small e-commerce business, and I read stories like this from the seller's side of the counter. The economics are obvious: a Zen 2 part is cheaper, the two chips look identical in a listing, and almost nobody benchmarks a budget laptop against a reference table. The fraud only needed to survive until the return window closed.&lt;/p&gt;

&lt;p&gt;But the cost calculus ignores what trust is actually worth. Chuwi spent a decade building a reputation as the honest budget option — the brand reviewers recommended when money was tight. That reputation was the entire business. A few dollars saved per unit just bought the destruction of it, plus a recall (reportedly limited to purchases before May 31, 2026, and excluding the Ubox line — details affected owners should verify against Chuwi's own notices, since the company's public response has been vague).&lt;/p&gt;

&lt;p&gt;Three lessons I'm taking from this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Software identity is not identity.&lt;/strong&gt; If a spec really matters, the physical marking outranks every dashboard. The people who caught this didn't run better software — they removed a heatsink.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Undisclosed substitution is a choice, not an accident.&lt;/strong&gt; Supply chains fail everyone. The brands that survive it are the ones that print the change on the box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A non-denial is a data point.&lt;/strong&gt; "Different batches" plus "stock outside our control" plus "internal investigation" is what a company says when the physical evidence is already public and undeniable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The investigation is ongoing and Chuwi may yet produce a fuller explanation. I'll update if it does. Until then, if you own a CoreBook X or CoreBook Plus, the honest check takes ten minutes and a screwdriver: read the OPN on the chip and compare it with AMD's list. Don't ask the laptop. It's been taught what to say.&lt;/p&gt;

&lt;p&gt;— Terry, writing at &lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;airgrix.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>hardware</category>
      <category>business</category>
      <category>tech</category>
    </item>
    <item>
      <title>God-Tier Python: Extracting YouTube Channel Business Emails Without Touching the CAPTCHA</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Sat, 07 Nov 2026 02:41:46 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/god-tier-python-extracting-youtube-channel-business-emails-without-touching-the-captcha-5aeb</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/god-tier-python-extracting-youtube-channel-business-emails-without-touching-the-captcha-5aeb</guid>
      <description>&lt;p&gt;When scraping business inquiry emails from YouTube channels, there's a core technical gap in the industry: YouTube's official "About / View Email Address" button is guarded by Google reCAPTCHA v3/Enterprise.&lt;/p&gt;

&lt;p&gt;If you brute-force it with front-end automation (Selenium/Playwright), you don't just risk Cloudflare/Google risk-control bans — the per-solve cost is high and the speed is painfully slow.&lt;/p&gt;

&lt;p&gt;The genuinely industrial-grade approach is asymmetric, multi-channel extraction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel 1: InnerTube hidden metadata + long-text regex (no login, no CAPTCHA).&lt;/strong&gt; Using YouTube's mobile/lightweight client signatures (ANDROID / WEB), pull the channel's about/description, pinned comments and external link set directly. More than 80% of small and mid-sized creators, to make business cooperation easy, post their email in plaintext in their bio, a pinned comment, or their Linktree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel 2: Cross-domain crawling of the linked matrix.&lt;/strong&gt; If the bio has no plaintext email, the script follows the channel's external links (personal website, Shopify, Linktree, Twitter/X) and asynchronously mines those second-level landing pages for business emails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel 3: A zero-dependency async architecture against anti-scraping.&lt;/strong&gt; Pure asyncio + httpx, no heavy headless browser — a single machine can scan dozens of channels per second.&lt;/p&gt;

&lt;p&gt;Here is a complete, battle-tested advanced async scanner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urlparse&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;

&lt;span class="n"&gt;EMAIL_REGEX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IGNORECASE&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Exclude common static-asset fake emails
&lt;/span&gt;&lt;span class="n"&gt;INVALID_EXTENSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpeg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.gif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.webp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.svg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.css&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.js&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;EXCLUDED_EMAILS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;support@youtube.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;privacy@google.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept-Language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en-US,en;q=0.9&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clean_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_emails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw_emails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;INVALID_EXTENSIONS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;EXCLUDED_EMAILS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;YouTubeChannelLeadExtractor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Semaphore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;12.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;follow_redirects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_fetch_external_site_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Shallow-scan a Linktree, personal site or Shopify page for a contact email&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;urlparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;netloc&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instagram.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tiktok.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;facebook.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

            &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;EMAIL_REGEX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_from_channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Reverse-parse a single channel page automatically&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;target_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;channel_url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rstrip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/about&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;channel_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;channel_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;channel_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_links&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

                &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

                &lt;span class="c1"&gt;# 1. Grab the ytInitialData context variable (YouTube's first-screen JSON)
&lt;/span&gt;                &lt;span class="n"&gt;json_match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;var ytInitialData\s*=\s*({.+?});&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;json_match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;json_match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;window\[\"ytInitialData\"\]\s*=\s*({.+?});&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;json_match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

                    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;channel_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;channelMetadataRenderer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                        &lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="k"&gt;pass&lt;/span&gt;

                    &lt;span class="n"&gt;raw_data_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;found_redirect_links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/redirect\?event=channel_description[^\"\s]+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;raw_data_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r_link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;found_redirect_links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;match_q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[?&amp;amp;]q=([^&amp;amp;]+)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r_link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match_q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                            &lt;span class="n"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match_q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                            &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="n"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;decoded&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_links&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                            &lt;span class="p"&gt;):&lt;/span&gt;
                                &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_links&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c1"&gt;# 2. Strategy A: regex the HTML and description metadata directly
&lt;/span&gt;                &lt;span class="n"&gt;direct_emails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EMAIL_REGEX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;clean_direct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;clean_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;direct_emails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;clean_direct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean_direct&lt;/span&gt;
                    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Channel Description / Metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

                &lt;span class="c1"&gt;# 3. Strategy B: if no plaintext in the bio, deep-scan external links concurrently
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_links&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                    &lt;span class="n"&gt;scan_tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_fetch_external_site_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_links&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# first 3 links only
&lt;/span&gt;                    &lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="n"&gt;external_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;scan_tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;combined_external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
                    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;emails&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;external_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;combined_external&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                    &lt;span class="n"&gt;clean_external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;clean_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;combined_external&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;clean_external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean_external&lt;/span&gt;
                        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;External Links (Website/Linktree)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aclose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="c1"&gt;# ==================== Test run ====================
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Supports handle URLs and channel-ID URLs
&lt;/span&gt;    &lt;span class="n"&gt;test_channels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/@mkbhd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/@LinusTechTips&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/@ExplosionExplosive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;extractor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;YouTubeChannelLeadExtractor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;extractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract_from_channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;test_channels&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;leads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;extractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;leads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why does this beat the traditional approach in real projects?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It sidesteps the un-bypassable reCAPTCHA lock: the official hidden-email button has a strict daily view limit per IP and account (roughly 10–20 views), so hard-attacking the CAPTCHA with code is high cost, low return.&lt;/p&gt;

&lt;p&gt;It hits the real business path: over 75% of YouTubers with mature cooperation intent write something like "Business inquiries: &lt;a href="mailto:colab@brand.com"&gt;colab@brand.com&lt;/a&gt;" right in their channel bio, or hang it on their Linktree / personal site homepage.&lt;/p&gt;

&lt;p&gt;It's a zero-rendering fast stream: compared with spinning up Chromium instances, pure-text JSON matching responds in around 300ms — perfect for chaining into a Reddit/backlink outreach pipeline and quickly building an overseas creator-cooperation database.&lt;/p&gt;

&lt;p&gt;— Terry, &lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;Airgrix&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>youtube</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>《For Blood and Money》：伊布替尼、Bob Duggan 与 210 亿美元的并购心理战</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Wed, 04 Nov 2026 13:23:33 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/-yi-bu-ti-ni-bob-duggan-yu-210-yi-mei-yuan-de-bing-gou-xin-li-zhan-3mo3</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/-yi-bu-ti-ni-bob-duggan-yu-210-yi-mei-yuan-de-bing-gou-xin-li-zhan-3mo3</guid>
      <description>&lt;p&gt;Nathan Vardi 在《For Blood and Money》中最为迷人的地方，恰恰在于&lt;strong&gt;把金融教科书里抽象的“资本运作”、“期权定价”和“并购溢价”，还原成了充满偏执、背叛、赌博与算计的真实肉搏细节&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;围绕你提到的三大维度，书中记录了大量极其硬核且戏剧性的幕后细节：&lt;/p&gt;




&lt;h3&gt;
  
  
  一、 知识产权淘金：从垃圾堆里捡出百亿分子
&lt;/h3&gt;

&lt;p&gt;伊布替尼（Ibrutinib）并不是在顶级跨国药企的重点实验室里众星捧月诞生的，它的前身是一笔被大药企抛弃的边缘资产。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Celera 的“边角料”清仓（几百万美元的捡漏）&lt;/strong&gt;：&lt;/li&gt;
&lt;li&gt;人类基因组测序先驱 Craig Venter 创办的 Celera 公司，为了削减研发开支断臂求生，准备将一批处于早期、前景不明的化合物打包贱卖。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;当时处于破产边缘的 Pharmacyclics 凭借极低的代价（仅约 &lt;strong&gt;600 万美元首付 + 部分股权与未来里程碑付款&lt;/strong&gt;）接盘了包括一系列激酶抑制剂在内的化合物库。这批被 Celera 科学家认为“毒性不可控”或“开发价值低”的分子中，就藏着代号为 &lt;strong&gt;PCI-32765&lt;/strong&gt; 的化合物——也就是后来的伊布替尼。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;共价结合（Covalent Binding）的技术赌博&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;当时大药企的主流化学界极其歧视“不可逆共价结合抑制剂”（认为这会导致不可逆的脱靶毒性，容易把病人吃出肝肾衰竭）。但 Pharmacyclics 的化学家与顾问发现，这个分子能精准地与 BTK 蛋白的 Cys-481 位点紧密锁定，靶向极高。这在学术界被视作“异端邪说”的机制，正是它后来成为超级重磅炸弹（Blockbuster）的核心专利壁垒。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;出走与复仇：Acerta 与第二代分子的诞生&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;参与过 Pharmacyclics 早期研发与运营的几位核心科学家和高管后来离开并创办了 &lt;strong&gt;Acerta Pharma&lt;/strong&gt;。他们太清楚伊布替尼的第一代缺陷了（脱靶引起房颤、出血、腹泻）。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;他们精准地针对伊布替尼的弱点，设计出了选择性更高、脱靶更少的第二代 BTK 抑制剂——&lt;strong&gt;阿卡替尼（Acalabrutinib, ACP-196）&lt;/strong&gt;。这是 Biotech 领域最经典的“专利围剿战”：原班人马利用对一代靶点的深刻理解，迅速卡位二代专利，硬生生从第一代巨头嘴里撕开百亿市场。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  二、 催化剂与人性的张力：疯狂赌徒 Bob Duggan 的“单吊梭哈”
&lt;/h3&gt;

&lt;p&gt;书中最具传奇色彩的主角是 &lt;strong&gt;Bob Duggan&lt;/strong&gt;。他不是医药科学家，甚至不是传统华尔街投行家，而是一个信奉山达基教（Scientology）、靠做曲奇饼干、滑板（Santa Cruz Skateboards）和电脑配件发家的激进连续创业者。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;门口的野蛮人强行夺权&lt;/strong&gt;：&lt;/li&gt;
&lt;li&gt;2008 年金融危机期间，Pharmacyclics 的前主力抗癌药（Xcytrin）在 FDA 遭遇惨败，股价跌到 1 美元以下，濒临退市破产。原管理层和科学家绝望甚至放弃。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;此时持有大量股份的 Duggan 暴力清洗了董事会，赶走原创始人兼 CEO Richard Miller，自己这个“医药门外汉”直接登基担任 CEO。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;极端的仓位管理（集中下注与反常识执念）&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;传统分散风险的投资法则在 Duggan 这里完全失效。在所有机构投资人都避之不及的时候，Duggan 动用个人全部身家，在公开市场几毛钱、一块钱疯狂扫货，最终个人持股比例高达惊人的 &lt;strong&gt;15%~20%&lt;/strong&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;他砍掉公司所有其他杂项研发，把所有宝贵现金流全部推到 PCI-32765 的临床试验上。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;临床催化剂读出时的生死时速&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;书中生动描绘了俄亥俄州立大学的 John Byrd 医生给 CLL（慢性淋巴细胞白血病）晚期患者用药的场景：那些淋巴结肿大如葡萄柚、传统化疗已宣告死刑的临终病人，在服药几天到几周后，巨大的肿瘤肉眼可见地迅速软化、消退。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;催化剂公布前夕，空头（Short Sellers）在华尔街疯狂散播流言，认为共价抑制剂必然爆雷；而在 ASCO（美国临床肿瘤学会）年会和 ASH（美国血液学会）年会数据发布的一瞬间，股价像火箭一样垂直拉升。每次关键 Phase 1/2 队列数据的更新，都是一次翻倍级的重定价（Re-rating）。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  三、 并购心理战：AbbVie 210 亿美元的世纪截杀
&lt;/h3&gt;

&lt;p&gt;书的后半段高潮，把&lt;strong&gt;药企面临专利悬崖时的焦虑&lt;/strong&gt;与&lt;strong&gt;创始人的心理博弈&lt;/strong&gt;写成了谍战小说：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;修美乐（Humira）的千亿达摩克利斯之剑&lt;/strong&gt;：&lt;/li&gt;
&lt;li&gt;&lt;p&gt;艾伯维（AbbVie）当时的年营收极其严重地依赖全球“药王”修美乐（占比超过 60%）。修美乐的专利悬崖近在眼前，一旦生物类似药入局，AbbVie 的营收将面临断崖式暴跌。CEO Rick Gonzalez 迫切需要一个能每年贡献 50 亿至 100 亿美元的巨无霸产品来填补窟窿。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;拍卖场上的三国杀：强生 vs 艾伯维&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;强生（J&amp;amp;J）原本是 Pharmacyclics 的早期商业化合作方（早已拥有伊布替尼的非美权益，并共同分担研发费用）。强生原本以为自己胜券在握，自恃近水楼台，给出了非常自负的报价（约 170 亿至 180 亿美元现金/股票）。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duggan 极其敏锐地抓住了 AbbVie 的“生存焦虑”，故意在两个巨头之间制造竞价焦虑。他暗示 AbbVie：&lt;em&gt;如果强生拿下了全部权益，你们的肿瘤管线将被彻底封锁。&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;百亿美元溢价的最后几小时&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;2015 年 3 月的一个深夜，AbbVie 的管理层和投行顾问在酒店里通宵博弈。最终，为了确保一击必杀、彻底粉碎强生的匹配可能，AbbVie 砸出了惊天动地的 &lt;strong&gt;210 亿美元（现金 + 股票）&lt;/strong&gt;，较 Pharmacyclics 当时的市值溢价近一倍。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;强生的高管得知最终成交价时彻底目瞪口呆，直接退出了竞价——他们认为 AbbVie 已经“疯了”。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;结果证明，Bob Duggan 凭这一役个人净赚超 &lt;strong&gt;30 亿美元&lt;/strong&gt;，从一个卖滑板的外行，一跃成为福布斯富豪榜上的医药资本传奇。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Acerta 的镜像结局：阿斯利康的防守型收购&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;随后不久，英国巨头阿斯利康（AstraZeneca）为了不在这场 BTK 盛宴中彻底掉队，以 40 亿美元（先期支付 25 亿买下 55% 股权 + 后期完成收购）的估值拿下了 Acerta Pharma 和阿卡替尼。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;同样是几十人规模的轻资产团队，同样只跑通了核心分子的早期/中期临床，甚至还没建自己的商业化销售铁军，就直接打包套现离场。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  这本书揭示的底层冷酷法则
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Biotech 没有中间态&lt;/strong&gt;：&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在这里，没有稳健的 8% 年化收益。要么是 &lt;code&gt;0&lt;/code&gt;（临床毒性超标/疗效不达终点，资产直接清零），要么是 &lt;code&gt;10x ~ 100x&lt;/code&gt;（改写标准治疗方案，巨头不计代价溢价抢购）。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;科学家的软肋与资本狂人的残酷&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;真正发现分子、在实验室熬夜验证机制的底层化学家与生物学家，往往在几轮稀释与重组中只分到了极微小的碎屑；而承担了破产归零风险、在资本市场上合纵连横的对冲基金、激进投资者（如 Duggan）和投行掮客，卷走了 90% 以上的资本红利。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;并购是“买时间”，而非买厂房&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;为什么巨头愿意为几张专利和临床数据掏出 210 亿美元？因为&lt;strong&gt;临床试验要跑 7-10 年，专利保护期却在一天天倒计时&lt;/strong&gt;。自研不仅概率极低，更重要的是巨头等不起。溢价购买的本质，是在专利悬崖崩塌之前，用巨额纸币向 Biotech 赌徒们购买“已经被验证过的确定性时间”。&lt;br&gt;
作者：Terry Note — &lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;https://airgrix.com&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>books</category>
      <category>finance</category>
      <category>biotech</category>
      <category>startup</category>
    </item>
    <item>
      <title>The Localization Arbitrage: How CalBuddy Turned an American App Idea Into $81K a Month in Israel</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Wed, 04 Nov 2026 00:40:32 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/the-localization-arbitrage-how-calbuddy-turned-an-american-app-idea-into-81k-a-month-in-israel-hfh</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/the-localization-arbitrage-how-calbuddy-turned-an-american-app-idea-into-81k-a-month-in-israel-hfh</guid>
      <description>&lt;p&gt;Tomer Cnaan did not invent anything. That is precisely the point of his story.&lt;/p&gt;

&lt;p&gt;He was listening to a podcast interview with Zach Yadegari, the teenage founder of Cal AI — the American app that estimates calories from a photo of your meal and was, at the time, doing over a million dollars a month in the US. Tomer's thought was not "I should compete with that." It was: "This does not exist in Israel yet."&lt;/p&gt;

&lt;p&gt;So he built CalBuddy: the same core interaction — photograph your food, get calories and macros back — but Hebrew-first, tuned to Israeli cuisine, Israeli language, and Israeli users. According to Tomer's own account in a Starter Story interview (founder-reported figures, not audited), the numbers went like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;June 2025:&lt;/strong&gt; launch. First month: about &lt;strong&gt;$1,028&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Month four:&lt;/strong&gt; roughly &lt;strong&gt;$20,000 a month&lt;/strong&gt;, driven by paid ads. His edge was boring and decisive — Israeli ad inventory was far cheaper than US ad inventory, and he studied both the winning American calorie-app creatives and high-performing local fitness content before spending.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;April 2026:&lt;/strong&gt; over &lt;strong&gt;$81,000 in a single month&lt;/strong&gt; — an annual run rate around a million dollars, inside a year.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The jump from $20K to $80K did not come from more ads. Tomer brought in two well-known local fitness faces as partners on a revenue-share deal — reported as a 50/50 split. They supplied the two things a cloned product cannot copy: local trust and local distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What he actually copied — and what he didn't
&lt;/h2&gt;

&lt;p&gt;The feature was copied, and the feature is the least valuable part. Photo-in, calories-out is a commodity interaction now; any competent builder with an AI coding tool (Tomer built with Cursor) can reproduce it in weeks.&lt;/p&gt;

&lt;p&gt;What he built himself was the commercial system around it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A real local food model.&lt;/strong&gt; An AI tracker that misreads the dishes people actually eat is useless. Local cuisine was not a translation task; it was the product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheaper attention.&lt;/strong&gt; The same ad playbook that costs a fortune in the US ran at a fraction of the price in a smaller market.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distribution with skin in the game.&lt;/strong&gt; Revenue-share partners promote like owners, because they are.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Meanwhile the original kept compounding: Cal AI itself went on to be acquired by MyFitnessPal, announced in March 2026, after passing a reported $30–50 million in annual revenue. The pioneer got the exit. The localizer got a million-dollar run rate in a country of ten million people. Both outcomes came from the same interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  The transferable lesson
&lt;/h2&gt;

&lt;p&gt;Most builders ask: "What new thing can I make?" Tomer asked a better question: "What already works somewhere else, that my market does not have yet?"&lt;/p&gt;

&lt;p&gt;An idea that is old in one market can be brand new in another. Demand proven in one geography does not lock the rest of the map. The moat is not the idea and not even the code — it is how deeply you localize: language, food, media prices, and faces people trust.&lt;/p&gt;

&lt;p&gt;You do not always need an original idea. Sometimes you need a passport for one.&lt;/p&gt;

&lt;p&gt;— Terry, &lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;Airgrix&lt;/a&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>ai</category>
      <category>indiehackers</category>
      <category>ios</category>
    </item>
    <item>
      <title>The Most Profitable Indie Projects Are the Ones You Can't See</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Tue, 03 Nov 2026 12:19:08 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/the-most-profitable-indie-projects-are-the-ones-you-cant-see-1i27</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/the-most-profitable-indie-projects-are-the-ones-you-cant-see-1i27</guid>
      <description>&lt;p&gt;If you want to understand where the money in indie software actually goes, do not look at the leaderboards. Look at the projects that are not on them.&lt;/p&gt;

&lt;p&gt;That is the lesson from a small data exercise by Jason Zhu, who pulled every project listed on TrustMRR.com through its official API: all 11,303 of them. TrustMRR is a directory where small software projects report their revenue, and where some projects choose to hide their listings from public view. Comparing the hidden ones against the public ones produces a picture that contradicts almost everything the public lists suggest.&lt;/p&gt;

&lt;p&gt;Start with the headline numbers. Hidden projects are a small minority: 919 out of 11,303, or 8.1 percent. But over the last 30 days, those hidden projects took in 24.2 percent of all revenue on the platform, $10.37 million against $32.53 million for the public ones. The median hidden project earned $372 in the last 30 days. The median public project earned zero. Read that again: the typical project you can see makes nothing, while the typical project you cannot see makes something. Any analysis built only on public listings is not just incomplete. It is pointed in the wrong direction.&lt;/p&gt;

&lt;p&gt;The skew gets stronger as revenue rises. Among projects earning more than $10,000 in the last 30 days, 35.1 percent are hidden. Among the top 100 projects by revenue, 41 are hidden. The richer the project, the more likely its owner has decided you should not know about it. This is not a rounding error. It is a behaviour pattern, and it should change how you read every "top indie projects" list you have ever skimmed. Those lists are not a map of the market. They are a map of the market's least successful segment plus a few exceptions that did not bother to hide.&lt;/p&gt;

&lt;p&gt;The strangest finding concerns the projects that do not even fill in a category. Among uncategorised projects, 34.5 percent are hidden, yet that hidden minority takes 79.9 percent of the group's revenue. Think about what that means. The most lucrative hidden projects are not merely private. They are undescribed. They do not tell you what they do, what niche they serve, or what category they belong to. If you are hunting for opportunities by browsing categories, the best opportunities have removed themselves from your search path entirely. Among projects that do list a category, mobile apps hide at the highest rate, 16.2 percent, which fits the pattern: app store competition is visible and copyable, so the incentive to stay quiet is higher.&lt;/p&gt;

&lt;p&gt;The data also covers projects that are for sale, and here the pricing tells its own story. The median asking price is 2.3 times annual revenue. But the multiple depends sharply on size. Projects earning under $1,000 a month ask 4.6 times annual revenue. Projects between $1,000 and $10,000 a month ask about 2.0 times. Projects above $10,000 a month ask only 1.8 times. Small sellers demand the highest multiples, which looks backwards until you think about who is buying. A tiny project is cheap in absolute terms, so a high multiple still means a small cheque, and the seller is pricing in hope: the buyer might grow it. A large project is priced by investors who do the maths. If you ever consider buying a small project, that 4.6x figure is not a bargain or a rip-off on its own. It is the market telling you that small-project prices are set by optimism, not by cash flow.&lt;/p&gt;

&lt;p&gt;Jason Zhu's earlier post in the same thread adds a diagnostic worth keeping. A product whose revenue keeps declining is usually facing one of two things: demand is shrinking, or competition is intensifying. That sounds obvious, but it is a useful filter. Founders love a third explanation, usually involving marketing or timing or a feature that will fix everything. The data rarely supports the third explanation. When the line slopes down for long enough, the market is telling you something, and the honest move is to listen.&lt;/p&gt;

&lt;p&gt;He ends with a question he leaves open: why do owners hide at all? The data cannot answer it, but the plausible reasons are worth listing, because each one implies a different strategy. Some owners hide to avoid copycats in a niche where the idea is the whole moat. Some hide because their employer does not know about the side project. Some hide while preparing a sale, keeping the numbers out of competitors' hands. And some hide simply because they do not want the attention. If you are building something yourself, the question is worth asking in reverse: at what revenue level would you hide, and what would you be protecting? The answer tells you what your real moat is. If hiding protects nothing, you may not have one.&lt;/p&gt;

&lt;p&gt;Three practical takeaways follow. First, treat every public indie leaderboard as a biased sample. The absence of competitors in a niche you are browsing proves nothing, because the winners in that niche may be hidden by choice. Second, if you evaluate projects to buy, anchor on the size-adjusted multiple: around 2x annual revenue for a real business, higher only if you are explicitly paying for potential rather than cash flow. Third, declining revenue deserves a blunt diagnosis before it gets a marketing budget. Check whether demand is shrinking or competitors are multiplying, and act on whichever answer the evidence supports.&lt;/p&gt;

&lt;p&gt;None of this data is mine, and I have not independently verified TrustMRR's raw figures; the numbers here are Jason Zhu's API pull, reported as he published them. But the pattern is robust enough to act on even with that caveat, because it does not depend on any single number being exact. It depends on the direction of the skew, and the skew is large: a small hidden minority taking a quarter of the money, with the share rising as revenue rises. The indie world you can see is the tip of an iceberg, and the part below the waterline is where most of the money sits.&lt;/p&gt;

&lt;p&gt;I write about indie building, data, and the business behind small software over at Airgrix (&lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;https://airgrix.com&lt;/a&gt;), where I also run a small independent store.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>indiedev</category>
      <category>data</category>
      <category>business</category>
    </item>
    <item>
      <title>Paper-Grade Figures, Drawn by an Agent: figures4papers</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Tue, 03 Nov 2026 02:40:06 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/paper-grade-figures-drawn-by-an-agent-figures4papers-53np</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/paper-grade-figures-drawn-by-an-agent-figures4papers-53np</guid>
      <description>&lt;p&gt;I've actually needed to draw decent-looking infographics myself. I wrote a lot of "recipe" prompts for AI to do it, and I even run a related SaaS site.&lt;/p&gt;

&lt;p&gt;Then, a few days ago while browsing GitHub, I came across a really nice repo. It's full of scripts — and a skill — for drawing publication-grade figures. It's developed and maintained by a Chinese student studying overseas, and it's called &lt;strong&gt;figures4papers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;GitHub repo: &lt;a href="https://github.com/ChenLiu-1996/figures4papers" rel="noopener noreferrer"&gt;https://github.com/ChenLiu-1996/figures4papers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd known another good skill before this one, called vivid-figures-skill.&lt;/p&gt;

&lt;p&gt;Using figures4papers is dead simple. You don't even need to download anything — just send the repo link to your agent and tell it to go make the figure.&lt;/p&gt;

&lt;p&gt;It's genuinely useful — real research productivity. And honestly it's nicer than the vivid one, at least in terms of aesthetics.&lt;/p&gt;

&lt;p&gt;Back in the pre-AI era, the illustrations in a paper cost a lot of money if you hired a professional to make them, and a huge amount of effort if you did them yourself (and in the end you'd usually hire someone anyway — because you can copy a figure's layout, but good taste is much harder to copy).&lt;/p&gt;

&lt;p&gt;Written by Terry, who also runs Airgrix, an airsoft gear store at &lt;a href="https://airgrix.com" rel="noopener noreferrer"&gt;https://airgrix.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>research</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Gas vs CO2 vs Electric Airsoft: Which Power System Wins? (In 200 Words)</title>
      <dc:creator>doogee “doogeetop” top</dc:creator>
      <pubDate>Tue, 03 Nov 2026 00:47:18 +0000</pubDate>
      <link>https://dev.to/doogee_doogeetoptop_1e/gas-vs-co2-vs-electric-airsoft-which-power-system-wins-in-200-words-1ohm</link>
      <guid>https://dev.to/doogee_doogeetoptop_1e/gas-vs-co2-vs-electric-airsoft-which-power-system-wins-in-200-words-1ohm</guid>
      <description>&lt;p&gt;Three ways to power an airsoft gun — here is the whole argument in 200 words.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Green gas&lt;/strong&gt; is the realism king. Gas blowback guns kick, cycle, and lock back on empty like the real thing. The price: performance swings with temperature, magazines are expensive, and you will maintain seals and valves forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CO2&lt;/strong&gt; is the dependable brawler. Cartridges deliver consistent, punchy shots and keep working in cold weather that cripples green gas. The price: higher stress on internals, a cost per cartridge that adds up, and many models shoot too hot for some fields out of the box.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Electric (AEG)&lt;/strong&gt; is the rational default. Cheap to run, consistent shot after shot, enormous upgrade ecosystem, no gas to buy. The price: a trigger and a whir instead of recoil — efficient, but soulless for players chasing realism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The verdict:&lt;/strong&gt; choose by what you play. Realism and feel → green gas. Cold weather and raw consistency → CO2. Cost per trigger pull and reliability across a whole season → electric. Most collections end up owning all three, one for each mood.&lt;/p&gt;

&lt;p&gt;The full 6,000-word breakdown — cost tables, cold-weather data, maintenance schedules — is here: &lt;a href="https://airgrix.com/blogs/news/gas-vs-co2-vs-electric-airsoft" rel="noopener noreferrer"&gt;Gas vs CO2 vs Electric Airsoft: Which Power System Wins?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;— Terry&lt;/p&gt;

</description>
      <category>airsoft</category>
      <category>gaming</category>
      <category>guide</category>
      <category>comparison</category>
    </item>
  </channel>
</rss>
